WorldOctTree optimization + more logging
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2025-03-30 16:03:21 -04:00
parent 0a3fbb8e27
commit 86b0de24e6
6 changed files with 54 additions and 27 deletions

View File

@ -1391,6 +1391,7 @@ ServerGroundMovementTree concurrent modify fix
TransvoxelModelGeneration allocation reduction TransvoxelModelGeneration allocation reduction
More allocation reduction More allocation reduction
Vector pooling Vector pooling
Simplify WorldOctTree to reduce lag with large node counts

View File

@ -640,10 +640,14 @@ public class ClientDrawCellManager {
this.recursivelyDestroy(node); this.recursivelyDestroy(node);
//perform op //perform op
Globals.profiler.beginCpuSample("ClientDrawCellManager.join - Perform Op");
DrawCell newLeafCell = DrawCell.generateTerrainCell(node.getMinBound(),node.getData().lod); DrawCell newLeafCell = DrawCell.generateTerrainCell(node.getMinBound(),node.getData().lod);
Globals.profiler.beginCpuSample("ClientDrawCellManager.join - Perform Op - Tree join");
WorldOctTreeNode<DrawCell> newLeaf = chunkTree.join(node, newLeafCell); WorldOctTreeNode<DrawCell> newLeaf = chunkTree.join(node, newLeafCell);
Globals.profiler.endCpuSample();
newLeaf.getData().transferChunkData(node.getData()); newLeaf.getData().transferChunkData(node.getData());
newLeaf.getData().setHasGenerated(false); newLeaf.getData().setHasGenerated(false);
Globals.profiler.endCpuSample();
//update neighbors //update neighbors
this.conditionalUpdateAdjacentNodes(newLeaf, newLeaf.getLevel()); this.conditionalUpdateAdjacentNodes(newLeaf, newLeaf.getLevel());

View File

@ -92,6 +92,7 @@ public class AssetManager {
public void loadAssetsInQueue(){ public void loadAssetsInQueue(){
//models //models
LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load models"); LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load models");
Globals.profiler.beginCpuSample("AssetManager.loadAssetsInQueue - Load Models");
for(String currentPath : modelsInQueue){ for(String currentPath : modelsInQueue){
modelsInQueue.remove(currentPath); modelsInQueue.remove(currentPath);
AIScene aiScene = ModelLoader.loadAIScene(currentPath); AIScene aiScene = ModelLoader.loadAIScene(currentPath);
@ -113,22 +114,28 @@ public class AssetManager {
} }
} }
} }
Globals.profiler.endCpuSample();
//textures from disk to gpu //textures from disk to gpu
LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load textures"); LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load textures");
Globals.profiler.beginCpuSample("AssetManager.loadAssetsInQueue - Load textures");
for(String currentPath : texturesInQueue){ for(String currentPath : texturesInQueue){
texturesInQueue.remove(currentPath); texturesInQueue.remove(currentPath);
texturesLoadedIntoMemory.put(currentPath, new Texture(Globals.renderingEngine.getOpenGLState(), currentPath)); texturesLoadedIntoMemory.put(currentPath, new Texture(Globals.renderingEngine.getOpenGLState(), currentPath));
} }
Globals.profiler.endCpuSample();
//audio from disk //audio from disk
LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load audio"); LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load audio");
Globals.profiler.beginCpuSample("AssetManager.loadAssetsInQueue - Load audio");
if(Globals.audioEngine != null && Globals.audioEngine.initialized()){ if(Globals.audioEngine != null && Globals.audioEngine.initialized()){
for(String currentPath : audioInQueue){ for(String currentPath : audioInQueue){
audioInQueue.remove(currentPath); audioInQueue.remove(currentPath);
audioLoadedIntoMemory.put(currentPath, new AudioBuffer(currentPath)); audioLoadedIntoMemory.put(currentPath, new AudioBuffer(currentPath));
} }
} }
Globals.profiler.endCpuSample();
//shaders //shaders
LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load shaders"); LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load visual shaders");
Globals.profiler.beginCpuSample("AssetManager.loadAssetsInQueue - Load visual shaders");
for(ActorShaderMask currentShader : shadersInQueue){ for(ActorShaderMask currentShader : shadersInQueue){
shadersInQueue.remove(currentShader); shadersInQueue.remove(currentShader);
String key = getShaderKey(currentShader.getVertexShaderPath(),currentShader.getFragmentShaderPath()); String key = getShaderKey(currentShader.getVertexShaderPath(),currentShader.getFragmentShaderPath());
@ -137,8 +144,10 @@ public class AssetManager {
VisualShader.loadSpecificShader(currentShader.getVertexShaderPath(),currentShader.getFragmentShaderPath()) VisualShader.loadSpecificShader(currentShader.getVertexShaderPath(),currentShader.getFragmentShaderPath())
); );
} }
Globals.profiler.endCpuSample();
//compute shaders //compute shaders
LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load compute shaders"); LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load compute shaders");
Globals.profiler.beginCpuSample("AssetManager.loadAssetsInQueue - Load compute shaders");
for(String computePath : computeShadersInQueue){ for(String computePath : computeShadersInQueue){
computeShadersInQueue.remove(computePath); computeShadersInQueue.remove(computePath);
String key = getComputeShaderKey(computePath); String key = getComputeShaderKey(computePath);
@ -151,15 +160,19 @@ public class AssetManager {
e.printStackTrace(); e.printStackTrace();
} }
} }
Globals.profiler.endCpuSample();
//pose models //pose models
LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load pose models"); LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load pose models");
Globals.profiler.beginCpuSample("AssetManager.loadAssetsInQueue - Load pose models");
for(String currentPath: poseModelsInQueue){ for(String currentPath: poseModelsInQueue){
poseModelsInQueue.remove(currentPath); poseModelsInQueue.remove(currentPath);
AIScene scene = ModelLoader.loadAIScene(currentPath); AIScene scene = ModelLoader.loadAIScene(currentPath);
poseModelsLoadedIntoMemory.put(currentPath, new PoseModel(currentPath, scene)); poseModelsLoadedIntoMemory.put(currentPath, new PoseModel(currentPath, scene));
} }
Globals.profiler.endCpuSample();
//queued assets //queued assets
LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load queued assets"); LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load queued assets");
Globals.profiler.beginCpuSample("AssetManager.loadAssetsInQueue - Load queued assets");
queuedAssetLock.lock(); queuedAssetLock.lock();
for(QueuedAsset<?> queuedAsset : queuedAssets){ for(QueuedAsset<?> queuedAsset : queuedAssets){
queuedAsset.load(); queuedAsset.load();
@ -171,14 +184,19 @@ public class AssetManager {
} }
queuedAssets.clear(); queuedAssets.clear();
queuedAssetLock.unlock(); queuedAssetLock.unlock();
Globals.profiler.endCpuSample();
//allocate homogenous buffers //allocate homogenous buffers
LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Allocate homogenous buffers"); LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Allocate homogenous buffers");
Globals.profiler.beginCpuSample("AssetManager.loadAssetsInQueue - Allocate homogenous buffers");
this.allocateHomogenousBuffers(); this.allocateHomogenousBuffers();
Globals.profiler.endCpuSample();
//allocate instance array buffers //allocate instance array buffers
LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Allocate instance array buffers"); LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Allocate instance array buffers");
Globals.profiler.beginCpuSample("AssetManager.loadAssetsInQueue - Allocate instance array buffers");
this.allocateInstanceArrayBuffers(); this.allocateInstanceArrayBuffers();
Globals.profiler.endCpuSample();
//override meshes //override meshes
LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Override meshes"); LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Override meshes");

View File

@ -116,9 +116,9 @@ public class MainContentPipeline implements RenderPipeline {
scaleVec.set(EntityUtils.getScale(currentEntity)) scaleVec.set(EntityUtils.getScale(currentEntity))
); );
//set actor value //set actor value
currentActor.setAttribute(modelAttribute, modelTransformMatrix); currentActor.setAttribute(modelAttribute, new Matrix4d(modelTransformMatrix));
//draw //draw
currentActor.draw(renderPipelineState, cameraModifiedPosition); currentActor.draw(renderPipelineState, new Vector3d(cameraModifiedPosition));
} else { } else {
currentActor.draw(renderPipelineState); currentActor.draw(renderPipelineState);
} }
@ -199,9 +199,9 @@ public class MainContentPipeline implements RenderPipeline {
scaleVec.set(EntityUtils.getScale(currentEntity)) scaleVec.set(EntityUtils.getScale(currentEntity))
); );
//set actor value //set actor value
currentActor.setAttribute(modelAttribute, modelTransformMatrix); currentActor.setAttribute(modelAttribute, new Matrix4d(modelTransformMatrix));
//draw //draw
currentActor.draw(renderPipelineState, cameraModifiedPosition); currentActor.draw(renderPipelineState, new Vector3d(cameraModifiedPosition));
} else { } else {
currentActor.draw(renderPipelineState); currentActor.draw(renderPipelineState);
} }

View File

@ -113,14 +113,14 @@ public class ShadowMapPipeline implements RenderPipeline {
//fetch actor //fetch actor
Actor currentActor = EntityUtils.getActor(currentEntity); Actor currentActor = EntityUtils.getActor(currentEntity);
//calculate camera-modified vector3d //calculate camera-modified vector3d
Vector3d cameraCenter = posVec.set(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); Vector3d cameraCenter = scaleVec.set(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
Vector3d cameraModifiedPosition = position.sub(cameraCenter); Vector3d cameraModifiedPosition = posVec.set(position).sub(cameraCenter);
//calculate and apply model transform //calculate and apply model transform
modelTransformMatrix = modelTransformMatrix.identity(); modelTransformMatrix = modelTransformMatrix.identity();
modelTransformMatrix.translate(cameraModifiedPosition); modelTransformMatrix.translate(cameraModifiedPosition);
modelTransformMatrix.rotate(EntityUtils.getRotation(currentEntity)); modelTransformMatrix.rotate(EntityUtils.getRotation(currentEntity));
modelTransformMatrix.scale(scaleVec.set(EntityUtils.getScale(currentEntity))); modelTransformMatrix.scale(scaleVec.set(EntityUtils.getScale(currentEntity)));
currentActor.applySpatialData(modelTransformMatrix,position); currentActor.applySpatialData(new Matrix4d(modelTransformMatrix),new Vector3d(position));
//draw //draw
currentActor.draw(renderPipelineState,openGLState); currentActor.draw(renderPipelineState,openGLState);
} }

View File

@ -1,11 +1,11 @@
package electrosphere.util.ds.octree; package electrosphere.util.ds.octree;
import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.joml.Vector3i; import org.joml.Vector3i;
import electrosphere.engine.Globals;
import io.github.studiorailgun.MathUtils; import io.github.studiorailgun.MathUtils;
/** /**
@ -22,11 +22,6 @@ public class WorldOctTree <T> {
*/ */
private WorldOctTreeNode<T> root = null; private WorldOctTreeNode<T> root = null;
/**
* The list of all nodes in the tree
*/
List<WorldOctTreeNode<T>> nodes = null;
/** /**
* The minimum position * The minimum position
*/ */
@ -59,10 +54,8 @@ public class WorldOctTree <T> {
//calculate max level //calculate max level
int dimRaw = max.x - min.x; int dimRaw = max.x - min.x;
this.maxLevel = (int)MathUtils.log2(dimRaw); this.maxLevel = (int)MathUtils.log2(dimRaw);
this.nodes = new ArrayList<WorldOctTreeNode<T>>();
this.root = new WorldOctTreeNode<T>(this, 0, new Vector3i(min), new Vector3i(max)); this.root = new WorldOctTreeNode<T>(this, 0, new Vector3i(min), new Vector3i(max));
this.root.setLeaf(true); this.root.setLeaf(true);
this.nodes.add(this.root);
} }
/** /**
@ -112,11 +105,6 @@ public class WorldOctTree <T> {
//replace existing node //replace existing node
replaceNode(existing,newContainer); replaceNode(existing,newContainer);
//update tracking
this.nodes.remove(existing);
this.nodes.add(newContainer);
this.nodes.addAll(newContainer.getChildren());
return newContainer; return newContainer;
} }
@ -130,20 +118,23 @@ public class WorldOctTree <T> {
if(existing.isLeaf()){ if(existing.isLeaf()){
throw new IllegalArgumentException("Tried to split non-leaf!"); throw new IllegalArgumentException("Tried to split non-leaf!");
} }
Globals.profiler.beginCpuSample("WorldOctTree.join - allocation");
Vector3i min = existing.getMinBound(); Vector3i min = existing.getMinBound();
Vector3i max = existing.getMaxBound(); Vector3i max = existing.getMaxBound();
int currentLevel = existing.getLevel(); int currentLevel = existing.getLevel();
WorldOctTreeNode<T> newContainer = new WorldOctTreeNode<>(this, currentLevel, min, max); WorldOctTreeNode<T> newContainer = new WorldOctTreeNode<>(this, currentLevel, min, max);
newContainer.setData(data); newContainer.setData(data);
newContainer.setLeaf(true); newContainer.setLeaf(true);
Globals.profiler.endCpuSample();
//replace existing node //replace existing node
Globals.profiler.beginCpuSample("WorldOctTree.join - replace");
this.replaceNode(existing,newContainer); this.replaceNode(existing,newContainer);
Globals.profiler.endCpuSample();
//update tracking //update tracking
this.nodes.remove(existing); Globals.profiler.beginCpuSample("WorldOctTree.join - tracking");
this.nodes.removeAll(existing.getChildren()); Globals.profiler.endCpuSample();
this.nodes.add(newContainer);
return newContainer; return newContainer;
} }
@ -191,10 +182,8 @@ public class WorldOctTree <T> {
* Clears the tree * Clears the tree
*/ */
public void clear(){ public void clear(){
this.nodes.clear();
this.root = new WorldOctTreeNode<T>(this, 0, new Vector3i(min), new Vector3i(max)); this.root = new WorldOctTreeNode<T>(this, 0, new Vector3i(min), new Vector3i(max));
this.root.isLeaf = true; this.root.isLeaf = true;
this.nodes.add(this.root);
} }
/** /**
@ -275,7 +264,22 @@ public class WorldOctTree <T> {
* @return The number of nodes * @return The number of nodes
*/ */
public int getNodeCount(){ public int getNodeCount(){
return nodes.size(); return this.recursivelyCountNotes(this.root);
}
/**
* Recursively counts all nodes
* @param searchTarget The root node
* @return The number of nodes underneath this one
*/
private int recursivelyCountNotes(WorldOctTreeNode<T> searchTarget){
int rVal = 1;
if(searchTarget.children.size() > 0){
for(WorldOctTreeNode<T> child : searchTarget.children){
rVal += this.recursivelyCountNotes(child);
}
}
return rVal;
} }