mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-27 05:17:56 +01:00
Mapped buffer sanity
- MappedBuffer no longer abstract - Mappable interface used within MappedBuffer - MappedBuffer is mapped before ctor - No more subclasses, no more thin wrapping overrides - Use try with resources for buffer mapping - Better error handling with mapped buffers - Unimplemented exception as a procrastination method
This commit is contained in:
parent
fd8d436640
commit
21a23d650f
13 changed files with 162 additions and 280 deletions
|
@ -0,0 +1,14 @@
|
|||
package com.jozufozu.flywheel.backend.gl.buffer;
|
||||
|
||||
/**
|
||||
* Interface for generically dealing with mapped buffers.
|
||||
*/
|
||||
public interface Mappable {
|
||||
GlBufferType getType();
|
||||
|
||||
/**
|
||||
* Indicates that this buffer need not be #flush()'d for its contents to sync.
|
||||
* @return true if this buffer is persistently mapped.
|
||||
*/
|
||||
boolean isPersistent();
|
||||
}
|
|
@ -1,133 +1,45 @@
|
|||
package com.jozufozu.flywheel.backend.gl.buffer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
public abstract class MappedBuffer extends VecBuffer implements AutoCloseable {
|
||||
public class MappedBuffer extends VecBuffer implements AutoCloseable {
|
||||
|
||||
protected boolean mapped;
|
||||
protected final GlBuffer owner;
|
||||
protected final long offset;
|
||||
protected final long length;
|
||||
protected final Mappable owner;
|
||||
|
||||
public MappedBuffer(GlBuffer owner) {
|
||||
public MappedBuffer(Mappable owner, ByteBuffer internal, long offset, long length) {
|
||||
this.internal = internal;
|
||||
this.owner = owner;
|
||||
this.offset = offset;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
public long addr() {
|
||||
return MemoryUtil.memAddress(this.internal, internal.position());
|
||||
}
|
||||
|
||||
protected abstract void checkAndMap();
|
||||
|
||||
/**
|
||||
* Make the changes in client memory available to the GPU.
|
||||
*/
|
||||
public void flush() {
|
||||
if (mapped) {
|
||||
GL15.glUnmapBuffer(owner.type.glEnum);
|
||||
mapped = false;
|
||||
setInternal(null);
|
||||
if (owner.isPersistent()) return;
|
||||
|
||||
if (internal == null) return;
|
||||
|
||||
GL15.glUnmapBuffer(owner.getType().glEnum);
|
||||
internal = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappedBuffer position(int p) {
|
||||
if (p < offset || p >= offset + length) {
|
||||
throw new IndexOutOfBoundsException("Index " + p + " is not mapped");
|
||||
}
|
||||
super.position(p - (int) offset);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
flush();
|
||||
}
|
||||
|
||||
public MappedBuffer putFloatArray(float[] floats) {
|
||||
checkAndMap();
|
||||
super.putFloatArray(floats);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MappedBuffer putByteArray(byte[] bytes) {
|
||||
checkAndMap();
|
||||
super.putByteArray(bytes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MappedBuffer put(FloatBuffer floats) {
|
||||
checkAndMap();
|
||||
super.put(floats);
|
||||
return this;
|
||||
}
|
||||
|
||||
public int position() {
|
||||
checkAndMap();
|
||||
return super.position();
|
||||
}
|
||||
|
||||
/**
|
||||
* Position this buffer relative to the 0-index in GPU memory.
|
||||
*
|
||||
* @return This buffer.
|
||||
*/
|
||||
public MappedBuffer position(int p) {
|
||||
checkAndMap();
|
||||
super.position(p);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MappedBuffer putFloat(float f) {
|
||||
checkAndMap();
|
||||
super.putFloat(f);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MappedBuffer putInt(int i) {
|
||||
checkAndMap();
|
||||
super.putInt(i);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MappedBuffer putShort(short s) {
|
||||
checkAndMap();
|
||||
super.putShort(s);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MappedBuffer put(byte b) {
|
||||
checkAndMap();
|
||||
super.put(b);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MappedBuffer put(ByteBuffer b) {
|
||||
checkAndMap();
|
||||
super.put(b);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MappedBuffer putVec4(float x, float y, float z, float w) {
|
||||
checkAndMap();
|
||||
super.putVec4(x, y, z, w);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MappedBuffer putVec3(float x, float y, float z) {
|
||||
checkAndMap();
|
||||
super.putVec3(x, y, z);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MappedBuffer putVec2(float x, float y) {
|
||||
checkAndMap();
|
||||
super.putVec2(x, y);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MappedBuffer putVec3(byte x, byte y, byte z) {
|
||||
checkAndMap();
|
||||
super.putVec3(x, y, z);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MappedBuffer putVec2(byte x, byte y) {
|
||||
checkAndMap();
|
||||
super.putVec2(x, y);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend.gl.buffer;
|
||||
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.gl.error.GlError;
|
||||
import com.jozufozu.flywheel.backend.gl.error.GlException;
|
||||
import com.jozufozu.flywheel.util.StringUtil;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
|
||||
public class MappedBufferRange extends MappedBuffer {
|
||||
|
||||
long offset, length;
|
||||
int access;
|
||||
|
||||
public MappedBufferRange(GlBuffer buffer, long offset, long length, int access) {
|
||||
super(buffer);
|
||||
this.offset = offset;
|
||||
this.length = length;
|
||||
this.access = access;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappedBuffer position(int p) {
|
||||
if (p < offset || p >= offset + length) {
|
||||
throw new IndexOutOfBoundsException("Index " + p + " is not mapped");
|
||||
}
|
||||
return super.position(p - (int) offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkAndMap() {
|
||||
if (!mapped) {
|
||||
setInternal(GL30.glMapBufferRange(owner.type.glEnum, offset, length, access));
|
||||
|
||||
GlError.pollAndThrow(() -> StringUtil.args("mapBufferRange", owner.type, offset, length, access));
|
||||
mapped = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,7 +5,11 @@ import java.nio.ByteBuffer;
|
|||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
public class MappedGlBuffer extends GlBuffer {
|
||||
import com.jozufozu.flywheel.backend.gl.error.GlError;
|
||||
import com.jozufozu.flywheel.backend.gl.error.GlException;
|
||||
import com.jozufozu.flywheel.util.StringUtil;
|
||||
|
||||
public class MappedGlBuffer extends GlBuffer implements Mappable {
|
||||
|
||||
protected final GlBufferUsage usage;
|
||||
|
||||
|
@ -27,6 +31,22 @@ public class MappedGlBuffer extends GlBuffer {
|
|||
}
|
||||
|
||||
public MappedBuffer getBuffer(int offset, int length) {
|
||||
return new MappedBufferRange(this, offset, length, GL30.GL_MAP_WRITE_BIT);
|
||||
ByteBuffer byteBuffer = GL30.glMapBufferRange(type.glEnum, offset, length, GL30.GL_MAP_WRITE_BIT);
|
||||
|
||||
if (byteBuffer == null) {
|
||||
throw new GlException(GlError.poll(), "Could not map buffer");
|
||||
}
|
||||
|
||||
return new MappedBuffer(this, byteBuffer, offset, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GlBufferType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistent() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,16 +6,19 @@ import static org.lwjgl.opengl.GL44.GL_MAP_PERSISTENT_BIT;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.gl.GlFence;
|
||||
import com.jozufozu.flywheel.backend.gl.error.GlError;
|
||||
import com.jozufozu.flywheel.backend.gl.error.GlException;
|
||||
import com.jozufozu.flywheel.util.StringUtil;
|
||||
import com.jozufozu.flywheel.util.Unimplemented;
|
||||
|
||||
|
||||
public class PersistentGlBuffer extends GlBuffer {
|
||||
public class PersistentGlBuffer extends GlBuffer implements Mappable {
|
||||
|
||||
private PersistentMappedBuffer buffer;
|
||||
private MappedBuffer buffer;
|
||||
int flags;
|
||||
|
||||
long size;
|
||||
|
@ -48,14 +51,25 @@ public class PersistentGlBuffer extends GlBuffer {
|
|||
|
||||
Backend.getInstance().compat.bufferStorage.bufferStorage(type, size, flags);
|
||||
|
||||
GlError.pollAndThrow(() -> StringUtil.args("bufferStorage", type, size, flags));
|
||||
GlError error = GlError.poll();
|
||||
if (error != null) {
|
||||
// If this error is being thrown but everything seems fine,
|
||||
// GlError.poll() might be returning an error from something earlier.
|
||||
throw new GlException(error, StringUtil.args("bufferStorage", type, size, flags));
|
||||
}
|
||||
|
||||
buffer = new PersistentMappedBuffer(this);
|
||||
ByteBuffer byteBuffer = GL30.glMapBufferRange(type.glEnum, 0, size, flags);
|
||||
|
||||
if (byteBuffer == null) {
|
||||
throw new GlException(GlError.poll(), "Could not map buffer");
|
||||
}
|
||||
|
||||
buffer = new MappedBuffer(this, byteBuffer, 0, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upload(ByteBuffer directBuffer) {
|
||||
|
||||
throw new Unimplemented("FIXME: Nothing calls #upload on a persistent buffer as of 12/10/2021.");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -67,4 +81,14 @@ public class PersistentGlBuffer extends GlBuffer {
|
|||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GlBufferType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistent() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend.gl.buffer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.gl.error.GlError;
|
||||
import com.jozufozu.flywheel.backend.gl.error.GlException;
|
||||
import com.jozufozu.flywheel.util.StringUtil;
|
||||
|
||||
public class PersistentMappedBuffer extends MappedBuffer {
|
||||
|
||||
private final long offset;
|
||||
private final long length;
|
||||
PersistentGlBuffer owner;
|
||||
|
||||
public PersistentMappedBuffer(PersistentGlBuffer buffer) {
|
||||
super(buffer);
|
||||
owner = buffer;
|
||||
offset = 0;
|
||||
length = owner.size;
|
||||
|
||||
ByteBuffer byteBuffer = GL30.glMapBufferRange(owner.type.glEnum, offset, length, owner.flags);
|
||||
|
||||
GlError.pollAndThrow(() -> StringUtil.args("mapBuffer", owner.type, offset, length, owner.flags));
|
||||
|
||||
setInternal(byteBuffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappedBuffer position(int p) {
|
||||
if (p < offset || p >= offset + length) {
|
||||
throw new IndexOutOfBoundsException("Index " + p + " is not mapped");
|
||||
}
|
||||
return super.position(p - (int) offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkAndMap() {
|
||||
|
||||
}
|
||||
}
|
|
@ -24,10 +24,6 @@ public class VecBuffer {
|
|||
return new VecBuffer(buffer);
|
||||
}
|
||||
|
||||
protected void setInternal(@Nullable ByteBuffer internal) {
|
||||
this.internal = internal;
|
||||
}
|
||||
|
||||
public ByteBuffer unwrap() {
|
||||
return internal;
|
||||
}
|
||||
|
|
|
@ -4,35 +4,12 @@ public class GlException extends RuntimeException {
|
|||
|
||||
final GlError errorCode;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String s = getClass().getName();
|
||||
String message = getLocalizedMessage();
|
||||
String withCode = s + ": " + errorCode;
|
||||
return (message != null) ? (withCode + ": " + message) : withCode;
|
||||
}
|
||||
|
||||
public GlException(GlError errorCode) {
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
public GlException(GlError errorCode, String message) {
|
||||
super(message);
|
||||
super(updateMessage(errorCode, message));
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
public GlException(GlError errorCode, String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
public GlException(GlError errorCode, Throwable cause) {
|
||||
super(cause);
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
public GlException(GlError errorCode, String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
this.errorCode = errorCode;
|
||||
private static String updateMessage(GlError error, String message) {
|
||||
return String.format("%s: %s", error, message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.jozufozu.flywheel.backend.instancing.instancing;
|
|||
|
||||
import java.util.BitSet;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||
|
@ -136,9 +137,11 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
|||
final int offset = size * instanceFormat.getStride();
|
||||
final int length = glBufferSize - offset;
|
||||
if (length > 0) {
|
||||
instanceVBO.getBuffer(offset, length)
|
||||
.putByteArray(new byte[length])
|
||||
.flush();
|
||||
try (MappedBuffer buf = instanceVBO.getBuffer(offset, length)) {
|
||||
buf.putByteArray(new byte[length]);
|
||||
} catch (Exception e) {
|
||||
Flywheel.log.error("Error clearing buffer tail:", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,16 +162,19 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
|||
final int length = (1 + lastDirty - firstDirty) * stride;
|
||||
|
||||
if (length > 0) {
|
||||
MappedBuffer mapped = instanceVBO.getBuffer(offset, length);
|
||||
try (MappedBuffer mapped = instanceVBO.getBuffer(offset, length)) {
|
||||
|
||||
StructWriter<D> writer = type.asInstanced().getWriter(mapped);
|
||||
StructWriter<D> writer = type.asInstanced()
|
||||
.getWriter(mapped);
|
||||
|
||||
dirtySet.stream()
|
||||
.forEach(i -> {
|
||||
writer.seek(i);
|
||||
writer.write(data.get(i));
|
||||
});
|
||||
mapped.flush();
|
||||
dirtySet.stream()
|
||||
.forEach(i -> {
|
||||
writer.seek(i);
|
||||
writer.write(data.get(i));
|
||||
});
|
||||
} catch (Exception e) {
|
||||
Flywheel.log.error("Error updating GPUInstancer:", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,12 +186,15 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
|||
glBufferSize = requiredSize + stride * 16;
|
||||
instanceVBO.alloc(glBufferSize);
|
||||
|
||||
MappedBuffer buffer = instanceVBO.getBuffer(0, glBufferSize);
|
||||
StructWriter<D> writer = type.asInstanced().getWriter(buffer);
|
||||
for (D datum : data) {
|
||||
writer.write(datum);
|
||||
try (MappedBuffer buffer = instanceVBO.getBuffer(0, glBufferSize)) {
|
||||
StructWriter<D> writer = type.asInstanced()
|
||||
.getWriter(buffer);
|
||||
for (D datum : data) {
|
||||
writer.write(datum);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Flywheel.log.error("Error reallocating GPUInstancer:", e);
|
||||
}
|
||||
buffer.flush();
|
||||
|
||||
glInstanceCount = size;
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import static org.lwjgl.opengl.GL11.glDrawArrays;
|
|||
|
||||
import org.lwjgl.opengl.GL31;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.backend.gl.GlPrimitive;
|
||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||
|
@ -32,9 +33,11 @@ public class BufferedModel implements IBufferedModel {
|
|||
vbo.alloc(model.size());
|
||||
|
||||
// mirror it in system memory so we can write to it, and upload our model.
|
||||
MappedBuffer buffer = vbo.getBuffer(0, model.size());
|
||||
model.buffer(new VecBufferWriter(buffer));
|
||||
buffer.flush();
|
||||
try (MappedBuffer buffer = vbo.getBuffer(0, model.size())) {
|
||||
model.buffer(new VecBufferWriter(buffer));
|
||||
} catch (Exception e) {
|
||||
Flywheel.log.error(String.format("Error uploading model '%s':", model.name()), e);
|
||||
}
|
||||
|
||||
vbo.unbind();
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.util.List;
|
|||
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.backend.gl.GlPrimitive;
|
||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||
|
@ -115,34 +116,35 @@ public class ModelPool implements ModelAllocator {
|
|||
}
|
||||
|
||||
private void uploadAll() {
|
||||
MappedBuffer buffer = vbo.getBuffer(0, bufferSize);
|
||||
try (MappedBuffer buffer = vbo.getBuffer(0, bufferSize)) {
|
||||
|
||||
VecBufferWriter consumer = new VecBufferWriter(buffer);
|
||||
VecBufferWriter consumer = new VecBufferWriter(buffer);
|
||||
|
||||
for (PooledModel model : models) {
|
||||
model.model.buffer(consumer);
|
||||
if (model.callback != null)
|
||||
model.callback.onAlloc(model);
|
||||
for (PooledModel model : models) {
|
||||
model.model.buffer(consumer);
|
||||
if (model.callback != null) model.callback.onAlloc(model);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Flywheel.log.error("Error uploading pooled models:", e);
|
||||
}
|
||||
|
||||
buffer.flush();
|
||||
}
|
||||
|
||||
private void uploadPending() {
|
||||
MappedBuffer buffer = vbo.getBuffer(0, bufferSize);
|
||||
VecBufferWriter consumer = new VecBufferWriter(buffer);
|
||||
try (MappedBuffer buffer = vbo.getBuffer(0, bufferSize)) {
|
||||
VecBufferWriter consumer = new VecBufferWriter(buffer);
|
||||
|
||||
int stride = format.getStride();
|
||||
for (PooledModel model : pendingUpload) {
|
||||
int pos = model.first * stride;
|
||||
buffer.position(pos);
|
||||
model.model.buffer(consumer);
|
||||
if (model.callback != null)
|
||||
model.callback.onAlloc(model);
|
||||
int stride = format.getStride();
|
||||
for (PooledModel model : pendingUpload) {
|
||||
int pos = model.first * stride;
|
||||
buffer.position(pos);
|
||||
model.model.buffer(consumer);
|
||||
if (model.callback != null) model.callback.onAlloc(model);
|
||||
}
|
||||
pendingUpload.clear();
|
||||
} catch (Exception e) {
|
||||
Flywheel.log.error("Error uploading pooled models:", e);
|
||||
}
|
||||
pendingUpload.clear();
|
||||
|
||||
buffer.flush();
|
||||
}
|
||||
|
||||
private void setDirty() {
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
package com.jozufozu.flywheel.core;
|
||||
|
||||
import static org.lwjgl.opengl.GL20.*;
|
||||
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
||||
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||
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.buffer.MappedGlBuffer;
|
||||
import com.jozufozu.flywheel.util.Lazy;
|
||||
|
||||
|
@ -28,16 +32,18 @@ public class FullscreenQuad {
|
|||
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
|
||||
vbo.bind();
|
||||
vbo.alloc(bufferSize);
|
||||
vbo.getBuffer(0, bufferSize)
|
||||
.putFloatArray(vertices)
|
||||
.flush();
|
||||
try (MappedBuffer buffer = vbo.getBuffer(0, bufferSize)) {
|
||||
buffer.putFloatArray(vertices);
|
||||
} catch (Exception e) {
|
||||
Flywheel.log.error("Could not create fullscreen quad.", e);
|
||||
}
|
||||
|
||||
vao = new GlVertexArray();
|
||||
vao.bind();
|
||||
|
||||
GL20.glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
GL20.glVertexAttribPointer(0, 4, GlNumericType.FLOAT.getGlEnum(), false, 4 * 4, 0);
|
||||
glVertexAttribPointer(0, 4, GlNumericType.FLOAT.getGlEnum(), false, 4 * 4, 0);
|
||||
|
||||
GlVertexArray.unbind();
|
||||
vbo.unbind();
|
||||
|
@ -45,7 +51,7 @@ public class FullscreenQuad {
|
|||
|
||||
public void draw() {
|
||||
vao.bind();
|
||||
GL20.glDrawArrays(GL20.GL_TRIANGLES, 0, 6);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
GlVertexArray.unbind();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package com.jozufozu.flywheel.util;
|
||||
|
||||
public class Unimplemented extends RuntimeException {
|
||||
public Unimplemented(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue