From 14e72c68cbef363734b7dcbd18118d38d0ccee54 Mon Sep 17 00:00:00 2001 From: tom lee Date: Thu, 20 Jan 2022 22:53:17 +0800 Subject: [PATCH] Added sub buffers. Greatly reducing fps stutters --- .../LodBufferBuilderFactory.java | 133 +++++++++++------- 1 file changed, 80 insertions(+), 53 deletions(-) diff --git a/src/main/java/com/seibel/lod/core/builders/bufferBuilding/LodBufferBuilderFactory.java b/src/main/java/com/seibel/lod/core/builders/bufferBuilding/LodBufferBuilderFactory.java index 1879cce40..6342ef8f3 100644 --- a/src/main/java/com/seibel/lod/core/builders/bufferBuilding/LodBufferBuilderFactory.java +++ b/src/main/java/com/seibel/lod/core/builders/bufferBuilding/LodBufferBuilderFactory.java @@ -117,6 +117,7 @@ public class LodBufferBuilderFactory * when need be to fit the larger sizes. */ public static final int DEFAULT_MEMORY_ALLOCATION = 1024; + public static final int MAX_TRIANGLES_PER_BUFFER = (1024*1024*2) / (LodUtil.LOD_VERTEX_FORMAT.getByteSize()*3); @@ -133,7 +134,7 @@ public class LodBufferBuilderFactory /** Stores the vertices when building the VBOs */ // FIXME: Use special warparound type of movable grid list in the future - public volatile MovableGridList buildableBuffers; + public volatile MovableGridList buildableBuffers; /** Used when building new VBOs */ public volatile MovableGridList buildableVbos; @@ -264,7 +265,7 @@ public class LodBufferBuilderFactory if (fullRegen || tooFar || buildableBuffers==null || buildableVbos==null || setsToRender==null || vertexOptimizerCache==null) { renderRange = lodDim.getWidth()/2; //get lodDim half width - buildableBuffers = new MovableGridList(renderRange, playerRegionX, playerRegionZ); + buildableBuffers = new MovableGridList(renderRange, playerRegionX, playerRegionZ); buildableVbos = new MovableGridList(renderRange, playerRegionX, playerRegionZ); setsToRender = new MovableGridList(renderRange, playerRegionX, playerRegionZ); vertexOptimizerCache = new MovableGridList(renderRange, playerRegionX, playerRegionZ); @@ -318,23 +319,13 @@ public class LodBufferBuilderFactory RegionPos regionPos = new RegionPos(regionX, regionZ); posToUpload.add(regionPos); - LodBufferBuilder[] builder = buildableBuffers.get(regionX, regionZ); - LodVertexBuffer[] vbo = buildableVbos.get(regionX, regionZ); - if (vbo == null) { - setupBuffers(regionX, regionZ); - vbo = buildableVbos.get(regionX, regionZ); - } + LodBufferBuilder builder = buildableBuffers.get(regionX, regionZ); if (builder == null) { - builder = buildableBuffers.setAndGet(regionX, regionZ, new LodBufferBuilder[vbo.length]); - } - for (int i=0; i * May have to wait for the bufferLock to open. */ - private void setupBuffers(int regionX, int regionZ) { + + private void setupBuffersTOBEREMOVED(int regionX, int regionZ) { //TODO: Impl actual multibuffers //int regionMemoryRequired = DEFAULT_MEMORY_ALLOCATION; //int numberOfBuffers; @@ -608,6 +598,7 @@ public class LodBufferBuilderFactory } else { numberOfBuffers = 1; }*/ + vbos = buildableVbos.setAndGet(regionX, regionZ, new LodVertexBuffer[1]); } @@ -668,34 +659,68 @@ public class LodBufferBuilderFactory long BPerNS = CONFIG.client().advanced().buffers().getGpuUploadPerMegabyteInMilliseconds(); // MB -> B = 1/1,000,000. MS -> NS = 1,000,000. So, MBPerMS = BPerNS. long remainingNS = 0; // We don't want to pause for like 0.1 ms... so we store those tiny MS. long bytesUploaded = 0; + long totalBuffers = 0; // actually upload the buffers for (RegionPos p : toBeUploaded) { - LodBufferBuilder[] buffers = buildableBuffers.get(p.x, p.z); - for (int i = 0; i < buffers.length; i++) - { - ByteBuffer uploadBuffer = null; - //FIXME: The sonme Buffers aren't closed/end() and causing errors! - try { - LagSpikeCatcher b = new LagSpikeCatcher(); - uploadBuffer = buffers[i].getCleanedByteBuffer(); - b.end("getCleanedByteBuffer"); - } catch (IndexOutOfBoundsException e) { - // NOTE: Temp try/catch for above FIXME. - e.printStackTrace(); - } catch (RuntimeException e) { - ClientApi.LOGGER.error(LodBufferBuilderFactory.class.getSimpleName() + " - UploadBuffers failed: " + e.getMessage()); - e.printStackTrace(); - } - if (uploadBuffer == null) continue; - LagSpikeCatcher vboU = new LagSpikeCatcher(); - vboUpload(p, i, uploadBuffer, uploadMethod); - vboU.end("vboUpload"); + LodBufferBuilder buffer = buildableBuffers.get(p.x, p.z); + ByteBuffer uploadBuffer = null; + //FIXME: The sonme Buffers aren't closed/end() and causing errors! + try { + LagSpikeCatcher b = new LagSpikeCatcher(); + uploadBuffer = buffer.getCleanedByteBuffer(); + b.end("getCleanedByteBuffer"); + } catch (IndexOutOfBoundsException e) { + // NOTE: Temp try/catch for above FIXME. + e.printStackTrace(); + } catch (RuntimeException e) { + ClientApi.LOGGER.error(LodBufferBuilderFactory.class.getSimpleName() + " - UploadBuffers failed: " + e.getMessage()); + e.printStackTrace(); + } + if (uploadBuffer == null) continue; + + + int maxLength = MAX_TRIANGLES_PER_BUFFER*(LodUtil.LOD_VERTEX_FORMAT.getByteSize()*3); + LagSpikeCatcher vboSetup = new LagSpikeCatcher(); + LodVertexBuffer[] vbos = buildableVbos.get(p.x, p.z); + int requiredFullBuffers = Math.floorDiv(uploadBuffer.capacity(),maxLength); + int additionalBuffer = Math.floorMod(uploadBuffer.capacity(),maxLength); + if (vbos == null) { + vbos = new LodVertexBuffer[requiredFullBuffers+1]; + buildableVbos.set(p.x, p.z, vbos); + } else if (vbos.length != requiredFullBuffers+1) { + LodVertexBuffer[] newVbos = new LodVertexBuffer[requiredFullBuffers+1]; + if (vbos.length > requiredFullBuffers+1) { + for (int i=requiredFullBuffers+1; i= TimeUnit.NANOSECONDS.convert(1000/60, TimeUnit.MILLISECONDS)) { if (remainingNS > MAX_BUFFER_UPLOAD_TIMEOUT_NANOSECONDS) remainingNS = MAX_BUFFER_UPLOAD_TIMEOUT_NANOSECONDS; try { @@ -704,8 +729,10 @@ public class LodBufferBuilderFactory remainingNS = 0; } } + totalBuffers += (requiredFullBuffers+1); + ClientApi.LOGGER.info("Uploaded {} sub buffers for {}", (requiredFullBuffers+1), p); } - ClientApi.LOGGER.info("UploadBuffers uploaded "+bytesUploaded+" bytes."); + ClientApi.LOGGER.info("UploadBuffers uploaded "+bytesUploaded+" bytes, with {} sub buffers", totalBuffers); } /** Uploads the uploadBuffer so the GPU can use it. */