Continued work on geometry removal

This commit is contained in:
mcrcortex
2025-01-25 04:14:00 +10:00
parent d0b5f32e2d
commit d6500d2227
9 changed files with 119 additions and 17 deletions

View File

@@ -7,6 +7,7 @@ import me.cortex.voxy.client.core.gl.GlBuffer;
import me.cortex.voxy.client.core.model.ModelBakerySubsystem; import me.cortex.voxy.client.core.model.ModelBakerySubsystem;
import me.cortex.voxy.client.core.rendering.*; import me.cortex.voxy.client.core.rendering.*;
import me.cortex.voxy.client.core.rendering.building.RenderDataFactory4; import me.cortex.voxy.client.core.rendering.building.RenderDataFactory4;
import me.cortex.voxy.client.core.rendering.building.RenderGenerationService;
import me.cortex.voxy.client.core.rendering.post.PostProcessing; import me.cortex.voxy.client.core.rendering.post.PostProcessing;
import me.cortex.voxy.client.core.rendering.util.DownloadStream; import me.cortex.voxy.client.core.rendering.util.DownloadStream;
import me.cortex.voxy.client.core.util.IrisUtil; import me.cortex.voxy.client.core.util.IrisUtil;
@@ -35,6 +36,7 @@ import org.lwjgl.opengl.GL11;
import java.io.File; import java.io.File;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import static org.lwjgl.opengl.GL30C.*; import static org.lwjgl.opengl.GL30C.*;
@@ -91,6 +93,7 @@ public class VoxelCore {
//this.testMeshingPerformance(); //this.testMeshingPerformance();
//this.testDbPerformance(); //this.testDbPerformance();
//this.testFullMesh();
} }
public void enqueueIngest(WorldChunk worldChunk) { public void enqueueIngest(WorldChunk worldChunk) {
@@ -266,6 +269,10 @@ public class VoxelCore {
return this.world; return this.world;
} }
private void verifyTopNodeChildren(int X, int Y, int Z) { private void verifyTopNodeChildren(int X, int Y, int Z) {
for (int lvl = 0; lvl < 5; lvl++) { for (int lvl = 0; lvl < 5; lvl++) {
for (int y = (Y<<5)>>lvl; y < ((Y+1)<<5)>>lvl; y++) { for (int y = (Y<<5)>>lvl; y < ((Y+1)<<5)>>lvl; y++) {
@@ -378,4 +385,70 @@ public class VoxelCore {
System.out.println("Total "+delta+"ms " + ((double)delta/c) + "ms average" ); System.out.println("Total "+delta+"ms " + ((double)delta/c) + "ms average" );
} }
private void testFullMesh() {
var modelService = new ModelBakerySubsystem(this.world.getMapper());
var completedCounter = new AtomicInteger();
var generationService = new RenderGenerationService(this.world, modelService, this.serviceThreadPool, a-> {completedCounter.incrementAndGet(); a.free();}, false);
var r = new Random(12345);
{
for (int i = 0; i < 10_000; i++) {
int x = (r.nextInt(256*2+2)-256)>>1;//-32
int z = (r.nextInt(256*2+2)-256)>>1;//-32
int y = r.nextInt(10)-2;
int lvl = 0;//r.nextInt(5);
long key = WorldEngine.getWorldSectionId(lvl, x>>lvl, y>>lvl, z>>lvl);
generationService.enqueueTask(key);
}
int i = 0;
while (true) {
modelService.tick();
if (i++%5000==0)
System.out.println(completedCounter.get());
glFinish();
List<String> a = new ArrayList<>();
generationService.addDebugData(a);
if (a.getFirst().endsWith(" 0")) {
break;
}
}
}
System.out.println("Running benchmark");
while (true)
{
completedCounter.set(0);
long start = System.currentTimeMillis();
int C = 200_000;
for (int i = 0; i < C; i++) {
int x = (r.nextInt(256 * 2 + 2) - 256) >> 1;//-32
int z = (r.nextInt(256 * 2 + 2) - 256) >> 1;//-32
int y = r.nextInt(10) - 2;
int lvl = 0;//r.nextInt(5);
long key = WorldEngine.getWorldSectionId(lvl, x >> lvl, y >> lvl, z >> lvl);
generationService.enqueueTask(key);
}
//int i = 0;
while (true) {
//if (i++%5000==0)
// System.out.println(completedCounter.get());
modelService.tick();
glFinish();
List<String> a = new ArrayList<>();
generationService.addDebugData(a);
if (a.getFirst().endsWith(" 0")) {
break;
}
}
long delta = (System.currentTimeMillis()-start);
System.out.println("Time "+delta+"ms count: " + completedCounter.get() + " avg per mesh: " + ((double)delta/completedCounter.get()));
if (false)
break;
}
generationService.shutdown();
modelService.shutdown();
}
} }

View File

@@ -1,6 +1,7 @@
package me.cortex.voxy.client.core.gl; package me.cortex.voxy.client.core.gl;
import me.cortex.voxy.common.util.TrackedObject; import me.cortex.voxy.common.util.TrackedObject;
import org.lwjgl.opengl.GL11;
import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE; import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE;
import static org.lwjgl.opengl.GL15.glDeleteBuffers; import static org.lwjgl.opengl.GL15.glDeleteBuffers;
@@ -46,6 +47,16 @@ public class GlBuffer extends TrackedObject {
return this; return this;
} }
public GlBuffer fill(int data) {
//Clear unpack values
//Fixed in mesa commit a5c3c452
glPixelStorei(GL11.GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL11.GL_UNPACK_SKIP_PIXELS, 0);
glClearNamedBufferData(this.id, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, new int[]{data});
return this;
}
public static int getCount() { public static int getCount() {
return COUNT; return COUNT;
} }

View File

@@ -49,7 +49,7 @@ public class RenderService<T extends AbstractSectionRenderer<J, ?>, J extends Vi
//Max sections: ~500k //Max sections: ~500k
//Max geometry: 1 gb //Max geometry: 1 gb
this.sectionRenderer = (T) createSectionRenderer(this.modelService.getStore(),1<<20, (1L<<31)-1024); this.sectionRenderer = (T) createSectionRenderer(this.modelService.getStore(),1<<20, (1L<<32)-1024);
//Do something incredibly hacky, we dont need to keep the reference to this around, so just connect and discard //Do something incredibly hacky, we dont need to keep the reference to this around, so just connect and discard
var router = new SectionUpdateRouter(); var router = new SectionUpdateRouter();
@@ -149,7 +149,7 @@ public class RenderService<T extends AbstractSectionRenderer<J, ?>, J extends Vi
private int q = -60; private int q = -60;
public void setup(Camera camera) { public void setup(Camera camera) {
final int W = 32; final int W = 3;
final int H = 2; final int H = 2;
boolean SIDED = false; boolean SIDED = false;
for (int i = 0; i<64 && q<((W*2+1)*(W*2+1)*H)&&q++>=0;i++) { for (int i = 0; i<64 && q<((W*2+1)*(W*2+1)*H)&&q++>=0;i++) {

View File

@@ -233,7 +233,7 @@ public class RenderDataFactory4 {
this.blockMesher.finish(); this.blockMesher.finish();
} }
{ if (true) {
this.blockMesher.doAuxiliaryFaceOffset = false; this.blockMesher.doAuxiliaryFaceOffset = false;
//Hacky generate section side faces (without check neighbor section) //Hacky generate section side faces (without check neighbor section)
for (int side = 0; side < 2; side++) { for (int side = 0; side < 2; side++) {
@@ -411,7 +411,7 @@ public class RenderDataFactory4 {
} }
//Generate the side faces, hackily, using 0 and 1 mesher //Generate the side faces, hackily, using 0 and 1 mesher
{ if (true) {
var ma = this.xAxisMeshers[0]; var ma = this.xAxisMeshers[0];
var mb = this.xAxisMeshers[31]; var mb = this.xAxisMeshers[31];
ma.finish(); ma.finish();

View File

@@ -5,6 +5,7 @@ import me.cortex.voxy.client.core.gl.GlBuffer;
import me.cortex.voxy.client.core.gl.shader.AutoBindingShader; import me.cortex.voxy.client.core.gl.shader.AutoBindingShader;
import me.cortex.voxy.client.core.gl.shader.Shader; import me.cortex.voxy.client.core.gl.shader.Shader;
import me.cortex.voxy.client.core.gl.shader.ShaderType; import me.cortex.voxy.client.core.gl.shader.ShaderType;
import me.cortex.voxy.client.core.rendering.util.DownloadStream;
import me.cortex.voxy.client.core.rendering.util.UploadStream; import me.cortex.voxy.client.core.rendering.util.UploadStream;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
@@ -26,7 +27,7 @@ public class NodeCleaner {
private static final int BATCH_SET_SIZE = 2048; private static final int BATCH_SET_SIZE = 2048;
private final Shader sorter = Shader.make() private final AutoBindingShader sorter = Shader.makeAuto()
.define("OUTPUT_SIZE", OUTPUT_COUNT) .define("OUTPUT_SIZE", OUTPUT_COUNT)
.define("VISIBILITY_BUFFER_BINDING", 1) .define("VISIBILITY_BUFFER_BINDING", 1)
.define("OUTPUT_BUFFER_BINDING", 2) .define("OUTPUT_BUFFER_BINDING", 2)
@@ -56,6 +57,10 @@ public class NodeCleaner {
this.batchClear this.batchClear
.ssbo("VISIBILITY_BUFFER_BINDING", this.visibilityBuffer) .ssbo("VISIBILITY_BUFFER_BINDING", this.visibilityBuffer)
.ssbo("LIST_BUFFER_BINDING", this.scratchBuffer); .ssbo("LIST_BUFFER_BINDING", this.scratchBuffer);
this.sorter
.ssbo("VISIBILITY_BUFFER_BINDING", this.visibilityBuffer)
.ssbo("OUTPUT_BUFFER_BINDING", this.outputBuffer);
} }
public void clearId(int id) { public void clearId(int id) {
@@ -63,6 +68,7 @@ public class NodeCleaner {
} }
public void tick() { public void tick() {
this.visibilityId++;
this.clearIds(); this.clearIds();
if (false) { if (false) {
@@ -70,14 +76,19 @@ public class NodeCleaner {
this.sorter.bind(); this.sorter.bind();
//TODO: choose whether this is in nodeSpace or section/geometryId space //TODO: choose whether this is in nodeSpace or section/geometryId space
//glDispatchCompute(this.nodeManager.getCurrentMaxNodeId()/, 1, 1); //this.nodeManager.getCurrentMaxNodeId()
glDispatchCompute((200_000+127)/128, 1, 1);
//DownloadStream.INSTANCE.download(this.outputBuffer, this::onDownload); DownloadStream.INSTANCE.download(this.outputBuffer, this::onDownload);
} }
} }
private void onDownload(long ptr, long size) { private void onDownload(long ptr, long size) {
StringBuilder b = new StringBuilder();
for (int i = 0; i < 64; i++) {
b.append(", ").append(MemoryUtil.memGetInt(ptr + 4 * i));
}
System.out.println(b);
} }
private void clearIds() { private void clearIds() {

View File

@@ -272,7 +272,7 @@ public final class NodeStore {
MemoryUtil.memPutInt(ptr, w); ptr += 4; MemoryUtil.memPutInt(ptr, w); ptr += 4;
} }
//public int getEndNodeId() { public int getEndNodeId() {
return this.allocationSet.getMaxIndex();
//} }
} }

View File

@@ -161,6 +161,10 @@ public class HierarchicalBitSet {
} }
public int getMaxIndex() {
throw new IllegalStateException();
}
public static void main(String[] args) { public static void main(String[] args) {
var h = new HierarchicalBitSet(1<<19); var h = new HierarchicalBitSet(1<<19);

View File

@@ -40,7 +40,7 @@ public class WorldEngine {
this.storage = storageBackend; this.storage = storageBackend;
this.mapper = new Mapper(this.storage); this.mapper = new Mapper(this.storage);
//4 cache size bits means that the section tracker has 16 separate maps that it uses //4 cache size bits means that the section tracker has 16 separate maps that it uses
this.sectionTracker = new ActiveSectionTracker(3, this::unsafeLoadSection); this.sectionTracker = new ActiveSectionTracker(4, this::unsafeLoadSection);
this.savingService = new SectionSavingService(this, serviceThreadPool); this.savingService = new SectionSavingService(this, serviceThreadPool);
this.ingestService = new VoxelIngestService(this, serviceThreadPool); this.ingestService = new VoxelIngestService(this, serviceThreadPool);

View File

@@ -4,7 +4,7 @@
//#define OUTPUT_SIZE 128 //#define OUTPUT_SIZE 128
layout(local_size_x=32, local_size_y=8) in; layout(local_size_x=128, local_size_y=1) in;
//256 workgroup //256 workgroup
@@ -16,6 +16,7 @@ layout(binding = OUTPUT_BUFFER_BINDING, std430) restrict volatile buffer Minimum
uint minVisIds[OUTPUT_SIZE]; uint minVisIds[OUTPUT_SIZE];
}; };
//Returns the id of the max value
uint atomicDerefMin(uint atId, uint id, uint value) { uint atomicDerefMin(uint atId, uint id, uint value) {
uint existingId = minVisIds[atId]; uint existingId = minVisIds[atId];
while (true) { while (true) {
@@ -26,9 +27,10 @@ uint atomicDerefMin(uint atId, uint id, uint value) {
//Attempt to swap, since we know we are less than the existingId //Attempt to swap, since we know we are less than the existingId
atomicCompSwap(minVisIds[atId], existingId, id); atomicCompSwap(minVisIds[atId], existingId, id);
//Check if we did swap, else if we failed (or got reswapped else where) recheck //Check if we did swap, else if we failed (or got reswapped else where) recheck
uint pExistingId = existingId;
existingId = minVisIds[atId]; existingId = minVisIds[atId];
if (existingId == id) { if (existingId == id) {
return existingId; return pExistingId;
} }
} }
} }
@@ -37,9 +39,6 @@ uint atomicDerefMin(uint atId, uint id, uint value) {
void bubbleSort(uint start, uint id, uint value) { void bubbleSort(uint start, uint id, uint value) {
for (uint i = start; i < OUTPUT_SIZE; i++) { for (uint i = start; i < OUTPUT_SIZE; i++) {
uint nextId = atomicDerefMin(i, id, value); uint nextId = atomicDerefMin(i, id, value);
if (nextId == id) {
return;//Not inserted, so return
}
//Else we need to bubble the value up //Else we need to bubble the value up
id = nextId; id = nextId;
value = visiblity[id]; value = visiblity[id];
@@ -47,5 +46,9 @@ void bubbleSort(uint start, uint id, uint value) {
} }
void main() { void main() {
//if (gl_GlobalInvocationID.x <64) {
// minVisIds[gl_GlobalInvocationID.x] = visiblity[gl_GlobalInvocationID.x];
//}
//First do a min sort/set of min OUTPUT_SIZE values of the set //First do a min sort/set of min OUTPUT_SIZE values of the set
bubbleSort(0, gl_GlobalInvocationID.x, visiblity[gl_GlobalInvocationID.x]);
} }