SimpleJavaEngine/src/main/java/speiger/src/coreengine/rendering/models/buffers/VertexBuffer.java

226 lines
8.4 KiB
Java

package speiger.src.coreengine.rendering.models.buffers;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.List;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL32;
import org.lwjgl.system.MemoryUtil;
import speiger.src.collections.ints.misc.pairs.IntObjectPair;
import speiger.src.coreengine.rendering.utils.AllocationTracker;
import speiger.src.coreengine.rendering.utils.values.BufferState;
import speiger.src.coreengine.rendering.utils.values.IGLValue.IGLBuffer;
import speiger.src.coreengine.utils.io.GameLog;
public class VertexBuffer {
protected final int id;
protected final IGLBuffer type;
protected BufferState state = BufferState.STATIC_DRAW;
protected int size;
public VertexBuffer(IGLBuffer type) {
this(type, GL15.glGenBuffers());
AllocationTracker.INSTANCE.track(this);
}
protected VertexBuffer(IGLBuffer type, int id) {
this.type = type;
this.id = id;
}
public static VertexBuffer wrap(IGLBuffer type, int id) {
return new VertexBuffer(type, id);
}
public VertexBuffer withState(BufferState state) {
this.state = state;
return this;
}
public int id() { return id; }
public IGLBuffer type() { return type; }
public BufferState state() { return state; }
public int size() { return size; }
protected void size(int newSize) { this.size = newSize; }
public VertexBuffer delete() {
AllocationTracker.INSTANCE.untrack(this);
GL15.glDeleteBuffers(id);
return this;
}
public VertexBuffer bind() {
GL15.glBindBuffer(type.glValue(), id);
return this;
}
public VertexBuffer unbind() {
GL15.glBindBuffer(type.glValue(), 0);
return this;
}
public VertexBuffer allocate(int totalBytes) {
this.size = totalBytes;
GL15.glBufferData(type.glValue(), totalBytes, state.glValue());
AllocationTracker.INSTANCE.addGPUBytes(totalBytes);
return this;
}
public VertexBuffer set(long pointer, int totalBytes) {
this.size = totalBytes;
GL15.nglBufferData(type.glValue(), totalBytes, pointer, state.glValue());
AllocationTracker.INSTANCE.addGPUBytes(totalBytes);
return this;
}
public VertexBuffer fill(long pointer, int totalBytes, int offset) {
GL15.nglBufferSubData(type.glValue(), offset, totalBytes, pointer);
AllocationTracker.INSTANCE.addGPUBytes(totalBytes);
return this;
}
public VertexBuffer read(long pointer, int totalBytes, int offset) {
GL15.nglGetBufferSubData(type.glValue(), offset, totalBytes, pointer);
AllocationTracker.INSTANCE.addGPUBytes(totalBytes);
return this;
}
private VertexBuffer read(Buffer buffer, int totalBytes, int offset) {
read(MemoryUtil.memAddress(buffer), totalBytes, offset);
buffer.flip();
return this;
}
public VertexBuffer set(ByteBuffer buffer) { return set(MemoryUtil.memAddress(buffer), buffer.remaining()); }
public VertexBuffer set(ShortBuffer buffer) { return set(MemoryUtil.memAddress(buffer), buffer.remaining() << 1); }
public VertexBuffer set(IntBuffer buffer) { return set(MemoryUtil.memAddress(buffer), buffer.remaining() << 2); }
public VertexBuffer set(FloatBuffer buffer) { return set(MemoryUtil.memAddress(buffer), buffer.remaining() << 2); }
public VertexBuffer fill(int offset, ByteBuffer buffer) { return fill(MemoryUtil.memAddress(buffer), buffer.remaining(), offset); }
public VertexBuffer fill(int offset, ShortBuffer buffer) { return fill(MemoryUtil.memAddress(buffer), buffer.remaining() << 1, offset); }
public VertexBuffer fill(int offset, IntBuffer buffer) { return fill(MemoryUtil.memAddress(buffer), buffer.remaining() << 2, offset); }
public VertexBuffer fill(int offset, FloatBuffer buffer) { return fill(MemoryUtil.memAddress(buffer), buffer.remaining() << 2, offset); }
public VertexBuffer read(int offset, ByteBuffer buffer) { return read(buffer, buffer.remaining(), offset); }
public VertexBuffer read(int offset, ShortBuffer buffer) { return read(buffer, buffer.remaining() << 1, offset); }
public VertexBuffer read(int offset, IntBuffer buffer) { return read(buffer, buffer.remaining() << 2, offset); }
public VertexBuffer read(int offset, FloatBuffer buffer) { return read(buffer, buffer.remaining() << 2, offset); }
public VertexBuffer set(byte[] data) {
ByteBuffer buffer = MemoryUtil.memAlloc(data.length).put(data).flip();
set(buffer);
MemoryUtil.memFree(buffer);
return this;
}
public VertexBuffer set(short[] data) {
ShortBuffer buffer = MemoryUtil.memAllocShort(data.length).put(data).flip();
set(buffer);
MemoryUtil.memFree(buffer);
return this;
}
public VertexBuffer set(int[] data) {
IntBuffer buffer = MemoryUtil.memAllocInt(data.length).put(data).flip();
set(buffer);
MemoryUtil.memFree(buffer);
return this;
}
public VertexBuffer set(float[] data) {
FloatBuffer buffer = MemoryUtil.memAllocFloat(data.length).put(data).flip();
set(buffer);
MemoryUtil.memFree(buffer);
return this;
}
public VertexBuffer fill(int offset, byte[] data) {
GL15.glMapBuffer(type.glValue(), GL15.GL_WRITE_ONLY).position(offset).put(data);
GL15.glUnmapBuffer(type.glValue());
AllocationTracker.INSTANCE.addGPUBytes(data.length);
return this;
}
public VertexBuffer fill(int offset, short[] data) {
GL15.glMapBuffer(type.glValue(), GL15.GL_WRITE_ONLY).position(offset).asShortBuffer().put(data);
GL15.glUnmapBuffer(type.glValue());
AllocationTracker.INSTANCE.addGPUBytes(data.length * 2L);
return this;
}
public VertexBuffer fill(int offset, int[] data) {
GL15.glMapBuffer(type.glValue(), GL15.GL_WRITE_ONLY).position(offset).asIntBuffer().put(data);
GL15.glUnmapBuffer(type.glValue());
AllocationTracker.INSTANCE.addGPUBytes(data.length * 4L);
return this;
}
public VertexBuffer fill(int offset, float[] data) {
GL15.glMapBuffer(type.glValue(), GL15.GL_WRITE_ONLY).position(offset).asFloatBuffer().put(data);
GL15.glUnmapBuffer(type.glValue());
AllocationTracker.INSTANCE.addGPUBytes(data.length * 4L);
return this;
}
public VertexBuffer fill(List<IntObjectPair<byte[]>> data) {
return fill(0, data);
}
public VertexBuffer fill(int offset, List<IntObjectPair<byte[]>> data) {
if(data.size() > 0) {
long totalInjected = 0;
ByteBuffer buffer = GL15.glMapBuffer(type.glValue(), GL15.GL_WRITE_ONLY);
for(int i = 0,m = data.size();i < m;i++) {
IntObjectPair<byte[]> entry = data.get(i);
buffer.position(entry.getIntKey() + offset);
buffer.put(entry.getValue());
totalInjected += entry.getValue().length;
}
buffer.flip();
if(!GL15.glUnmapBuffer(type.glValue())) GameLog.info("Memory Corruption?");
AllocationTracker.INSTANCE.addGPUBytes(totalInjected);
}
return this;
}
public VertexBuffer grow(int newSize) {
if(size >= newSize) throw new IllegalArgumentException("New Size ["+newSize+"] is smaller then the buffer ["+size+"]");
ByteBuffer buffer = GL15.glMapBuffer(type.glValue(), GL15.GL_READ_ONLY);
if(size != buffer.remaining()) throw new IllegalStateException("Grow Function found inconsisten data: Found=["+buffer.remaining()+"], Expected=["+size+"]");
ByteBuffer newBuff = MemoryUtil.memAlloc(newSize);
MemoryUtil.memCopy(MemoryUtil.memAddress(buffer), MemoryUtil.memAddress(newBuff), size);
newBuff.position(newSize).flip();
GL15.glUnmapBuffer(type.glValue());
AllocationTracker.INSTANCE.addGPUBytes(size);
set(MemoryUtil.memAddress(newBuff), newSize);
MemoryUtil.memFree(newBuff);
return this;
}
public VertexBuffer shrink(int newSize) {
if(size <= newSize) throw new IllegalArgumentException("New Size ["+newSize+"] is bigger then the buffer ["+size+"]");
ByteBuffer buffer = GL15.glMapBuffer(type.glValue(), GL15.GL_READ_WRITE);
if(size != buffer.remaining()) throw new IllegalStateException("Grow Function found inconsisten data: Found=["+buffer.remaining()+"], Expected=["+size+"]");
ByteBuffer newBuff = MemoryUtil.memAlloc(newSize);
MemoryUtil.memCopy(MemoryUtil.memAddress(buffer), MemoryUtil.memAddress(newBuff), newSize);
newBuff.position(newSize).flip();
GL15.glUnmapBuffer(type.glValue());
AllocationTracker.INSTANCE.addGPUBytes(size);
set(MemoryUtil.memAddress(newBuff), newSize);
MemoryUtil.memFree(newBuff);
return this;
}
public VertexBuffer shift(int source, int dest, int length) {
if(source < 0 || source + length >= size) throw new ArrayIndexOutOfBoundsException();
if(dest < 0 || dest + length >= size) throw new ArrayIndexOutOfBoundsException();
GL32.glCopyBufferSubData(id, id, source, dest, length);
AllocationTracker.INSTANCE.addGPUBytes(length*2);
return this;
}
}