mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-26 15:06:28 +01:00
GlBuffer tracks its size
- GlVertexArray#enableArrays
This commit is contained in:
parent
1594c56df2
commit
21d0db1364
10 changed files with 93 additions and 61 deletions
|
@ -1,5 +1,6 @@
|
|||
package com.jozufozu.flywheel.backend.gl;
|
||||
|
||||
import com.jozufozu.flywheel.util.AttribUtil;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
|
||||
public class GlVertexArray extends GlObject {
|
||||
|
@ -18,4 +19,8 @@ public class GlVertexArray extends GlObject {
|
|||
protected void deleteInternal(int handle) {
|
||||
GlStateManager._glDeleteVertexArrays(handle);
|
||||
}
|
||||
|
||||
public void enableArrays(int count) {
|
||||
AttribUtil.enableArrays(count);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,13 +9,6 @@ import com.jozufozu.flywheel.backend.gl.GlObject;
|
|||
|
||||
public abstract class GlBuffer extends GlObject {
|
||||
|
||||
protected final GlBufferType type;
|
||||
|
||||
public GlBuffer(GlBufferType type) {
|
||||
_create();
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a Persistent mapped buffer.
|
||||
*
|
||||
|
@ -35,10 +28,63 @@ public abstract class GlBuffer extends GlObject {
|
|||
}
|
||||
}
|
||||
|
||||
public GlBufferType getBufferTarget() {
|
||||
return type;
|
||||
protected final GlBufferType type;
|
||||
|
||||
/**
|
||||
* The size (in bytes) of the buffer on the GPU.
|
||||
*/
|
||||
protected long capacity;
|
||||
|
||||
/**
|
||||
* How much extra room to give the buffer when we reallocate.
|
||||
*/
|
||||
protected int growthMargin;
|
||||
|
||||
public GlBuffer(GlBufferType type) {
|
||||
_create();
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void setGrowthMargin(int growthMargin) {
|
||||
this.growthMargin = growthMargin;
|
||||
}
|
||||
|
||||
public long getCapacity() {
|
||||
return capacity;
|
||||
}
|
||||
|
||||
public MappedBuffer getBuffer() {
|
||||
return getBuffer(0, capacity);
|
||||
}
|
||||
|
||||
public abstract MappedBuffer getBuffer(long offset, long length);
|
||||
|
||||
/**
|
||||
* Ensure that the buffer has at least enough room to store size bytes.
|
||||
*
|
||||
* @return true if the buffer grew.
|
||||
*/
|
||||
public boolean ensureCapacity(long size) {
|
||||
if (size > capacity) {
|
||||
capacity = size + growthMargin;
|
||||
alloc(capacity);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this after all draw calls using this buffer are complete.
|
||||
*/
|
||||
public void doneForThisFrame() {
|
||||
|
||||
}
|
||||
|
||||
protected abstract void alloc(long size);
|
||||
|
||||
public abstract void upload(ByteBuffer directBuffer);
|
||||
|
||||
public void bind() {
|
||||
type.bind(handle());
|
||||
}
|
||||
|
@ -47,16 +93,6 @@ public abstract class GlBuffer extends GlObject {
|
|||
type.unbind();
|
||||
}
|
||||
|
||||
public void doneForThisFrame() {
|
||||
|
||||
}
|
||||
|
||||
public abstract void alloc(long size);
|
||||
|
||||
public abstract void upload(ByteBuffer directBuffer);
|
||||
|
||||
public abstract MappedBuffer getBuffer(int offset, int length);
|
||||
|
||||
protected void _create() {
|
||||
setHandle(GL20.glGenBuffers());
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ public class MappedGlBuffer extends GlBuffer implements Mappable {
|
|||
this.usage = usage;
|
||||
}
|
||||
|
||||
public void alloc(long size) {
|
||||
protected void alloc(long size) {
|
||||
GL15.glBufferData(type.glEnum, size, usage.glEnum);
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ public class MappedGlBuffer extends GlBuffer implements Mappable {
|
|||
GL15.glBufferData(type.glEnum, directBuffer, usage.glEnum);
|
||||
}
|
||||
|
||||
public MappedBuffer getBuffer(int offset, int length) {
|
||||
public MappedBuffer getBuffer(long offset, long length) {
|
||||
ByteBuffer byteBuffer = GL30.glMapBufferRange(type.glEnum, offset, length, GL30.GL_MAP_WRITE_BIT);
|
||||
|
||||
if (byteBuffer == null) {
|
||||
|
|
|
@ -35,7 +35,7 @@ public class PersistentGlBuffer extends GlBuffer implements Mappable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void alloc(long size) {
|
||||
protected void alloc(long size) {
|
||||
this.size = size;
|
||||
|
||||
if (buffer != null) {
|
||||
|
@ -71,11 +71,11 @@ public class PersistentGlBuffer extends GlBuffer implements Mappable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public MappedBuffer getBuffer(int offset, int length) {
|
||||
public MappedBuffer getBuffer(long offset, long length) {
|
||||
|
||||
fence.waitSync();
|
||||
|
||||
buffer.position(offset);
|
||||
buffer.position((int) offset);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.jozufozu.flywheel.backend.instancing.instancing;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.api.InstanceData;
|
||||
import com.jozufozu.flywheel.api.struct.Instanced;
|
||||
|
@ -10,12 +12,10 @@ import com.jozufozu.flywheel.core.layout.BufferLayout;
|
|||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||
import com.jozufozu.flywheel.backend.gl.error.GlError;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
|
||||
import com.jozufozu.flywheel.backend.model.BufferedModel;
|
||||
import com.jozufozu.flywheel.backend.model.ModelAllocator;
|
||||
import com.jozufozu.flywheel.core.model.Model;
|
||||
import com.jozufozu.flywheel.util.AttribUtil;
|
||||
|
||||
public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
||||
|
||||
|
@ -26,7 +26,6 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
|||
private BufferedModel model;
|
||||
private GlVertexArray vao;
|
||||
private GlBuffer instanceVBO;
|
||||
private int glBufferSize = -1;
|
||||
private int glInstanceCount = 0;
|
||||
private boolean deleted;
|
||||
private boolean initialized;
|
||||
|
@ -49,14 +48,11 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
|||
if (invalid()) return;
|
||||
|
||||
vao.bind();
|
||||
GlError.pollAndThrow(() -> modelData.name() + "_bind");
|
||||
|
||||
renderSetup();
|
||||
GlError.pollAndThrow(() -> modelData.name() + "_setup");
|
||||
|
||||
if (glInstanceCount > 0) {
|
||||
model.drawInstances(glInstanceCount);
|
||||
GlError.pollAndThrow(() -> modelData.name() + "_draw");
|
||||
}
|
||||
|
||||
// persistent mapping sync point
|
||||
|
@ -83,7 +79,8 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
|||
vao.bind();
|
||||
|
||||
instanceVBO = GlBuffer.requestPersistent(GlBufferType.ARRAY_BUFFER);
|
||||
AttribUtil.enableArrays(model.getAttributeCount() + instanceFormat.getAttributeCount());
|
||||
instanceVBO.setGrowthMargin(instanceFormat.getStride() * 16);
|
||||
vao.enableArrays(model.getAttributeCount() + instanceFormat.getAttributeCount());
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
|
@ -135,10 +132,10 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
|||
private void clearBufferTail() {
|
||||
int size = data.size();
|
||||
final int offset = size * instanceFormat.getStride();
|
||||
final int length = glBufferSize - offset;
|
||||
final long length = instanceVBO.getCapacity() - offset;
|
||||
if (length > 0) {
|
||||
try (MappedBuffer buf = instanceVBO.getBuffer(offset, length)) {
|
||||
buf.putByteArray(new byte[length]);
|
||||
MemoryUtil.memSet(MemoryUtil.memAddress(buf.unwrap()), 0, length);
|
||||
} catch (Exception e) {
|
||||
Flywheel.log.error("Error clearing buffer tail:", e);
|
||||
}
|
||||
|
@ -150,7 +147,7 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
|||
|
||||
if (size <= 0) return;
|
||||
|
||||
try (MappedBuffer mapped = instanceVBO.getBuffer(0, glBufferSize)) {
|
||||
try (MappedBuffer mapped = instanceVBO.getBuffer()) {
|
||||
|
||||
final StructWriter<D> writer = instancedType.getWriter(mapped);
|
||||
|
||||
|
@ -170,11 +167,9 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
|||
int size = this.data.size();
|
||||
int stride = instanceFormat.getStride();
|
||||
int requiredSize = size * stride;
|
||||
if (requiredSize > glBufferSize) {
|
||||
glBufferSize = requiredSize + stride * 16;
|
||||
instanceVBO.alloc(glBufferSize);
|
||||
if (instanceVBO.ensureCapacity(requiredSize)) {
|
||||
|
||||
try (MappedBuffer buffer = instanceVBO.getBuffer(0, glBufferSize)) {
|
||||
try (MappedBuffer buffer = instanceVBO.getBuffer()) {
|
||||
StructWriter<D> writer = instancedType.getWriter(buffer);
|
||||
for (D datum : data) {
|
||||
writer.write(datum);
|
||||
|
|
|
@ -59,7 +59,10 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
|
|||
.values();
|
||||
|
||||
// initialize all uninitialized instancers...
|
||||
instancers.forEach(GPUInstancer::init);
|
||||
for (GPUInstancer<?> gpuInstancer : instancers) {
|
||||
gpuInstancer.init();
|
||||
}
|
||||
|
||||
if (material.allocator instanceof ModelPool pool) {
|
||||
// ...and then flush the model arena in case anything was marked for upload
|
||||
pool.flush();
|
||||
|
@ -74,7 +77,9 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
|
|||
|
||||
setup(program);
|
||||
|
||||
instancers.forEach(GPUInstancer::render);
|
||||
for (GPUInstancer<?> instancer : instancers) {
|
||||
instancer.render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,12 +36,11 @@ public class ArrayModelRenderer extends ModelRenderer {
|
|||
vao = new GlVertexArray();
|
||||
|
||||
vao.bind();
|
||||
vao.enableArrays(this.model.getAttributeCount());
|
||||
|
||||
// bind the model's vbo to our vao
|
||||
this.model.setupState();
|
||||
|
||||
AttribUtil.enableArrays(this.model.getAttributeCount());
|
||||
|
||||
GlVertexArray.unbind();
|
||||
|
||||
this.model.clearState();
|
||||
|
|
|
@ -25,7 +25,6 @@ public class ModelPool implements ModelAllocator {
|
|||
private final List<PooledModel> pendingUpload = new ArrayList<>();
|
||||
|
||||
private final GlBuffer vbo;
|
||||
private int bufferSize;
|
||||
|
||||
private int vertices;
|
||||
|
||||
|
@ -34,12 +33,13 @@ public class ModelPool implements ModelAllocator {
|
|||
|
||||
public ModelPool(VertexType vertexType, int initialSize) {
|
||||
this.vertexType = vertexType;
|
||||
bufferSize = vertexType.getStride() * initialSize;
|
||||
int stride = vertexType.getStride();
|
||||
|
||||
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
|
||||
|
||||
vbo.bind();
|
||||
vbo.alloc(bufferSize);
|
||||
vbo.ensureCapacity((long) stride * initialSize);
|
||||
vbo.setGrowthMargin(stride * 64);
|
||||
vbo.unbind();
|
||||
}
|
||||
|
||||
|
@ -104,19 +104,11 @@ public class ModelPool implements ModelAllocator {
|
|||
* @return true if the buffer was reallocated
|
||||
*/
|
||||
private boolean realloc() {
|
||||
int neededSize = vertices * vertexType.getStride();
|
||||
if (neededSize > bufferSize) {
|
||||
bufferSize = neededSize + 128;
|
||||
vbo.alloc(bufferSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return vbo.ensureCapacity((long) vertices * vertexType.getStride());
|
||||
}
|
||||
|
||||
private void uploadAll() {
|
||||
try (MappedBuffer buffer = vbo.getBuffer(0, bufferSize)) {
|
||||
try (MappedBuffer buffer = vbo.getBuffer()) {
|
||||
VertexWriter writer = vertexType.createWriter(buffer.unwrap());
|
||||
|
||||
int vertices = 0;
|
||||
|
@ -134,7 +126,7 @@ public class ModelPool implements ModelAllocator {
|
|||
}
|
||||
|
||||
private void uploadPending() {
|
||||
try (MappedBuffer buffer = vbo.getBuffer(0, bufferSize)) {
|
||||
try (MappedBuffer buffer = vbo.getBuffer()) {
|
||||
VertexWriter writer = vertexType.createWriter(buffer.unwrap());
|
||||
for (PooledModel model : pendingUpload) {
|
||||
buffer(writer, model);
|
||||
|
|
|
@ -29,10 +29,10 @@ public class VBOModel implements BufferedModel {
|
|||
|
||||
vbo.bind();
|
||||
// allocate the buffer on the gpu
|
||||
vbo.alloc(model.size());
|
||||
vbo.ensureCapacity(model.size());
|
||||
|
||||
// mirror it in system memory so we can write to it, and upload our model.
|
||||
try (MappedBuffer buffer = vbo.getBuffer(0, model.size())) {
|
||||
// mirror it in system memory, so we can write to it, and upload our model.
|
||||
try (MappedBuffer buffer = vbo.getBuffer()) {
|
||||
model.writeInto(buffer.unwrap());
|
||||
} catch (Exception e) {
|
||||
Flywheel.log.error(String.format("Error uploading model '%s':", model.name()), e);
|
||||
|
|
|
@ -32,8 +32,8 @@ public class FullscreenQuad {
|
|||
private FullscreenQuad() {
|
||||
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
|
||||
vbo.bind();
|
||||
vbo.alloc(bufferSize);
|
||||
try (MappedBuffer buffer = vbo.getBuffer(0, bufferSize)) {
|
||||
vbo.ensureCapacity(bufferSize);
|
||||
try (MappedBuffer buffer = vbo.getBuffer()) {
|
||||
buffer.putFloatArray(vertices);
|
||||
} catch (Exception e) {
|
||||
Flywheel.log.error("Could not create fullscreen quad.", e);
|
||||
|
|
Loading…
Reference in a new issue