226 lines
8.4 KiB
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;
|
|
}
|
|
}
|