diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/GlObject.java b/src/main/java/com/jozufozu/flywheel/backend/gl/GlObject.java index b36bcb5ce..27956c87e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/GlObject.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/GlObject.java @@ -18,9 +18,7 @@ public abstract class GlObject { protected final void checkHandle() { if (this.isInvalid()) { - String descriptor = getDescriptor(); - String message = (descriptor == null ? "" : (descriptor + " ")) + "handle is not valid."; - throw new IllegalStateException(message); + throw new IllegalStateException("handle is not valid."); } } @@ -33,10 +31,8 @@ public abstract class GlObject { } public void delete() { - if (isInvalid()) { - String descriptor = getDescriptor(); - String message = (descriptor == null ? "" : (descriptor + " ")) + "handle already deleted."; - throw new IllegalStateException(message); + if (this.isInvalid()) { + throw new IllegalStateException("handle already deleted."); } deleteInternal(handle); @@ -45,7 +41,4 @@ public abstract class GlObject { protected abstract void deleteInternal(int handle); - protected String getDescriptor() { - return ""; - } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/GlVertexArray.java b/src/main/java/com/jozufozu/flywheel/backend/gl/GlVertexArray.java index 18f7bfc26..1ec315fa9 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/GlVertexArray.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/GlVertexArray.java @@ -1,7 +1,10 @@ package com.jozufozu.flywheel.backend.gl; +import org.lwjgl.opengl.GL20; + +import com.jozufozu.flywheel.core.layout.BufferLayout; +import com.jozufozu.flywheel.core.layout.LayoutItem; import com.jozufozu.flywheel.mixin.BufferUploaderAccessor; -import com.jozufozu.flywheel.util.AttribUtil; import com.mojang.blaze3d.platform.GlStateManager; public class GlVertexArray extends GlObject { @@ -20,11 +23,28 @@ public class GlVertexArray extends GlObject { BufferUploaderAccessor.flywheel$setLastVAO(0); } + public void enableArrays(int count) { + for (int i = 0; i < count; i++) { + GL20.glEnableVertexAttribArray(i); + } + } + + public void disableArrays(int count) { + for (int i = 0; i < count; i++) { + GL20.glDisableVertexAttribArray(i); + } + } + + public void bindAttributes(int startIndex, BufferLayout type) { + int offset = 0; + for (LayoutItem spec : type.getLayoutItems()) { + spec.vertexAttribPointer(type.getStride(), startIndex, offset); + startIndex += spec.getAttributeCount(); + offset += spec.getSize(); + } + } + protected void deleteInternal(int handle) { GlStateManager._glDeleteVertexArrays(handle); } - - public void enableArrays(int count) { - AttribUtil.enableArrays(count); - } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java index 1c7f0eb74..5d0e20bd2 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java @@ -8,13 +8,13 @@ import com.jozufozu.flywheel.api.struct.Instanced; import com.jozufozu.flywheel.api.struct.StructWriter; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.gl.GlVertexArray; -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.instancing.AbstractInstancer; import com.jozufozu.flywheel.backend.model.BufferedModel; import com.jozufozu.flywheel.backend.model.ModelAllocator; +import com.jozufozu.flywheel.core.layout.BufferLayout; import com.jozufozu.flywheel.core.model.Model; public class GPUInstancer extends AbstractInstancer { @@ -73,14 +73,14 @@ public class GPUInstancer extends AbstractInstancer { model = modelAllocator.alloc(modelData, arenaModel -> { vao.bind(); - arenaModel.setupState(); + arenaModel.setupState(vao); }); vao.bind(); + vao.enableArrays(model.getAttributeCount() + instanceFormat.getAttributeCount()); instanceVBO = GlBuffer.requestPersistent(GlBufferType.ARRAY_BUFFER); instanceVBO.setGrowthMargin(instanceFormat.getStride() * 16); - vao.enableArrays(model.getAttributeCount() + instanceFormat.getAttributeCount()); } public boolean isInitialized() { @@ -180,19 +180,19 @@ public class GPUInstancer extends AbstractInstancer { glInstanceCount = size; - informAttribDivisors(); + bindInstanceAttributes(); return true; } return false; } - private void informAttribDivisors() { - int staticAttributes = model.getAttributeCount(); - instanceFormat.vertexAttribPointers(staticAttributes); + private void bindInstanceAttributes() { + int attributeBaseIndex = model.getAttributeCount(); + vao.bindAttributes(attributeBaseIndex, instanceFormat); for (int i = 0; i < instanceFormat.getAttributeCount(); i++) { - Backend.getInstance().compat.instancedArrays.vertexAttribDivisor(i + staticAttributes, 1); + Backend.getInstance().compat.instancedArrays.vertexAttribDivisor(attributeBaseIndex + i, 1); } } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/ArrayModelRenderer.java b/src/main/java/com/jozufozu/flywheel/backend/model/ArrayModelRenderer.java index 457226ead..f190aa103 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/model/ArrayModelRenderer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/model/ArrayModelRenderer.java @@ -1,46 +1,54 @@ package com.jozufozu.flywheel.backend.model; -import java.util.function.Supplier; - import com.jozufozu.flywheel.backend.gl.GlVertexArray; import com.jozufozu.flywheel.core.model.Model; -public class ArrayModelRenderer extends ModelRenderer { +public class ArrayModelRenderer { + private final Model model; protected GlVertexArray vao; + protected BufferedModel vbo; + protected boolean initialized; - public ArrayModelRenderer(Supplier model) { - super(model); + public ArrayModelRenderer(Model model) { + this.model = model; } - @Override + /** + * Renders this model, checking first if there is anything to render. + */ public void draw() { if (!initialized) init(); if (!isValid()) return; vao.bind(); - model.drawCall(); + vbo.drawCall(); } - @Override protected void init() { initialized = true; - Model model = modelSupplier.get(); if (model.empty()) return; - this.model = new IndexedModel(model); + this.vbo = new IndexedModel(model); vao = new GlVertexArray(); vao.bind(); // bind the model's vbo to our vao - this.model.setupState(); + this.vbo.setupState(vao); GlVertexArray.unbind(); + } - this.model.clearState(); + public void delete() { + if (vbo != null) + vbo.delete(); + } + + protected boolean isValid() { + return vbo != null && vbo.valid(); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/BufferedModel.java b/src/main/java/com/jozufozu/flywheel/backend/model/BufferedModel.java index 2c7bf5cb9..5dc2e3107 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/model/BufferedModel.java +++ b/src/main/java/com/jozufozu/flywheel/backend/model/BufferedModel.java @@ -1,7 +1,8 @@ package com.jozufozu.flywheel.backend.model; -import com.jozufozu.flywheel.core.layout.BufferLayout; import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.backend.gl.GlVertexArray; +import com.jozufozu.flywheel.core.layout.BufferLayout; public interface BufferedModel { @@ -10,11 +11,9 @@ public interface BufferedModel { int getVertexCount(); /** - * The VBO/VAO should be bound externally. + * The VAO must be bound externally. */ - void setupState(); - - void clearState(); + void setupState(GlVertexArray vao); void drawCall(); @@ -27,7 +26,7 @@ public interface BufferedModel { void delete(); - default BufferLayout getFormat() { + default BufferLayout getLayout() { return getType().getLayout(); } @@ -36,6 +35,6 @@ public interface BufferedModel { } default int getAttributeCount() { - return getFormat().getAttributeCount(); + return getType().getLayout().getAttributeCount(); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java b/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java index 06bd043b2..7a372b0c8 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java +++ b/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java @@ -3,7 +3,14 @@ package com.jozufozu.flywheel.backend.model; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL31; +import com.jozufozu.flywheel.Flywheel; +import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.backend.gl.GlPrimitive; +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.core.model.Model; /** @@ -11,26 +18,43 @@ import com.jozufozu.flywheel.core.model.Model; * *
This should be favored over a normal BufferedModel. */ -public class IndexedModel extends VBOModel { +public class IndexedModel implements BufferedModel { + protected final Model model; + protected final GlPrimitive primitiveMode; protected ElementBuffer ebo; + protected GlBuffer vbo; + protected boolean deleted; public IndexedModel(Model model) { - super(GlPrimitive.TRIANGLES, model); + this.model = model; + this.primitiveMode = GlPrimitive.TRIANGLES; + + vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER); + + vbo.bind(); + // allocate the buffer on the gpu + vbo.ensureCapacity(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.LOGGER.error(String.format("Error uploading model '%s':", model.name()), e); + } + + vbo.unbind(); this.ebo = model.createEBO(); } - @Override - public void setupState() { - super.setupState(); - ebo.bind(); - } - - @Override - public void clearState() { - super.clearState(); - ebo.unbind(); + /** + * The VBO/VAO should be bound externally. + */ + public void setupState(GlVertexArray vao) { + vbo.bind(); + vao.enableArrays(getAttributeCount()); + vao.bindAttributes(0, getType().getLayout()); } @Override @@ -39,6 +63,9 @@ public class IndexedModel extends VBOModel { GL20.glDrawElements(primitiveMode.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0); } + /** + * Draws many instances of this model, assuming the appropriate state is already bound. + */ @Override public void drawInstances(int instanceCount) { if (!valid()) return; @@ -47,4 +74,24 @@ public class IndexedModel extends VBOModel { GL31.glDrawElementsInstanced(primitiveMode.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0, instanceCount); } + + public boolean isDeleted() { + return deleted; + } + + @Override + public VertexType getType() { + return model.getType(); + } + + public int getVertexCount() { + return model.vertexCount(); + } + + public void delete() { + if (deleted) return; + + deleted = true; + vbo.delete(); + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java b/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java index 4561577bf..7eadc68dc 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java +++ b/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java @@ -6,15 +6,15 @@ import java.util.List; import org.lwjgl.opengl.GL32; import com.jozufozu.flywheel.Flywheel; +import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.api.vertex.VertexWriter; import com.jozufozu.flywheel.backend.gl.GlPrimitive; +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.core.model.Model; -import com.jozufozu.flywheel.api.vertex.VertexType; -import com.jozufozu.flywheel.api.vertex.VertexWriter; -import com.jozufozu.flywheel.util.AttribUtil; public class ModelPool implements ModelAllocator { @@ -178,18 +178,10 @@ public class ModelPool implements ModelAllocator { } @Override - public void setupState() { + public void setupState(GlVertexArray vao) { vbo.bind(); - ebo.bind(); - AttribUtil.enableArrays(getAttributeCount()); - ModelPool.this.vertexType.getLayout().vertexAttribPointers(0); - } - - @Override - public void clearState() { - AttribUtil.disableArrays(getAttributeCount()); - ebo.unbind(); - vbo.unbind(); + vao.enableArrays(getAttributeCount()); + vao.bindAttributes(0, vertexType.getLayout()); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/ModelRenderer.java b/src/main/java/com/jozufozu/flywheel/backend/model/ModelRenderer.java deleted file mode 100644 index 2debba1ab..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/model/ModelRenderer.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.jozufozu.flywheel.backend.model; - -import java.util.function.Supplier; - -import com.jozufozu.flywheel.core.model.Model; - -public class ModelRenderer { - - protected Supplier modelSupplier; - protected BufferedModel model; - - protected boolean initialized; - - public ModelRenderer(Supplier modelSupplier) { - this.modelSupplier = modelSupplier; - } - - /** - * Renders this model, checking first if there is anything to render. - */ - public void draw() { - if (!initialized) init(); - if (!isValid()) return; - - model.setupState(); - model.drawCall(); - model.clearState(); - } - - public void delete() { - if (model != null) - model.delete(); - } - - protected void init() { - initialized = true; - Model model = modelSupplier.get(); - - if (model.empty()) return; - - this.model = new IndexedModel(model); - } - - protected boolean isValid() { - return model != null && model.valid(); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/VBOModel.java b/src/main/java/com/jozufozu/flywheel/backend/model/VBOModel.java index dcc26d234..54dccbd28 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/model/VBOModel.java +++ b/src/main/java/com/jozufozu/flywheel/backend/model/VBOModel.java @@ -5,14 +5,14 @@ import static org.lwjgl.opengl.GL11.glDrawArrays; import org.lwjgl.opengl.GL31; import com.jozufozu.flywheel.Flywheel; +import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.backend.gl.GlPrimitive; +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.core.model.Model; -import com.jozufozu.flywheel.api.vertex.VertexType; -import com.jozufozu.flywheel.util.AttribUtil; public class VBOModel implements BufferedModel { @@ -57,15 +57,10 @@ public class VBOModel implements BufferedModel { /** * The VBO/VAO should be bound externally. */ - public void setupState() { + public void setupState(GlVertexArray vao) { vbo.bind(); - AttribUtil.enableArrays(getAttributeCount()); - getFormat().vertexAttribPointers(0); - } - - public void clearState() { - AttribUtil.disableArrays(getAttributeCount()); - vbo.unbind(); + vao.enableArrays(getAttributeCount()); + vao.bindAttributes(0, getLayout()); } public void drawCall() { diff --git a/src/main/java/com/jozufozu/flywheel/core/layout/BufferLayout.java b/src/main/java/com/jozufozu/flywheel/core/layout/BufferLayout.java index cbfb4fcc7..d7111f706 100644 --- a/src/main/java/com/jozufozu/flywheel/core/layout/BufferLayout.java +++ b/src/main/java/com/jozufozu/flywheel/core/layout/BufferLayout.java @@ -9,7 +9,7 @@ import com.jozufozu.flywheel.api.vertex.VertexType; * Classic Vertex Format struct with a clever name. * *

- * Used for vertices and instance. Describes the layout of a datatype in a buffer object. + * Used for vertices and instances. Describes the layout of a datatype in a buffer object. *

* * @see com.jozufozu.flywheel.api.struct.StructType @@ -34,6 +34,10 @@ public class BufferLayout { this.stride = stride; } + public List getLayoutItems() { + return allAttributes; + } + public int getAttributeCount() { return numAttributes; } @@ -42,15 +46,6 @@ public class BufferLayout { return stride; } - public void vertexAttribPointers(int index) { - int offset = 0; - for (LayoutItem spec : this.allAttributes) { - spec.vertexAttribPointer(stride, index, offset); - index += spec.getAttributeCount(); - offset += spec.getSize(); - } - } - public static Builder builder() { return new Builder(); } diff --git a/src/main/java/com/jozufozu/flywheel/util/AttribUtil.java b/src/main/java/com/jozufozu/flywheel/util/AttribUtil.java deleted file mode 100644 index b50fe47a3..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/AttribUtil.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.jozufozu.flywheel.util; - -import org.lwjgl.opengl.GL20; - -// TODO: move this functionality into GlVertexArray and track it -public class AttribUtil { - - public static void enableArrays(int count) { - enableArrays(0, count); - } - - public static void enableArrays(int fromInclusive, int toExclusive) { - for (int i = fromInclusive; i < toExclusive; i++) { - GL20.glEnableVertexAttribArray(i); - } - } - - public static void disableArrays(int count) { - disableArrays(0, count); - } - - public static void disableArrays(int fromInclusive, int toExclusive) { - for (int i = fromInclusive; i < toExclusive; i++) { - GL20.glDisableVertexAttribArray(i); - } - } -}