mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-07 12:56:31 +01:00
So unsafe it wrapped back around
- Convert buffer mapping to unsafe - Implement gpu memory tracking - Fix massive gl resource leak - Fix GPU memory leak caused by not deleting gl resources - Fix CPU memory leak caused by not deleting meshes in Models - Remove PersistentGlBuffer, merge GlBuffer and MappedGlBuffer
This commit is contained in:
parent
293d6ee59c
commit
a1553b04e7
22 changed files with 191 additions and 359 deletions
|
@ -6,13 +6,13 @@ import com.jozufozu.flywheel.core.source.FileResolution;
|
||||||
|
|
||||||
public abstract class UniformProvider {
|
public abstract class UniformProvider {
|
||||||
|
|
||||||
protected ByteBuffer buffer;
|
protected long ptr;
|
||||||
protected Notifier notifier;
|
protected Notifier notifier;
|
||||||
|
|
||||||
public abstract int getSize();
|
public abstract int getSize();
|
||||||
|
|
||||||
public void updatePtr(ByteBuffer backing, Notifier notifier) {
|
public void updatePtr(long ptr, Notifier notifier) {
|
||||||
this.buffer = backing;
|
this.ptr = ptr;
|
||||||
this.notifier = notifier;
|
this.notifier = notifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@ import org.lwjgl.opengl.GL32;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlObject;
|
import com.jozufozu.flywheel.backend.gl.GlObject;
|
||||||
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
|
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
|
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
|
||||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
|
|
|
@ -1,49 +1,105 @@
|
||||||
package com.jozufozu.flywheel.backend.gl.buffer;
|
package com.jozufozu.flywheel.backend.gl.buffer;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import static org.lwjgl.opengl.GL32.*;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL20;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlObject;
|
import com.jozufozu.flywheel.backend.gl.GlObject;
|
||||||
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
|
import com.jozufozu.flywheel.backend.gl.error.GlError;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.error.GlException;
|
||||||
|
import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker;
|
||||||
|
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||||
|
|
||||||
public abstract class GlBuffer extends GlObject {
|
public class GlBuffer extends GlObject {
|
||||||
|
|
||||||
/**
|
|
||||||
* Request a Persistent mapped buffer.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* If Persistent buffers are supported, this will provide one. Otherwise it will fall back to a classic mapped
|
|
||||||
* buffer.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param type The type of buffer you want.
|
|
||||||
* @return A buffer that will be persistent if the driver supports it.
|
|
||||||
*/
|
|
||||||
public static GlBuffer requestPersistent(GlBufferType type) {
|
|
||||||
if (GlCompat.getInstance()
|
|
||||||
.bufferStorageSupported()) {
|
|
||||||
return new PersistentGlBuffer(type);
|
|
||||||
} else {
|
|
||||||
return new MappedGlBuffer(type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final GlBufferType type;
|
public final GlBufferType type;
|
||||||
|
protected final GlBufferUsage usage;
|
||||||
/**
|
/**
|
||||||
* The size (in bytes) of the buffer on the GPU.
|
* The size (in bytes) of the buffer on the GPU.
|
||||||
*/
|
*/
|
||||||
protected long size;
|
protected long size;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How much extra room to give the buffer when we reallocate.
|
* How much extra room to give the buffer when we reallocate.
|
||||||
*/
|
*/
|
||||||
protected int growthMargin;
|
protected int growthMargin;
|
||||||
|
|
||||||
public GlBuffer(GlBufferType type) {
|
public GlBuffer(GlBufferType type) {
|
||||||
setHandle(GL20.glGenBuffers());
|
this(type, GlBufferUsage.STATIC_DRAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GlBuffer(GlBufferType type, GlBufferUsage usage) {
|
||||||
|
setHandle(glGenBuffers());
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
this.usage = usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean ensureCapacity(long size) {
|
||||||
|
if (size < 0) {
|
||||||
|
throw new IllegalArgumentException("Size " + size + " < 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.size == 0) {
|
||||||
|
this.size = size;
|
||||||
|
bind();
|
||||||
|
glBufferData(type.glEnum, size, usage.glEnum);
|
||||||
|
FlwMemoryTracker._allocGPUMemory(size);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size > this.size) {
|
||||||
|
var oldSize = this.size;
|
||||||
|
this.size = size + growthMargin;
|
||||||
|
|
||||||
|
realloc(oldSize, this.size);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void realloc(long oldSize, long newSize) {
|
||||||
|
FlwMemoryTracker._freeGPUMemory(oldSize);
|
||||||
|
FlwMemoryTracker._allocGPUMemory(newSize);
|
||||||
|
var oldHandle = handle();
|
||||||
|
var newHandle = glGenBuffers();
|
||||||
|
|
||||||
|
GlBufferType.COPY_READ_BUFFER.bind(oldHandle);
|
||||||
|
type.bind(newHandle);
|
||||||
|
|
||||||
|
glBufferData(type.glEnum, newSize, usage.glEnum);
|
||||||
|
glCopyBufferSubData(GlBufferType.COPY_READ_BUFFER.glEnum, type.glEnum, 0, 0, oldSize);
|
||||||
|
|
||||||
|
glDeleteBuffers(oldHandle);
|
||||||
|
setHandle(newHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void upload(MemoryBlock directBuffer) {
|
||||||
|
bind();
|
||||||
|
FlwMemoryTracker._freeGPUMemory(size);
|
||||||
|
nglBufferData(type.glEnum, directBuffer.size(), directBuffer.ptr(), usage.glEnum);
|
||||||
|
this.size = directBuffer.size();
|
||||||
|
FlwMemoryTracker._allocGPUMemory(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MappedBuffer map() {
|
||||||
|
bind();
|
||||||
|
long ptr = nglMapBufferRange(type.glEnum, 0, size, GL_MAP_WRITE_BIT);
|
||||||
|
|
||||||
|
if (ptr == MemoryUtil.NULL) {
|
||||||
|
throw new GlException(GlError.poll(), "Could not map buffer");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MappedBuffer(this, ptr, 0, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPersistent() {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGrowthMargin(int growthMargin) {
|
public void setGrowthMargin(int growthMargin) {
|
||||||
|
@ -66,24 +122,8 @@ public abstract class GlBuffer extends GlObject {
|
||||||
type.unbind();
|
type.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void upload(ByteBuffer directBuffer);
|
|
||||||
|
|
||||||
public abstract MappedBuffer map();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensure that the buffer has at least enough room to store {@code size} bytes.
|
|
||||||
*
|
|
||||||
* @return {@code true} if the buffer moved.
|
|
||||||
*/
|
|
||||||
public abstract boolean ensureCapacity(long size);
|
|
||||||
|
|
||||||
protected void deleteInternal(int handle) {
|
protected void deleteInternal(int handle) {
|
||||||
GL20.glDeleteBuffers(handle);
|
glDeleteBuffers(handle);
|
||||||
|
FlwMemoryTracker._freeGPUMemory(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates that this buffer need not be #flush()'d for its contents to sync.
|
|
||||||
* @return true if this buffer is persistently mapped.
|
|
||||||
*/
|
|
||||||
public abstract boolean isPersistent();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.jozufozu.flywheel.backend.gl.buffer;
|
package com.jozufozu.flywheel.backend.gl.buffer;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import static org.lwjgl.system.MemoryUtil.NULL;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL15;
|
import org.lwjgl.opengl.GL15;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
@ -11,10 +11,10 @@ public class MappedBuffer implements AutoCloseable {
|
||||||
private final long length;
|
private final long length;
|
||||||
private final GlBuffer owner;
|
private final GlBuffer owner;
|
||||||
private final boolean persistent;
|
private final boolean persistent;
|
||||||
private ByteBuffer internal;
|
private long ptr;
|
||||||
|
|
||||||
public MappedBuffer(GlBuffer owner, ByteBuffer internal, long offset, long length) {
|
public MappedBuffer(GlBuffer owner, long ptr, long offset, long length) {
|
||||||
this.internal = internal;
|
this.ptr = ptr;
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
this.offset = offset;
|
this.offset = offset;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
|
@ -27,19 +27,11 @@ public class MappedBuffer implements AutoCloseable {
|
||||||
public void flush() {
|
public void flush() {
|
||||||
if (persistent) return;
|
if (persistent) return;
|
||||||
|
|
||||||
if (internal == null) return;
|
if (ptr == NULL) return;
|
||||||
|
|
||||||
owner.bind();
|
owner.bind();
|
||||||
GL15.glUnmapBuffer(owner.getType().glEnum);
|
GL15.glUnmapBuffer(owner.getType().glEnum);
|
||||||
internal = null;
|
ptr = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
public MappedBuffer position(int p) {
|
|
||||||
if (p < offset || p >= offset + length) {
|
|
||||||
throw new IndexOutOfBoundsException("Index " + p + " is not mapped");
|
|
||||||
}
|
|
||||||
internal.position(p - (int) offset);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -47,12 +39,8 @@ public class MappedBuffer implements AutoCloseable {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer unwrap() {
|
public long getPtr() {
|
||||||
return internal;
|
return ptr;
|
||||||
}
|
|
||||||
|
|
||||||
public long getMemAddress() {
|
|
||||||
return MemoryUtil.memAddress(internal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear(long clearStart, long clearLength) {
|
public void clear(long clearStart, long clearLength) {
|
||||||
|
@ -64,7 +52,7 @@ public class MappedBuffer implements AutoCloseable {
|
||||||
throw new IndexOutOfBoundsException("Clear range [" + clearStart + "," + (clearStart + clearLength) + "] is not mapped");
|
throw new IndexOutOfBoundsException("Clear range [" + clearStart + "," + (clearStart + clearLength) + "] is not mapped");
|
||||||
}
|
}
|
||||||
|
|
||||||
long addr = MemoryUtil.memAddress(unwrap()) + clearStart;
|
long addr = ptr + clearStart;
|
||||||
|
|
||||||
MemoryUtil.memSet(addr, 0, clearLength);
|
MemoryUtil.memSet(addr, 0, clearLength);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
package com.jozufozu.flywheel.backend.gl.buffer;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL30;
|
|
||||||
import org.lwjgl.opengl.GL32;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.error.GlError;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.error.GlException;
|
|
||||||
|
|
||||||
public class MappedGlBuffer extends GlBuffer {
|
|
||||||
|
|
||||||
protected final GlBufferUsage usage;
|
|
||||||
|
|
||||||
public MappedGlBuffer(GlBufferType type) {
|
|
||||||
this(type, GlBufferUsage.STATIC_DRAW);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MappedGlBuffer(GlBufferType type, GlBufferUsage usage) {
|
|
||||||
super(type);
|
|
||||||
this.usage = usage;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean ensureCapacity(long size) {
|
|
||||||
if (size < 0) {
|
|
||||||
throw new IllegalArgumentException("Size " + size + " < 0");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.size == 0) {
|
|
||||||
this.size = size;
|
|
||||||
bind();
|
|
||||||
GL32.glBufferData(type.glEnum, size, usage.glEnum);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size > this.size) {
|
|
||||||
var oldSize = this.size;
|
|
||||||
this.size = size + growthMargin;
|
|
||||||
|
|
||||||
realloc(oldSize, this.size);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void realloc(long oldSize, long newSize) {
|
|
||||||
var oldHandle = handle();
|
|
||||||
var newHandle = GL32.glGenBuffers();
|
|
||||||
|
|
||||||
GlBufferType.COPY_READ_BUFFER.bind(oldHandle);
|
|
||||||
type.bind(newHandle);
|
|
||||||
|
|
||||||
GL32.glBufferData(type.glEnum, newSize, usage.glEnum);
|
|
||||||
GL32.glCopyBufferSubData(GlBufferType.COPY_READ_BUFFER.glEnum, type.glEnum, 0, 0, oldSize);
|
|
||||||
|
|
||||||
delete();
|
|
||||||
setHandle(newHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void upload(ByteBuffer directBuffer) {
|
|
||||||
bind();
|
|
||||||
GL32.glBufferData(type.glEnum, directBuffer, usage.glEnum);
|
|
||||||
this.size = directBuffer.capacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MappedBuffer map() {
|
|
||||||
bind();
|
|
||||||
ByteBuffer byteBuffer = GL30.glMapBufferRange(type.glEnum, 0, size, GL30.GL_MAP_WRITE_BIT);
|
|
||||||
|
|
||||||
if (byteBuffer == null) {
|
|
||||||
throw new GlException(GlError.poll(), "Could not map buffer");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new MappedBuffer(this, byteBuffer, 0, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPersistent() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,124 +0,0 @@
|
||||||
package com.jozufozu.flywheel.backend.gl.buffer;
|
|
||||||
|
|
||||||
import static org.lwjgl.opengl.GL30.GL_MAP_WRITE_BIT;
|
|
||||||
import static org.lwjgl.opengl.GL44.GL_MAP_COHERENT_BIT;
|
|
||||||
import static org.lwjgl.opengl.GL44.GL_MAP_PERSISTENT_BIT;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.lwjgl.opengl.GL32;
|
|
||||||
import org.lwjgl.system.MemoryUtil;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.error.GlError;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.error.GlException;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
|
|
||||||
|
|
||||||
public class PersistentGlBuffer extends GlBuffer {
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private MappedBuffer access;
|
|
||||||
private final int storageFlags;
|
|
||||||
|
|
||||||
public PersistentGlBuffer(GlBufferType type) {
|
|
||||||
super(type);
|
|
||||||
|
|
||||||
storageFlags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean ensureCapacity(long size) {
|
|
||||||
if (size < 0) {
|
|
||||||
throw new IllegalArgumentException("Size " + size + " < 0");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.size == 0) {
|
|
||||||
this.size = size;
|
|
||||||
bind();
|
|
||||||
GlCompat.getInstance().bufferStorage.bufferStorage(type, this.size, storageFlags);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size > this.size) {
|
|
||||||
var oldSize = this.size;
|
|
||||||
this.size = size + growthMargin;
|
|
||||||
|
|
||||||
realloc(this.size, oldSize);
|
|
||||||
|
|
||||||
access = null;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void upload(ByteBuffer directBuffer) {
|
|
||||||
ensureCapacity(directBuffer.capacity());
|
|
||||||
|
|
||||||
var access = getWriteAccess();
|
|
||||||
|
|
||||||
ByteBuffer ourBuffer = access.unwrap();
|
|
||||||
|
|
||||||
ourBuffer.reset();
|
|
||||||
|
|
||||||
MemoryUtil.memCopy(directBuffer, ourBuffer);
|
|
||||||
|
|
||||||
int uploadSize = directBuffer.remaining();
|
|
||||||
int ourSize = ourBuffer.capacity();
|
|
||||||
|
|
||||||
if (uploadSize < ourSize) {
|
|
||||||
long clearFrom = access.getMemAddress() + uploadSize;
|
|
||||||
MemoryUtil.memSet(clearFrom, 0, ourSize - uploadSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void mapToClientMemory() {
|
|
||||||
bind();
|
|
||||||
ByteBuffer byteBuffer = GL32.glMapBufferRange(type.glEnum, 0, size, storageFlags);
|
|
||||||
|
|
||||||
if (byteBuffer == null) {
|
|
||||||
throw new GlException(GlError.poll(), "Could not map buffer");
|
|
||||||
}
|
|
||||||
|
|
||||||
access = new MappedBuffer(this, byteBuffer, 0, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void realloc(long newSize, long oldSize) {
|
|
||||||
int oldHandle = handle();
|
|
||||||
int newHandle = GL32.glGenBuffers();
|
|
||||||
|
|
||||||
GlBufferType.COPY_READ_BUFFER.bind(oldHandle);
|
|
||||||
type.bind(newHandle);
|
|
||||||
|
|
||||||
GlCompat.getInstance().bufferStorage.bufferStorage(type, newSize, storageFlags);
|
|
||||||
|
|
||||||
GL32.glCopyBufferSubData(GlBufferType.COPY_READ_BUFFER.glEnum, type.glEnum, 0, 0, oldSize);
|
|
||||||
|
|
||||||
delete();
|
|
||||||
setHandle(newHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MappedBuffer map() {
|
|
||||||
return getWriteAccess()
|
|
||||||
.position(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private MappedBuffer getWriteAccess() {
|
|
||||||
if (access == null) {
|
|
||||||
mapToClientMemory();
|
|
||||||
}
|
|
||||||
|
|
||||||
return access;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPersistent() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -27,7 +27,7 @@ import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
* The instancer manager is shared between the different instance managers.
|
* The instancer manager is shared between the different instance managers.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public class InstanceWorld {
|
public class InstanceWorld implements AutoCloseable {
|
||||||
protected final Engine engine;
|
protected final Engine engine;
|
||||||
protected final InstanceManager<Entity> entities;
|
protected final InstanceManager<Entity> entities;
|
||||||
protected final InstanceManager<BlockEntity> blockEntities;
|
protected final InstanceManager<BlockEntity> blockEntities;
|
||||||
|
@ -149,4 +149,8 @@ public class InstanceWorld {
|
||||||
.forEach(entities::add);
|
.forEach(entities::add);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ public class DrawBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the draw buffer to have no vertices.
|
* Reset the draw buffer to have no vertices.<p>
|
||||||
*
|
*
|
||||||
* Does not clear the backing buffer.
|
* Does not clear the backing buffer.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -3,18 +3,15 @@ package com.jozufozu.flywheel.backend.instancing.instancing;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.lwjgl.system.MemoryUtil;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.Flywheel;
|
import com.jozufozu.flywheel.Flywheel;
|
||||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||||
import com.jozufozu.flywheel.api.struct.StructType;
|
import com.jozufozu.flywheel.api.struct.StructType;
|
||||||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||||
import com.jozufozu.flywheel.backend.gl.array.GlVertexArray;
|
import com.jozufozu.flywheel.backend.gl.array.GlVertexArray;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferUsage;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferUsage;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
|
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
|
||||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||||
|
|
||||||
|
@ -45,7 +42,7 @@ public class GPUInstancer<D extends InstancedPart> extends AbstractInstancer<D>
|
||||||
public void init() {
|
public void init() {
|
||||||
if (vbo != null) return;
|
if (vbo != null) return;
|
||||||
|
|
||||||
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER, GlBufferUsage.DYNAMIC_DRAW);
|
vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER, GlBufferUsage.DYNAMIC_DRAW);
|
||||||
vbo.setGrowthMargin(instanceFormat.getStride() * 16);
|
vbo.setGrowthMargin(instanceFormat.getStride() * 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,8 +88,8 @@ public class GPUInstancer<D extends InstancedPart> extends AbstractInstancer<D>
|
||||||
buf.clear(clearStart, clearLength);
|
buf.clear(clearStart, clearLength);
|
||||||
|
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
final long ptr = MemoryUtil.memAddress(buf.unwrap());
|
final long ptr = buf.getPtr();
|
||||||
final int stride = structType.getLayout().getStride();
|
final long stride = structType.getLayout().getStride();
|
||||||
final StructWriter<D> writer = structType.getWriter();
|
final StructWriter<D> writer = structType.getWriter();
|
||||||
|
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.jozufozu.flywheel.backend.instancing.instancing;
|
package com.jozufozu.flywheel.backend.instancing.instancing;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -10,16 +9,14 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.lwjgl.opengl.GL32;
|
import org.lwjgl.opengl.GL32;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.Flywheel;
|
import com.jozufozu.flywheel.Flywheel;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.backend.gl.GlPrimitive;
|
import com.jozufozu.flywheel.backend.gl.GlPrimitive;
|
||||||
import com.jozufozu.flywheel.backend.gl.array.GlVertexArray;
|
import com.jozufozu.flywheel.backend.gl.array.GlVertexArray;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||||
import com.jozufozu.flywheel.core.model.Mesh;
|
import com.jozufozu.flywheel.core.model.Mesh;
|
||||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||||
|
@ -58,7 +55,7 @@ public class MeshPool {
|
||||||
* Create a new mesh pool.
|
* Create a new mesh pool.
|
||||||
*/
|
*/
|
||||||
public MeshPool() {
|
public MeshPool() {
|
||||||
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
|
vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER);
|
||||||
|
|
||||||
vbo.setGrowthMargin(2048);
|
vbo.setGrowthMargin(2048);
|
||||||
}
|
}
|
||||||
|
@ -141,13 +138,13 @@ public class MeshPool {
|
||||||
|
|
||||||
private void uploadAll() {
|
private void uploadAll() {
|
||||||
try (MappedBuffer mapped = vbo.map()) {
|
try (MappedBuffer mapped = vbo.map()) {
|
||||||
ByteBuffer buffer = mapped.unwrap();
|
long ptr = mapped.getPtr();
|
||||||
|
|
||||||
int byteIndex = 0;
|
int byteIndex = 0;
|
||||||
for (BufferedMesh model : allBuffered) {
|
for (BufferedMesh model : allBuffered) {
|
||||||
model.byteIndex = byteIndex;
|
model.byteIndex = byteIndex;
|
||||||
|
|
||||||
model.buffer(buffer);
|
model.buffer(ptr);
|
||||||
|
|
||||||
byteIndex += model.mesh.size();
|
byteIndex += model.mesh.size();
|
||||||
}
|
}
|
||||||
|
@ -159,7 +156,7 @@ public class MeshPool {
|
||||||
|
|
||||||
private void uploadPending() {
|
private void uploadPending() {
|
||||||
try (MappedBuffer mapped = vbo.map()) {
|
try (MappedBuffer mapped = vbo.map()) {
|
||||||
ByteBuffer buffer = mapped.unwrap();
|
long buffer = mapped.getPtr();
|
||||||
for (BufferedMesh model : pendingUpload) {
|
for (BufferedMesh model : pendingUpload) {
|
||||||
model.buffer(buffer);
|
model.buffer(buffer);
|
||||||
}
|
}
|
||||||
|
@ -240,10 +237,8 @@ public class MeshPool {
|
||||||
this.deleted = true;
|
this.deleted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buffer(ByteBuffer buffer) {
|
private void buffer(long ptr) {
|
||||||
buffer.position((int) this.byteIndex);
|
this.mesh.write(ptr + byteIndex);
|
||||||
long ptr = MemoryUtil.memAddress(buffer);
|
|
||||||
this.mesh.write(ptr);
|
|
||||||
|
|
||||||
this.boundTo.clear();
|
this.boundTo.clear();
|
||||||
this.gpuResident = true;
|
this.gpuResident = true;
|
||||||
|
|
|
@ -3,13 +3,14 @@ package com.jozufozu.flywheel.core;
|
||||||
import static org.lwjgl.opengl.GL11.GL_TRIANGLES;
|
import static org.lwjgl.opengl.GL11.GL_TRIANGLES;
|
||||||
import static org.lwjgl.opengl.GL11.glDrawArrays;
|
import static org.lwjgl.opengl.GL11.glDrawArrays;
|
||||||
|
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.Flywheel;
|
import com.jozufozu.flywheel.Flywheel;
|
||||||
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
|
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
|
||||||
import com.jozufozu.flywheel.backend.gl.array.GlVertexArray;
|
import com.jozufozu.flywheel.backend.gl.array.GlVertexArray;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||||
import com.jozufozu.flywheel.core.layout.CommonItems;
|
import com.jozufozu.flywheel.core.layout.CommonItems;
|
||||||
import com.jozufozu.flywheel.util.Lazy;
|
import com.jozufozu.flywheel.util.Lazy;
|
||||||
|
@ -34,13 +35,14 @@ public class FullscreenQuad {
|
||||||
|
|
||||||
private FullscreenQuad() {
|
private FullscreenQuad() {
|
||||||
try (var restoreState = GlStateTracker.getRestoreState()) {
|
try (var restoreState = GlStateTracker.getRestoreState()) {
|
||||||
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
|
vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER);
|
||||||
vbo.ensureCapacity(bufferSize);
|
vbo.ensureCapacity(bufferSize);
|
||||||
try (MappedBuffer buffer = vbo.map()) {
|
try (MappedBuffer buffer = vbo.map()) {
|
||||||
|
var ptr = buffer.getPtr();
|
||||||
|
|
||||||
buffer.unwrap()
|
for (var i = 0; i < vertices.length; i++) {
|
||||||
.asFloatBuffer()
|
MemoryUtil.memPutFloat(ptr + i * Float.BYTES, vertices[i]);
|
||||||
.put(vertices);
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Flywheel.LOGGER.error("Could not create fullscreen quad.", e);
|
Flywheel.LOGGER.error("Could not create fullscreen quad.", e);
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package com.jozufozu.flywheel.core;
|
package com.jozufozu.flywheel.core;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
@ -9,7 +7,7 @@ import org.lwjgl.system.MemoryUtil;
|
||||||
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer;
|
import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer;
|
||||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||||
|
|
||||||
|
@ -34,11 +32,11 @@ public class QuadConverter {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final MappedGlBuffer ebo;
|
private final GlBuffer ebo;
|
||||||
private int quadCapacity;
|
private int quadCapacity;
|
||||||
|
|
||||||
public QuadConverter() {
|
public QuadConverter() {
|
||||||
this.ebo = new MappedGlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER);
|
this.ebo = new GlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER);
|
||||||
this.quadCapacity = 0;
|
this.quadCapacity = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,9 +47,7 @@ public class QuadConverter {
|
||||||
ebo.ensureCapacity((long) indexCount * GlNumericType.UINT.getByteWidth());
|
ebo.ensureCapacity((long) indexCount * GlNumericType.UINT.getByteWidth());
|
||||||
|
|
||||||
try (MappedBuffer map = ebo.map()) {
|
try (MappedBuffer map = ebo.map()) {
|
||||||
ByteBuffer indices = map.unwrap();
|
fillBuffer(map.getPtr(), quads);
|
||||||
|
|
||||||
fillBuffer(indices, quads);
|
|
||||||
}
|
}
|
||||||
ebo.unbind();
|
ebo.unbind();
|
||||||
|
|
||||||
|
@ -66,32 +62,18 @@ public class QuadConverter {
|
||||||
this.quadCapacity = 0;
|
this.quadCapacity = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillBuffer(ByteBuffer indices, int quads) {
|
private void fillBuffer(long addr, int quads) {
|
||||||
long addr = MemoryUtil.memAddress(indices);
|
|
||||||
int numVertices = 4 * quads;
|
int numVertices = 4 * quads;
|
||||||
int baseVertex = 0;
|
int baseVertex = 0;
|
||||||
while (baseVertex < numVertices) {
|
while (baseVertex < numVertices) {
|
||||||
// writeQuadIndices(indices, baseVertex);
|
writeQuadIndices(addr, baseVertex);
|
||||||
writeQuadIndicesUnsafe(addr, baseVertex);
|
|
||||||
|
|
||||||
baseVertex += 4;
|
baseVertex += 4;
|
||||||
addr += 6 * 4;
|
addr += 6 * 4;
|
||||||
}
|
}
|
||||||
// ((Buffer) indices).flip();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeQuadIndices(ByteBuffer indices, int baseVertex) {
|
private void writeQuadIndices(long addr, int baseVertex) {
|
||||||
// triangle a
|
|
||||||
indices.putInt(baseVertex);
|
|
||||||
indices.putInt(baseVertex + 1);
|
|
||||||
indices.putInt(baseVertex + 2);
|
|
||||||
// triangle b
|
|
||||||
indices.putInt(baseVertex);
|
|
||||||
indices.putInt(baseVertex + 2);
|
|
||||||
indices.putInt(baseVertex + 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeQuadIndicesUnsafe(long addr, int baseVertex) {
|
|
||||||
// triangle a
|
// triangle a
|
||||||
MemoryUtil.memPutInt(addr, baseVertex);
|
MemoryUtil.memPutInt(addr, baseVertex);
|
||||||
MemoryUtil.memPutInt(addr + 4, baseVertex + 1);
|
MemoryUtil.memPutInt(addr + 4, baseVertex + 1);
|
||||||
|
@ -102,7 +84,7 @@ public class QuadConverter {
|
||||||
MemoryUtil.memPutInt(addr + 20, baseVertex + 3);
|
MemoryUtil.memPutInt(addr + 20, baseVertex + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure this gets reset first so it has a chance to repopulate
|
// make sure this gets reset first, so it has a chance to repopulate
|
||||||
public static void onRendererReload(ReloadRenderersEvent event) {
|
public static void onRendererReload(ReloadRenderersEvent event) {
|
||||||
if (INSTANCE != null) {
|
if (INSTANCE != null) {
|
||||||
INSTANCE.delete();
|
INSTANCE.delete();
|
||||||
|
|
|
@ -7,6 +7,8 @@ import com.jozufozu.flywheel.api.material.Material;
|
||||||
public interface Model {
|
public interface Model {
|
||||||
Map<Material, Mesh> getMeshes();
|
Map<Material, Mesh> getMeshes();
|
||||||
|
|
||||||
|
void delete();
|
||||||
|
|
||||||
default int getVertexCount() {
|
default int getVertexCount() {
|
||||||
int size = 0;
|
int size = 0;
|
||||||
for (Mesh mesh : getMeshes().values()) {
|
for (Mesh mesh : getMeshes().values()) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.jozufozu.flywheel.core.model;
|
package com.jozufozu.flywheel.core.model;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -41,8 +42,16 @@ public class Models {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onReload(ReloadRenderersEvent event) {
|
public static void onReload(ReloadRenderersEvent event) {
|
||||||
|
deleteAll(BLOCK_STATE.values());
|
||||||
|
deleteAll(PARTIAL.values());
|
||||||
|
deleteAll(PARTIAL_DIR.values());
|
||||||
|
|
||||||
BLOCK_STATE.clear();
|
BLOCK_STATE.clear();
|
||||||
PARTIAL.clear();
|
PARTIAL.clear();
|
||||||
PARTIAL_DIR.clear();
|
PARTIAL_DIR.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void deleteAll(Collection<Model> values) {
|
||||||
|
values.forEach(Model::delete);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,11 @@ public class SimpleLazyModel implements Model {
|
||||||
return ImmutableMap.of(material, supplier.get());
|
return ImmutableMap.of(material, supplier.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete() {
|
||||||
|
supplier.ifPresent(Mesh::close);
|
||||||
|
}
|
||||||
|
|
||||||
public int getVertexCount() {
|
public int getVertexCount() {
|
||||||
return supplier.map(Mesh::getVertexCount)
|
return supplier.map(Mesh::getVertexCount)
|
||||||
.orElse(0);
|
.orElse(0);
|
||||||
|
|
|
@ -19,6 +19,12 @@ public class TessellatedModel implements Model {
|
||||||
return meshes;
|
return meshes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete() {
|
||||||
|
meshes.values()
|
||||||
|
.forEach(Mesh::close);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isShadeSeparated() {
|
public boolean isShadeSeparated() {
|
||||||
return shadeSeparated;
|
return shadeSeparated;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,12 @@ public class FogProvider extends UniformProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update() {
|
public void update() {
|
||||||
if (buffer == null) {
|
if (ptr == MemoryUtil.NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var color = RenderSystem.getShaderFogColor();
|
var color = RenderSystem.getShaderFogColor();
|
||||||
|
|
||||||
long ptr = MemoryUtil.memAddress(buffer);
|
|
||||||
|
|
||||||
MemoryUtil.memPutFloat(ptr, color[0]);
|
MemoryUtil.memPutFloat(ptr, color[0]);
|
||||||
MemoryUtil.memPutFloat(ptr + 4, color[1]);
|
MemoryUtil.memPutFloat(ptr + 4, color[1]);
|
||||||
MemoryUtil.memPutFloat(ptr + 8, color[2]);
|
MemoryUtil.memPutFloat(ptr + 8, color[2]);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.jozufozu.flywheel.core.uniform;
|
package com.jozufozu.flywheel.core.uniform;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -11,8 +10,8 @@ import org.lwjgl.system.MemoryUtil;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.jozufozu.flywheel.api.uniform.UniformProvider;
|
import com.jozufozu.flywheel.api.uniform.UniformProvider;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker;
|
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||||
import com.jozufozu.flywheel.core.ComponentRegistry;
|
import com.jozufozu.flywheel.core.ComponentRegistry;
|
||||||
import com.jozufozu.flywheel.util.RenderMath;
|
import com.jozufozu.flywheel.util.RenderMath;
|
||||||
|
|
||||||
|
@ -33,13 +32,13 @@ public class UniformBuffer {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final MappedGlBuffer buffer;
|
private final GlBuffer buffer;
|
||||||
private final ByteBuffer data;
|
private final MemoryBlock data;
|
||||||
|
|
||||||
private final BitSet changedBytes;
|
private final BitSet changedBytes;
|
||||||
|
|
||||||
private UniformBuffer() {
|
private UniformBuffer() {
|
||||||
buffer = new MappedGlBuffer(GlBufferType.UNIFORM_BUFFER);
|
buffer = new GlBuffer(GlBufferType.UNIFORM_BUFFER);
|
||||||
|
|
||||||
Collection<UniformProvider> providers = ComponentRegistry.getAllUniformProviders();
|
Collection<UniformProvider> providers = ComponentRegistry.getAllUniformProviders();
|
||||||
|
|
||||||
|
@ -57,7 +56,7 @@ public class UniformBuffer {
|
||||||
|
|
||||||
allocatedProviders = builder.build();
|
allocatedProviders = builder.build();
|
||||||
|
|
||||||
data = FlwMemoryTracker.mallocBuffer(totalBytes);
|
data = MemoryBlock.mallocTracked(totalBytes);
|
||||||
changedBytes = new BitSet(totalBytes);
|
changedBytes = new BitSet(totalBytes);
|
||||||
|
|
||||||
for (Allocated p : allocatedProviders) {
|
for (Allocated p : allocatedProviders) {
|
||||||
|
@ -108,8 +107,8 @@ public class UniformBuffer {
|
||||||
changedBytes.set(offset, offset + size);
|
changedBytes.set(offset, offset + size);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updatePtr(ByteBuffer bufferBase) {
|
private void updatePtr(MemoryBlock bufferBase) {
|
||||||
provider.updatePtr(MemoryUtil.memSlice(bufferBase, offset, size), this);
|
provider.updatePtr(bufferBase.ptr() + offset, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniformProvider provider() {
|
public UniformProvider provider() {
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class ViewProvider extends UniformProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(RenderContext context) {
|
public void update(RenderContext context) {
|
||||||
if (buffer == null) {
|
if (ptr == MemoryUtil.NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,8 +52,6 @@ public class ViewProvider extends UniformProvider {
|
||||||
var vp = context.viewProjection().copy();
|
var vp = context.viewProjection().copy();
|
||||||
vp.multiplyWithTranslation(-camX, -camY, -camZ);
|
vp.multiplyWithTranslation(-camX, -camY, -camZ);
|
||||||
|
|
||||||
long ptr = MemoryUtil.memAddress(buffer);
|
|
||||||
|
|
||||||
MatrixWrite.writeUnsafe(vp, ptr);
|
MatrixWrite.writeUnsafe(vp, ptr);
|
||||||
MemoryUtil.memPutFloat(ptr + 64, camX);
|
MemoryUtil.memPutFloat(ptr + 64, camX);
|
||||||
MemoryUtil.memPutFloat(ptr + 68, camY);
|
MemoryUtil.memPutFloat(ptr + 68, camY);
|
||||||
|
|
|
@ -7,6 +7,7 @@ import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||||
import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker;
|
import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker;
|
||||||
import com.jozufozu.flywheel.light.LightUpdater;
|
import com.jozufozu.flywheel.light.LightUpdater;
|
||||||
|
import com.jozufozu.flywheel.util.StringUtil;
|
||||||
import com.jozufozu.flywheel.util.WorldAttached;
|
import com.jozufozu.flywheel.util.WorldAttached;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
@ -24,7 +25,7 @@ public class ForgeEvents {
|
||||||
|
|
||||||
InstancedRenderDispatcher.getDebugString(debug);
|
InstancedRenderDispatcher.getDebugString(debug);
|
||||||
|
|
||||||
debug.add("Memory Usage: CPU: " + FlwMemoryTracker.getCPUMemory() / 1024 + "KiB GPU: " + FlwMemoryTracker.getGPUMemory() / 1024 + "KiB");
|
debug.add("Memory Usage: CPU: " + StringUtil.formatBytes(FlwMemoryTracker.getCPUMemory()) + ", GPU: " + StringUtil.formatBytes(FlwMemoryTracker.getGPUMemory()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,17 +19,29 @@ import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker;
|
||||||
|
|
||||||
public class StringUtil {
|
public class StringUtil {
|
||||||
|
|
||||||
private static final NumberFormat timeFormat = new DecimalFormat("#0.000");
|
private static final NumberFormat THREE_DECIMAL_PLACES = new DecimalFormat("#0.000");
|
||||||
|
|
||||||
|
public static String formatBytes(long bytes) {
|
||||||
|
if (bytes < 1024) {
|
||||||
|
return bytes + " B";
|
||||||
|
} else if (bytes < 1024 * 1024) {
|
||||||
|
return THREE_DECIMAL_PLACES.format(bytes / 1024f) + " KB";
|
||||||
|
} else if (bytes < 1024 * 1024 * 1024) {
|
||||||
|
return THREE_DECIMAL_PLACES.format(bytes / 1024f / 1024f) + " MB";
|
||||||
|
} else {
|
||||||
|
return THREE_DECIMAL_PLACES.format(bytes / 1024f / 1024f / 1024f) + " GB";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static String formatTime(long ns) {
|
public static String formatTime(long ns) {
|
||||||
if (ns < 1000) {
|
if (ns < 1000) {
|
||||||
return ns + " ns";
|
return ns + " ns";
|
||||||
} else if (ns < 1000000) {
|
} else if (ns < 1000000) {
|
||||||
return timeFormat.format(ns / 1000.) + " μs";
|
return THREE_DECIMAL_PLACES.format(ns / 1000f) + " μs";
|
||||||
} else if (ns < 1000000000) {
|
} else if (ns < 1000000000) {
|
||||||
return timeFormat.format(ns / 1000000.) + " ms";
|
return THREE_DECIMAL_PLACES.format(ns / 1000000f) + " ms";
|
||||||
} else {
|
} else {
|
||||||
return timeFormat.format(ns / 1000000000.) + " s";
|
return THREE_DECIMAL_PLACES.format(ns / 1000000000f) + " s";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,16 @@ public class WorldAttached<T> {
|
||||||
i.remove();
|
i.remove();
|
||||||
} else {
|
} else {
|
||||||
// Prevent leaks
|
// Prevent leaks
|
||||||
map.remove(world);
|
Object attached = map.remove(world);
|
||||||
|
|
||||||
|
// No, *really* prevent leaks
|
||||||
|
if (attached instanceof AutoCloseable closeable) {
|
||||||
|
try {
|
||||||
|
closeable.close();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue