Reduce buffer uploading stuttering

I also included commented out versions of several other buffer uploading options and comments on how well they perform.
This commit is contained in:
James Seibel
2021-10-04 22:52:11 -05:00
parent ee6c8d597c
commit f6ea990ab0
2 changed files with 128 additions and 16 deletions
@@ -31,6 +31,7 @@ import java.util.concurrent.locks.ReentrantLock;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL15C;
import org.lwjgl.opengl.GL45;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.seibel.lod.builders.bufferBuilding.lodTemplates.Box;
@@ -60,7 +61,7 @@ import net.minecraft.util.math.ChunkPos;
* This object is used to create NearFarBuffer objects.
*
* @author James Seibel
* @version 10-2-2021
* @version 10-4-2021
*/
public class LodBufferBuilder
{
@@ -469,7 +470,6 @@ public class LodBufferBuilder
else
{
numberOfBuffers = (int) Math.ceil(memoryRequired / BUFFER_MAX_CAPACITY) + 1;
System.out.println(numberOfBuffers);
memoryRequired = BUFFER_MAX_CAPACITY;
bufferSize[x][z] = numberOfBuffers;
buildableBuffers[x][z] = new BufferBuilder[numberOfBuffers];
@@ -480,8 +480,25 @@ public class LodBufferBuilder
for (int i = 0; i < bufferSize[x][z]; i++)
{
buildableBuffers[x][z][i] = new BufferBuilder((int) memoryRequired);
buildableVbos[x][z][i] = new VertexBuffer(LodRenderer.LOD_VERTEX_FORMAT);
drawableVbos[x][z][i] = new VertexBuffer(LodRenderer.LOD_VERTEX_FORMAT);
// // buffer storage
// GL15.glDeleteBuffers(buildableVbos[x][z][i].id);
// GL15.glDeleteBuffers(drawableVbos[x][z][i].id);
//
// GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, buildableVbos[x][z][i].id);
// // no matter the size the buffer are created at sometimes they will still fail
// // to map later on, James isn't sure why that is
// GL45.glBufferStorage(GL15.GL_ARRAY_BUFFER, BUFFER_MAX_CAPACITY / 2, GL45.GL_MAP_WRITE_BIT | GL45.GL_MAP_PERSISTENT_BIT | GL45.GL_MAP_COHERENT_BIT);
// GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
//
// GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, drawableVbos[x][z][i].id);
// GL45.glBufferStorage(GL15.GL_ARRAY_BUFFER, BUFFER_MAX_CAPACITY / 2, GL45.GL_MAP_WRITE_BIT | GL45.GL_MAP_PERSISTENT_BIT | GL45.GL_MAP_COHERENT_BIT);
// GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
// // buffer storage end
}
}
}
@@ -547,6 +564,7 @@ public class LodBufferBuilder
}
}
/**
* Upload all buildableBuffers to the GPU.
*/
@@ -577,7 +595,7 @@ public class LodBufferBuilder
}
}
}
catch (IllegalStateException e)
catch (Exception e) // TODO this try/catch may not be needed anymore, James needs to check
{
ClientProxy.LOGGER.error(LodBufferBuilder.class.getSimpleName() + " - UploadBuffers failed: " + e.getMessage());
e.printStackTrace();
@@ -602,18 +620,115 @@ public class LodBufferBuilder
// this is how many points will be rendered
vbo.vertexCount = (uploadBuffer.remaining() / vbo.format.getVertexSize());
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo.id);
// subData only works if the memory is allocated beforehand.
GL15C.glBufferData(GL15.GL_ARRAY_BUFFER, uploadBuffer.remaining(), GL15C.GL_DYNAMIC_DRAW);
// interestingly bufferSubData renders faster than glMapBuffer
// even though OpenGLInsights-AsynchronousBufferTransfers says glMapBuffer
// is faster for transferring data. They must put the data in different memory
// or something.
GL15C.glBufferSubData(GL15.GL_ARRAY_BUFFER, 0, uploadBuffer);
// // buffer mapping //
// // no stutter 50% GPU useage
// // stores everything in system memory instead of GPU memory
// // making rendering much slower
//
// GL45.glBindBuffer(GL45.GL_ARRAY_BUFFER, vbo.id);
//
// ByteBuffer vboBuffer = null;
// try
// {
// vboBuffer = GL45.glMapBufferRange(GL45.GL_ARRAY_BUFFER, 0, uploadBuffer.capacity(), GL45.GL_MAP_WRITE_BIT | GL45.GL_MAP_UNSYNCHRONIZED_BIT);
// if (vboBuffer == null)
// {
// GL45.glBufferData(GL45.GL_ARRAY_BUFFER, uploadBuffer.capacity() * 4, GL45.GL_STREAM_DRAW);
// GL45.glBufferSubData(GL45.GL_ARRAY_BUFFER, 0, uploadBuffer);
//
// ClientProxy.LOGGER.info("null");
// }
// else
// {
// vboBuffer.put(uploadBuffer);
//// ClientProxy.LOGGER.info("not null");
// }
// }
// catch(Exception e)
// {
// ClientProxy.LOGGER.info(e.getClass().getSimpleName());
//// e.printStackTrace();
// }
// finally
// {
// GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER);
// GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
// }
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
// // bufferstorage //
// // to test: uncomment the bufferstorage lines in setupBuffers as well
// // then reboot the game
//
// // moderate stutter 50% gpu
// // stores everything in system memory instead of GPU memory
// // making rendering much slower
//
// GL45.glBindBuffer(GL45.GL_ARRAY_BUFFER, vbo.id);
//
// try
// {
// ByteBuffer vboBuffer = GL45.glMapBufferRange(GL45.GL_ARRAY_BUFFER, 0, uploadBuffer.capacity(), GL45.GL_MAP_WRITE_BIT | GL45.GL_MAP_UNSYNCHRONIZED_BIT);
// if (vboBuffer == null)
// {
// ClientProxy.LOGGER.info("mapping fail");
// }
// else
// {
// vboBuffer.put(uploadBuffer);
// }
// }
// catch(Exception e)
// {
// ClientProxy.LOGGER.info(e.getClass().getSimpleName());
// //e.printStackTrace();
// }
// finally
// {
// GL45.glUnmapBuffer(GL45.GL_ARRAY_BUFFER);
// GL45.glBindBuffer(GL45.GL_ARRAY_BUFFER, 0);
// }
// hybrid subData/bufferData //
// less stutter 12% GPU usage
GL45.glBindBuffer(GL45.GL_ARRAY_BUFFER, vbo.id);
long size = GL45.glGetBufferParameteri64(GL45.GL_ARRAY_BUFFER, GL45.GL_BUFFER_SIZE);
if (size < uploadBuffer.capacity() * 4)
{
GL45.glBufferData(GL45.GL_ARRAY_BUFFER, uploadBuffer.capacity() * 5, GL45.GL_STREAM_DRAW);
ClientProxy.LOGGER.info("expand buffer: " + size + " -> " + (uploadBuffer.capacity() * 4));
}
GL45.glBufferSubData(GL45.GL_ARRAY_BUFFER, 0, uploadBuffer);
GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER);
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
// // old method - bufferData
// // bad stuttering 12% GPU usage
//
// GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo.id);
// // subData only works if the memory is allocated beforehand.
// GL15C.glBufferData(GL15.GL_ARRAY_BUFFER, uploadBuffer.remaining(), GL15C.GL_DYNAMIC_DRAW);
//
// // interestingly bufferSubData renders faster than glMapBuffer
// // even though OpenGLInsights-AsynchronousBufferTransfers says glMapBuffer
// // is faster for transferring data. They must put the data in different memory
// // or something.
// GL15C.glBufferSubData(GL15.GL_ARRAY_BUFFER, 0, uploadBuffer);
// GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
}
@@ -630,6 +745,7 @@ public class LodBufferBuilder
drawableVbos = buildableVbos;
buildableVbos = tmpVbo;
drawableCenterChunkPos = buildableCenterChunkPos;
// the vbos have been swapped
@@ -100,10 +100,6 @@ public class GlProxy
/**
* A wrapper function to make switching contexts easier. <br>
* Does nothing if the calling thread is already using newContext.
*
* @throws IllegalStateException if unable to change to newContext. <br>
* This exception should never be thrown if
* switching to GlProxyContext.NONE
*/
public void setGlContext(GlProxyContext newContext)
{