136 lines
3.9 KiB
Java
136 lines
3.9 KiB
Java
package com.mojang.blaze3d.buffers;
|
|
|
|
import com.mojang.blaze3d.platform.GlStateManager;
|
|
import com.mojang.jtracy.MemoryPool;
|
|
import com.mojang.jtracy.TracyClient;
|
|
import java.nio.ByteBuffer;
|
|
import net.fabricmc.api.EnvType;
|
|
import net.fabricmc.api.Environment;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public class GpuBuffer implements AutoCloseable {
|
|
private static final MemoryPool MEMORY_POOl = TracyClient.createMemoryPool("GPU Buffers");
|
|
private final BufferType type;
|
|
private final BufferUsage usage;
|
|
private boolean closed;
|
|
private boolean initialized = false;
|
|
public final int handle;
|
|
public int size;
|
|
|
|
public GpuBuffer(BufferType bufferType, BufferUsage bufferUsage, int i) {
|
|
this.type = bufferType;
|
|
this.size = i;
|
|
this.usage = bufferUsage;
|
|
this.handle = GlStateManager._glGenBuffers();
|
|
}
|
|
|
|
public GpuBuffer(BufferType bufferType, BufferUsage bufferUsage, ByteBuffer byteBuffer) {
|
|
this(bufferType, bufferUsage, byteBuffer.remaining());
|
|
this.write(byteBuffer, 0);
|
|
}
|
|
|
|
public void resize(int i) {
|
|
if (this.closed) {
|
|
throw new IllegalStateException("Buffer already closed");
|
|
} else {
|
|
if (this.initialized) {
|
|
MEMORY_POOl.free(this.handle);
|
|
}
|
|
|
|
this.size = i;
|
|
if (this.usage.writable) {
|
|
this.initialized = false;
|
|
} else {
|
|
this.bind();
|
|
GlStateManager._glBufferData(this.type.id, i, this.usage.id);
|
|
MEMORY_POOl.malloc(this.handle, i);
|
|
this.initialized = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void write(ByteBuffer byteBuffer, int i) {
|
|
if (this.closed) {
|
|
throw new IllegalStateException("Buffer already closed");
|
|
} else if (!this.usage.writable) {
|
|
throw new IllegalStateException("Buffer is not writable");
|
|
} else {
|
|
int j = byteBuffer.remaining();
|
|
if (j + i > this.size) {
|
|
throw new IllegalArgumentException(
|
|
"Cannot write more data than this buffer can hold (attempting to write " + j + " bytes at offset " + i + " to " + this.size + " size buffer)"
|
|
);
|
|
} else {
|
|
this.bind();
|
|
if (this.initialized) {
|
|
GlStateManager._glBufferSubData(this.type.id, i, byteBuffer);
|
|
} else if (i == 0 && j == this.size) {
|
|
GlStateManager._glBufferData(this.type.id, byteBuffer, this.usage.id);
|
|
MEMORY_POOl.malloc(this.handle, this.size);
|
|
this.initialized = true;
|
|
} else {
|
|
GlStateManager._glBufferData(this.type.id, this.size, this.usage.id);
|
|
GlStateManager._glBufferSubData(this.type.id, i, byteBuffer);
|
|
MEMORY_POOl.malloc(this.handle, this.size);
|
|
this.initialized = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Nullable
|
|
public GpuBuffer.ReadView read() {
|
|
return this.read(0, this.size);
|
|
}
|
|
|
|
@Nullable
|
|
public GpuBuffer.ReadView read(int i, int j) {
|
|
if (this.closed) {
|
|
throw new IllegalStateException("Buffer already closed");
|
|
} else if (!this.usage.readable) {
|
|
throw new IllegalStateException("Buffer is not readable");
|
|
} else if (i + j > this.size) {
|
|
throw new IllegalArgumentException(
|
|
"Cannot read more data than this buffer can hold (attempting to read " + j + " bytes at offset " + i + " from " + this.size + " size buffer)"
|
|
);
|
|
} else {
|
|
this.bind();
|
|
ByteBuffer byteBuffer = GlStateManager._glMapBufferRange(this.type.id, i, j, 1);
|
|
return byteBuffer == null ? null : new GpuBuffer.ReadView(this.type.id, byteBuffer);
|
|
}
|
|
}
|
|
|
|
public void close() {
|
|
if (!this.closed) {
|
|
this.closed = true;
|
|
GlStateManager._glDeleteBuffers(this.handle);
|
|
if (this.initialized) {
|
|
MEMORY_POOl.free(this.handle);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void bind() {
|
|
GlStateManager._glBindBuffer(this.type.id, this.handle);
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public static class ReadView implements AutoCloseable {
|
|
private final int target;
|
|
private final ByteBuffer data;
|
|
|
|
protected ReadView(int i, ByteBuffer byteBuffer) {
|
|
this.target = i;
|
|
this.data = byteBuffer;
|
|
}
|
|
|
|
public ByteBuffer data() {
|
|
return this.data;
|
|
}
|
|
|
|
public void close() {
|
|
GlStateManager._glUnmapBuffer(this.target);
|
|
}
|
|
}
|
|
}
|