ClientDrawCellManager optimizations
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2024-11-10 14:51:29 -05:00
parent 221bcd70a7
commit 4d6db78059
21 changed files with 272 additions and 81 deletions

5
.gitignore vendored
View File

@ -63,3 +63,8 @@
#General cache for the engine
/.cache
#Memory debug files
/heap.dump
/heap.dump.hwcache
/tmp

9
.vscode/launch.json vendored
View File

@ -8,14 +8,15 @@
"type": "java",
"name": "Launch Current File",
"request": "launch",
"mainClass": "${file}"
"mainClass": "${file}",
"vmArgs": "-Xmx4G -Xms1024m -XX:+UseZGC -XX:SoftMaxHeapSize=3G -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=\"./tmp/heap.dump\""
},
{
"type": "java",
"name": "Launch Main",
"request": "launch",
"mainClass": "electrosphere.engine.Main",
"vmArgs": "-Xmx2G -Xms100m -XX:+UseZGC -XX:+UseDynamicNumberOfGCThreads -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=\"/tmp\"",
"vmArgs": "-Xmx4G -Xms1024m -XX:+UseZGC -XX:SoftMaxHeapSize=3G -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=\"./tmp/heap.dump\"",
"projectName": "Renderer"
},
{
@ -23,7 +24,7 @@
"name": "Launch Main (Debug Memory)",
"request": "launch",
"mainClass": "electrosphere.engine.Main",
"vmArgs": "-Xmx2G -Xms100m -XX:+UseZGC -XX:+UseDynamicNumberOfGCThreads -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=\"/tmp\" -javaagent:./lwjglx-debug-1.0.0.jar=t;o=trace.log",
"vmArgs": "-Xmx4G -Xms1024m -XX:+UseZGC -XX:SoftMaxHeapSize=3G -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=\"./tmp/heap.dump\" -javaagent:./lwjglx-debug-1.0.0.jar=t;o=trace.log",
"projectName": "Renderer"
},
{
@ -34,7 +35,7 @@
"env": {
"ALSOFT_LOGLEVEL": 4,
},
"vmArgs": "-Xmx2G -Xms100m -XX:+UseZGC -XX:+UseDynamicNumberOfGCThreads -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=\"/tmp\"",
"vmArgs": "-Xmx4G -Xms1024m -XX:+UseZGC -XX:SoftMaxHeapSize=3G -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=\"./tmp/heap.dump\"",
"projectName": "Renderer"
},
{

View File

@ -973,6 +973,10 @@ ScriptEngine full re-initialization signal
Add surface width to test generator
User setting to toggle foliage manager
Fix client terrain cache lookup bug
Memory debugging work + update memory flags in launch file
(11/10/2024)
Attempts at optimizing ClientDrawCellManager
# TODO

View File

@ -122,7 +122,7 @@ public class ClientSceneWrapper {
* @param clientEntity The client entity
*/
public void deregisterTranslationMapping(Entity clientEntity){
if(clientToServerMapContainsId(clientEntity.getId())){
if(this.clientToServerMapContainsId(clientEntity.getId())){
//remove from client->server map
int serverId = clientToServerIdMap.remove(clientEntity.getId());
//remove from server->client map

View File

@ -17,6 +17,11 @@ public class ChunkData {
*/
public static final int NO_STRIDE = 0;
/**
* The id for a non-homogenous data
*/
public static final int NOT_HOMOGENOUS = -1;
//The size of a chunk in virtual data
public static final int CHUNK_SIZE = ServerTerrainChunk.CHUNK_DIMENSION;
//The size of the data passed into marching cubes/transvoxel algorithm to get a fully connected and seamless chunk
@ -35,10 +40,12 @@ public class ChunkData {
* The word x coordinate
*/
int worldX;
/**
* The word y coordinate
*/
int worldY;
/**
* The word z coordinate
*/
@ -49,18 +56,25 @@ public class ChunkData {
*/
int stride;
/**
* Tracks whether this chunk is homogenous or not
*/
int homogenousValue = NOT_HOMOGENOUS;
/**
* Creates a chunk data
* @param worldX The word x coordinate
* @param worldY The word y coordinate
* @param worldZ The word z coordinate
* @param stride The stride of the data
* @param homogenous Tracks whether this chunk is homogenous or not
*/
public ChunkData(int worldX, int worldY, int worldZ, int stride){
public ChunkData(int worldX, int worldY, int worldZ, int stride, int homogenousValue){
this.worldX = worldX;
this.worldY = worldY;
this.worldZ = worldZ;
this.stride = stride;
this.homogenousValue = homogenousValue;
}
@ -231,5 +245,13 @@ public class ChunkData {
return stride;
}
/**
* The homogenous value of the chunk data
* @return if the data is homogenous, will return the id of the voxel that comprises the whole data block. Otherwise will return ChunkData.NOT_HOMOGENOUS
*/
public int getHomogenousValue(){
return homogenousValue;
}
}

View File

@ -1,10 +1,10 @@
package electrosphere.client.terrain.cache;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Semaphore;
import org.joml.Vector3i;
@ -25,37 +25,37 @@ public class ClientTerrainCache {
/**
* The map of full res chunk key -> chunk data
*/
Map<Long,ChunkData> cacheMapFullRes = new ConcurrentHashMap<Long,ChunkData>();
Map<Long,ChunkData> cacheMapFullRes = new HashMap<Long,ChunkData>();
/**
* The map of half res chunk key -> chunk data
*/
Map<Long,ChunkData> cacheMapHalfRes = new ConcurrentHashMap<Long,ChunkData>();
Map<Long,ChunkData> cacheMapHalfRes = new HashMap<Long,ChunkData>();
/**
* The map of quarter res chunk key -> chunk data
*/
Map<Long,ChunkData> cacheMapQuarterRes = new ConcurrentHashMap<Long,ChunkData>();
Map<Long,ChunkData> cacheMapQuarterRes = new HashMap<Long,ChunkData>();
/**
* The map of eighth res chunk key -> chunk data
*/
Map<Long,ChunkData> cacheMapEighthRes = new ConcurrentHashMap<Long,ChunkData>();
Map<Long,ChunkData> cacheMapEighthRes = new HashMap<Long,ChunkData>();
/**
* The map of sixteenth res chunk key -> chunk data
*/
Map<Long,ChunkData> cacheMapSixteenthRes = new ConcurrentHashMap<Long,ChunkData>();
Map<Long,ChunkData> cacheMapSixteenthRes = new HashMap<Long,ChunkData>();
/**
* The list of keys in the cache
*/
List<Long> cacheList = new CopyOnWriteArrayList<Long>();
List<Long> cacheList = new LinkedList<Long>();
/**
* A map of chunk to its world position
*/
Map<ChunkData,Vector3i> chunkPositionMap = new ConcurrentHashMap<ChunkData,Vector3i>();
Map<ChunkData,Vector3i> chunkPositionMap = new HashMap<ChunkData,Vector3i>();
/**
* The lock on the terrain cache
@ -82,9 +82,47 @@ public class ClientTerrainCache {
Map<Long,ChunkData> cache = this.getCache(chunkData.getStride());
cache.put(getKey(worldX,worldY,worldZ),chunkData);
chunkPositionMap.put(chunkData,new Vector3i(worldX,worldY,worldZ));
cacheList.add(this.getKey(worldX,worldY,worldZ));
while(cacheList.size() > cacheSize){
Long currentChunk = cacheList.remove(0);
cache.remove(currentChunk);
Long currentKey = cacheList.remove(0);
ChunkData chunk = null;
ChunkData removed = null;
removed = cacheMapFullRes.remove(currentKey);
if(removed != null){
chunk = removed;
}
removed = cacheMapHalfRes.remove(currentKey);
if(removed != null){
chunk = removed;
}
removed = cacheMapQuarterRes.remove(currentKey);
if(removed != null){
chunk = removed;
}
removed = cacheMapEighthRes.remove(currentKey);
if(removed != null){
chunk = removed;
}
removed = cacheMapSixteenthRes.remove(currentKey);
if(removed != null){
chunk = removed;
}
chunkPositionMap.remove(chunk);
}
if(cacheMapFullRes.size() > cacheSize){
throw new Error("Client cache surpassed designated size! " + cacheMapFullRes.size());
}
if(cacheMapHalfRes.size() > cacheSize){
throw new Error("Client cache surpassed designated size! " + cacheMapHalfRes.size());
}
if(cacheMapQuarterRes.size() > cacheSize){
throw new Error("Client cache surpassed designated size! " + cacheMapQuarterRes.size());
}
if(cacheMapEighthRes.size() > cacheSize){
throw new Error("Client cache surpassed designated size! " + cacheMapEighthRes.size());
}
if(cacheMapSixteenthRes.size() > cacheSize){
throw new Error("Client cache surpassed designated size! " + cacheMapSixteenthRes.size());
}
lock.release();
}

View File

@ -36,7 +36,7 @@ public class ClientDrawCellManager {
/**
* The distance to draw at full resolution
*/
public static final double FULL_RES_DIST = 12 * ServerTerrainChunk.CHUNK_DIMENSION;
public static final double FULL_RES_DIST = 8 * ServerTerrainChunk.CHUNK_DIMENSION;
/**
* The distance for half resolution
@ -301,8 +301,9 @@ public class ClientDrawCellManager {
updated = true;
} else if(!node.isLeaf()){
this.validCellCount++;
List<FloatingChunkTreeNode<DrawCell>> children = new LinkedList<FloatingChunkTreeNode<DrawCell>>(node.getChildren());
for(FloatingChunkTreeNode<DrawCell> child : children){
List<FloatingChunkTreeNode<DrawCell>> children = node.getChildren();
for(int i = 0; i < 8; i++){
FloatingChunkTreeNode<DrawCell> child = children.get(i);
boolean childUpdate = recursivelyUpdateCells(child, playerPos, evaluationMap, minLeafLod);
if(childUpdate == true){
updated = true;

View File

@ -92,7 +92,7 @@ public class DrawCell {
* Generates a drawable entity based on this chunk
*/
public void generateDrawableEntity(VoxelTextureAtlas atlas, int lod, List<DrawCellFace> higherLODFaces){
Globals.profiler.beginCpuSample("DrawCell.fillInData");
Globals.profiler.beginAggregateCpuSample("DrawCell.fillInData");
boolean success = this.fillInData(lod);
Globals.profiler.endCpuSample();
if(!success){
@ -143,8 +143,8 @@ public class DrawCell {
* Destroys a drawcell including its physics
*/
public void destroy(){
CollisionEngine collisionEngine = Globals.clientSceneWrapper.getCollisionEngine();
if(modelEntity != null){
CollisionEngine collisionEngine = Globals.clientSceneWrapper.getCollisionEngine();
collisionEngine.destroyPhysics(modelEntity);
ClientEntityUtils.destroyEntity(modelEntity);
}

View File

@ -4,12 +4,11 @@ import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Semaphore;
import org.joml.Vector3i;
@ -35,7 +34,7 @@ import io.github.studiorailgun.HashUtils;
public class ClientTerrainManager {
//queues messages from server
List<TerrainMessage> messageQueue = new CopyOnWriteArrayList<TerrainMessage>();
List<TerrainMessage> messageQueue = new LinkedList<TerrainMessage>();
/**
* Locks the terrain manager (eg if adding message from network)
@ -56,7 +55,7 @@ public class ClientTerrainManager {
public static final int INTERPOLATION_RATIO = ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO;
//caches chunks from server
static final int CACHE_SIZE = 1500 + (int)(ClientDrawCellManager.FULL_RES_DIST * 10) + (int)(ClientDrawCellManager.HALF_RES_DIST * 10);
static final int CACHE_SIZE = 2500 + (int)(ClientDrawCellManager.FULL_RES_DIST) + (int)(ClientDrawCellManager.HALF_RES_DIST);
/**
* Size of the cache in bytes
@ -70,12 +69,12 @@ public class ClientTerrainManager {
ClientWorldData clientWorldData;
//The queue of terrain chunk data to be buffered to gpu
static List<TerrainChunkGenQueueItem> terrainChunkGenerationQueue = new CopyOnWriteArrayList<TerrainChunkGenQueueItem>();
static List<TerrainChunkGenQueueItem> terrainChunkGenerationQueue = new LinkedList<TerrainChunkGenQueueItem>();
/**
* Tracks what outgoing requests are currently active
*/
Map<Long,Integer> requestedMap = new ConcurrentHashMap<Long,Integer>();
Map<Long,Integer> requestedMap = new HashMap<Long,Integer>();
/**
* Constructor
@ -93,7 +92,6 @@ public class ClientTerrainManager {
lock.acquireUninterruptibly();
List<TerrainMessage> bouncedMessages = new LinkedList<TerrainMessage>();
for(TerrainMessage message : messageQueue){
messageQueue.remove(message);
switch(message.getMessageSubtype()){
case SENDCHUNKDATA: {
int[][][] values = new int[ChunkData.CHUNK_SIZE][ChunkData.CHUNK_SIZE][ChunkData.CHUNK_SIZE];
@ -116,7 +114,7 @@ public class ClientTerrainManager {
}
}
}
ChunkData data = new ChunkData(message.getworldX(), message.getworldY(), message.getworldZ(), ChunkData.NO_STRIDE);
ChunkData data = new ChunkData(message.getworldX(), message.getworldY(), message.getworldZ(), ChunkData.NO_STRIDE, ChunkData.NOT_HOMOGENOUS);
data.setVoxelType(values);
data.setVoxelWeight(weights);
terrainCache.addChunkDataToCache(
@ -138,26 +136,27 @@ public class ClientTerrainManager {
}
IntBuffer intView = buffer.asIntBuffer();
intView.position(floatBuffer.position());
int firstType = -1;
boolean homogenous = true;
for(int x = 0; x < ChunkData.CHUNK_SIZE; x++){
for(int y = 0; y < ChunkData.CHUNK_SIZE; y++){
for(int z = 0; z < ChunkData.CHUNK_SIZE; z++){
values[x][y][z] = intView.get();
if(firstType == -1){
firstType = values[x][y][z];
} else if(homogenous && firstType == values[x][y][z]){
homogenous = false;
}
}
}
}
ChunkData data = new ChunkData(message.getworldX(), message.getworldY(), message.getworldZ(), message.getchunkResolution());
ChunkData data = new ChunkData(message.getworldX(), message.getworldY(), message.getworldZ(), message.getchunkResolution(),homogenous ? firstType : ChunkData.NOT_HOMOGENOUS);
data.setVoxelType(values);
data.setVoxelWeight(weights);
terrainCache.addChunkDataToCache(
message.getworldX(), message.getworldY(), message.getworldZ(),
data
);
if(message.getworldX() == 16 && message.getworldY() == 0 && message.getworldZ() == 32){
System.out.println("Received! " + message.getchunkResolution());
for(int i = 0; i < 10; i++){
System.out.println(values[1][i][3]);
}
}
//remove from request map
this.requestedMap.remove(this.getRequestKey(message.getworldX(), message.getworldY(), message.getworldZ(), message.getchunkResolution()));
} break;
@ -166,6 +165,7 @@ public class ClientTerrainManager {
break;
}
}
messageQueue.clear();
for(TerrainMessage message : bouncedMessages){
messageQueue.add(message);
}

View File

@ -56,9 +56,8 @@ public class ImGuiChunkMonitor {
ImGui.text("Chunk Monitor");
Globals.clientDrawCellManager.updateStatus();
ImGui.text("Renderable chunks: " + Globals.clientDrawCellManager.getGenerated());
ImGui.text("Full res chunks: " + Globals.clientDrawCellManager.getMaxResCount());
ImGui.text("Half res chunks: " + Globals.clientDrawCellManager.getHalfResCount());
// ImGui.text("Full res chunks: " + Globals.clientDrawCellManager.getFullResCacheSize());
// ImGui.text("Garbage queue: " + Globals.clientDrawCellManager.getGarbageSize());
//client network pressure

View File

@ -0,0 +1,105 @@
package electrosphere.client.ui.menu.debug;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.util.List;
import electrosphere.engine.Globals;
import electrosphere.renderer.ui.imgui.ImGuiLinePlot;
import electrosphere.renderer.ui.imgui.ImGuiLinePlot.ImGuiLinePlotDataset;
import electrosphere.renderer.ui.imgui.ImGuiWindow;
import electrosphere.renderer.ui.imgui.ImGuiWindow.ImGuiWindowCallback;
import imgui.ImGui;
/**
* Debug menu for memory profiling
*/
public class ImGuiMemory {
/**
* Size of a kilobyte
*/
static final long KB = 1024;
/**
* Size of a megabyte
*/
static final long MB = 1024 * 1024;
/**
* Size of a gigabyte
*/
static final long GB = 1024 * 1024 * 1024;
/**
* Number of points on the graph
*/
static final int GRAPH_POINT_COUNT = 50;
//window for viewing information about the memory usage
protected static ImGuiWindow memoryWindow;
/**
* Creates the windows in this file
*/
protected static void createMemoryWindows(){
createMemoryDebugWindow();
}
/**
* Memory window
*/
protected static void createMemoryDebugWindow(){
//memory usage graph
ImGuiLinePlot memoryGraph = new ImGuiLinePlot("Memory Usage",400,400);
ImGuiLinePlotDataset memoryGraphDataset = new ImGuiLinePlotDataset("Memory Usage (mb)", GRAPH_POINT_COUNT);
memoryGraphDataset.zeroOut();
memoryGraph.addDataset(memoryGraphDataset);
memoryWindow = new ImGuiWindow("Memory Usage");
memoryWindow.setCallback(new ImGuiWindowCallback() {
@Override
public void exec() {
//get garbage collector name
List<GarbageCollectorMXBean> gcMxBeans = ManagementFactory.getGarbageCollectorMXBeans();
if(gcMxBeans != null && gcMxBeans.size() > 0){
GarbageCollectorMXBean gcMxBean = gcMxBeans.get(0);
ImGui.text(gcMxBean.getName() + " - " + gcMxBean.getObjectName());
}
//get memory usage
long totalMemory = Runtime.getRuntime().totalMemory();
long freeMemory = Runtime.getRuntime().freeMemory();
long memoryUsage = totalMemory - freeMemory;
ImGui.text("Total Memory: " + formatMemory(totalMemory));
ImGui.text("Free Memory: " + formatMemory(freeMemory));
ImGui.text("Memory Usage: " + formatMemory(memoryUsage));
//memory usage graph
memoryGraphDataset.addPoint(memoryUsage);
memoryGraph.draw();
}
});
memoryWindow.setOpen(false);
Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(memoryWindow);
}
/**
* Formats a memory value
* @param memoryRaw The memory value
* @return The formatted string
*/
private static String formatMemory(long memoryRaw){
if(memoryRaw < KB){
return "" + memoryRaw;
} else if(memoryRaw < MB){
return (memoryRaw / KB) + "kb";
} else {
return (memoryRaw / MB) + "mb";
}
}
}

View File

@ -53,6 +53,7 @@ public class ImGuiWindowMacros {
ImGuiTestGen.createTestGenWindows();
ImGuiChunkMonitor.createChunkMonitorWindows();
ImGuiGriddedManager.createGriddedManagerWindows();
ImGuiMemory.createMemoryWindows();
}
/**
@ -114,10 +115,11 @@ public class ImGuiWindowMacros {
fluidWindow.setCallback(new ImGuiWindowCallback() {
@Override
public void exec() {
ServerFluidManager fluidManager = Globals.playerManager.getPlayerRealm(Globals.clientPlayer).getServerWorldData().getServerFluidManager();
//audio engine details
ImGui.text("Fluids Debug");
ImGui.text("State: " + (fluidManager.getSimulate() ? "on" : "off"));
if(ImGui.button("Toggle Simulation")){
ServerFluidManager fluidManager = Globals.playerManager.getPlayerRealm(Globals.clientPlayer).getServerWorldData().getServerFluidManager();
fluidManager.setSimulate(!fluidManager.getSimulate());
}
}
@ -193,6 +195,10 @@ public class ImGuiWindowMacros {
if(ImGui.button("Gridded Data Cell Monitor")){
ImGuiGriddedManager.griddedManagerWindow.setOpen(true);
}
//memory usage
if(ImGui.button("Memory Usage")){
ImGuiMemory.memoryWindow.setOpen(!ImGuiMemory.memoryWindow.isOpen());
}
//close button
if(ImGui.button("Close")){
mainDebugWindow.setOpen(false);

View File

@ -722,10 +722,10 @@ public class CollisionEngine {
//make uncollidable
if(PhysicsEntityUtils.containsDBody(e)){
DBody rigidBody = PhysicsEntityUtils.getDBody(e);
deregisterCollisionObject(rigidBody,PhysicsEntityUtils.getCollidable(e));
this.deregisterCollisionObject(rigidBody,PhysicsEntityUtils.getCollidable(e));
e.removeData(EntityDataStrings.PHYSICS_COLLISION_BODY);
if(rigidBody != null){
deregisterPhysicsObject(rigidBody);
this.deregisterPhysicsObject(rigidBody);
}
}
if(ServerPhysicsSyncTree.hasTree(e)){

View File

@ -154,6 +154,10 @@ public class Globals {
//set to true to trigger full GC every frame
//a full GC includes collecting old generations as well -- likely very laggy!!
public static boolean EXPLICIT_GC = false;
/**
* Number of frames to wait before triggering gc again
*/
public static final int GC_FRAME_FREQUENCY = 15;
//

View File

@ -376,7 +376,7 @@ public class Main {
/// G A R B A G E C H E C K
///
Globals.profiler.beginCpuSample("gc");
if(Globals.EXPLICIT_GC){
if(Globals.EXPLICIT_GC && Globals.timekeeper.getNumberOfRenderFramesElapsed() % Globals.GC_FRAME_FREQUENCY == 0){
System.gc();
}
Globals.profiler.endCpuSample();

View File

@ -41,7 +41,7 @@ public class TerrainChunk {
* @return The terrain chunk entity
*/
public static Entity clientCreateTerrainChunkEntity(TransvoxelChunkData chunkData, int levelOfDetail, VoxelTextureAtlas atlas, boolean hasPolygons){
Globals.profiler.beginCpuSample("TerrainChunk.clientCreateTerrainChunkEntity");
Globals.profiler.beginAggregateCpuSample("TerrainChunk.clientCreateTerrainChunkEntity");
Entity rVal = EntityCreationUtils.createClientSpatialEntity();

View File

@ -45,7 +45,7 @@ public class EntityProtocol implements ClientProtocolTemplate<EntityMessage> {
@Override
public void handleSyncMessage(EntityMessage message) {
Globals.profiler.beginCpuSample("EntityProtocol.handleEntityMessage");
Globals.profiler.beginAggregateCpuSample("EntityProtocol.handleEntityMessage");
LoggerInterface.loggerNetworking.DEBUG_LOOP("Parse entity message of type " + message.getMessageSubtype());
//error check

View File

@ -28,7 +28,7 @@ public class TerrainProtocol implements ClientProtocolTemplate<TerrainMessage> {
@Override
public void handleSyncMessage(TerrainMessage message) {
Globals.profiler.beginCpuSample("TerrainProtocol.handleTerrainMessage");
Globals.profiler.beginAggregateCpuSample("TerrainProtocol.handleTerrainMessage");
switch(message.getMessageSubtype()){
case RESPONSEMETADATA:
Globals.clientWorldData = new ClientWorldData(

View File

@ -3,7 +3,7 @@ package electrosphere.server.terrain.generation;
import java.util.HashMap;
import java.util.Map;
import org.graalvm.polyglot.Value;
// import org.graalvm.polyglot.Value;
import electrosphere.engine.Globals;
import electrosphere.game.data.biome.BiomeData;
@ -94,9 +94,6 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
float[][][] weights = new float[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];;
int[][][] values = new int[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
if(worldX == 16 && worldY == 0 && worldZ == 32){
System.out.println(worldX + " " + worldY + " " + worldZ);
}
try {
//actual generation algo
@ -129,34 +126,34 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
}
if(this.useJavascript){
Globals.scriptEngine.executeSynchronously(() -> {
Value getVoxelFunc = Globals.scriptEngine.invokeEngineMember("chunkGeneratorManager", "getVoxelFunction", SCRIPT_GEN_TEST_TAG);
for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator - Generate slice");
for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){
for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){
int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
int finalWorldY = worldY + ((y * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
int finalWorldZ = worldZ + ((z * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
int finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
int finalChunkY = (y * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
Value result = getVoxelFunc.execute(
finalWorldX, finalWorldY, finalWorldZ,
finalChunkX, finalChunkY, finalChunkZ,
stride,
heightfield[x][z],
surfaceBiome
);
if(result != null){
weights[x][y][z] = result.getMember("weight").asFloat();
values[x][y][z] = result.getMember("type").asInt();
}
}
}
Globals.profiler.endCpuSample();
}
});
// Globals.scriptEngine.executeSynchronously(() -> {
// Value getVoxelFunc = Globals.scriptEngine.invokeEngineMember("chunkGeneratorManager", "getVoxelFunction", SCRIPT_GEN_TEST_TAG);
// for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
// Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator - Generate slice");
// for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){
// for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){
// int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
// int finalWorldY = worldY + ((y * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
// int finalWorldZ = worldZ + ((z * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
// int finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
// int finalChunkY = (y * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
// int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
// Value result = getVoxelFunc.execute(
// finalWorldX, finalWorldY, finalWorldZ,
// finalChunkX, finalChunkY, finalChunkZ,
// stride,
// heightfield[x][z],
// surfaceBiome
// );
// if(result != null){
// weights[x][y][z] = result.getMember("weight").asFloat();
// values[x][y][z] = result.getMember("type").asInt();
// }
// }
// }
// Globals.profiler.endCpuSample();
// }
// });
} else {
for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator - Generate slice");

View File

@ -19,7 +19,7 @@ public class ServerChunkCache {
/**
* Number of chunks to cache
*/
static final int CACHE_SIZE = 2500;
static final int CACHE_SIZE = 1500;
/**
* The size of the cache
@ -124,6 +124,14 @@ public class ServerChunkCache {
queryRecencyQueue.add(0, key);
Map<Long,ServerTerrainChunk> cache = this.getCache(stride);
cache.put(key, chunk);
while(queryRecencyQueue.size() > cacheSize){
Long oldKey = queryRecencyQueue.remove(queryRecencyQueue.size() - 1);
cacheMapFullRes.remove(oldKey);
cacheMapHalfRes.remove(oldKey);
cacheMapQuarterRes.remove(oldKey);
cacheMapEighthRes.remove(oldKey);
cacheMapSixteenthRes.remove(oldKey);
}
lock.release();
}

View File

@ -38,6 +38,7 @@ public class ClientDrawCellManagerTests {
int worldDiscreteSize = 64;
Globals.clientWorldData = new ClientWorldData(new Vector3f(0), new Vector3f(worldDiscreteSize * ServerTerrainChunk.CHUNK_DIMENSION), 0, worldDiscreteSize);
ClientDrawCellManager manager = new ClientDrawCellManager(null, 64);
double precomputedMidDist = 0;
Vector3d playerPos = new Vector3d(0,0,0);
FloatingChunkTreeNode<DrawCell> node = FloatingChunkTreeNode.constructorForTests(manager.chunkTree, 1, new Vector3i(16,0,0), new Vector3i(32,16,16));
node.convertToLeaf(DrawCell.generateTerrainCell(new Vector3i(0,0,0)));