From e2bcc5f325dbd3b4642dec13979f908b98e6b7fc Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Sat, 6 May 2023 16:14:30 -0700 Subject: [PATCH] Should use separate attribute format correctly - Switch to object oriented vertex array impl - Expose vao api similar to separate attribute format - For DSA, directly call methods - For 33, defer state changes until bindForDraw is called - Inline instanced mesh #drawInstances method in favor of more fine-grained control over binding order - Move buffer binding to GlStateTracker - Remove raw bindVAO(0) from indirect engine - Make VertexAttribute a sealed interface. - Fix ebo restore state by always updating it and never restoring it - Remove restore state wrapping in DrawCall - Also misc cleanup. --- .../engine/indirect/IndirectBuffers.java | 52 +++--- .../engine/indirect/IndirectCullingGroup.java | 9 +- .../backend/engine/instancing/DrawCall.java | 21 +-- .../engine/instancing/GPUInstancer.java | 10 +- .../engine/instancing/InstancedMeshPool.java | 22 +-- .../com/jozufozu/flywheel/gl/GlCompat.java | 5 +- .../jozufozu/flywheel/gl/GlNumericType.java | 1 + .../com/jozufozu/flywheel/gl/GlObject.java | 8 +- .../jozufozu/flywheel/gl/GlStateTracker.java | 8 +- .../com/jozufozu/flywheel/gl/GlTexture.java | 2 +- .../flywheel/gl/array/GlVertexArray.java | 96 +++-------- .../flywheel/gl/array/GlVertexArrayDSA.java | 91 +++++++++++ .../flywheel/gl/array/GlVertexArrayGL3.java | 153 ++++++++++++++++++ .../flywheel/gl/array/VertexArray.java | 133 --------------- .../flywheel/gl/array/VertexAttribute.java | 32 ++-- .../flywheel/gl/array/VertexAttributeF.java | 30 ---- .../flywheel/gl/array/VertexAttributeI.java | 29 ---- .../jozufozu/flywheel/gl/buffer/Buffer.java | 8 +- .../flywheel/gl/buffer/ElementBuffer.java | 4 - .../jozufozu/flywheel/gl/buffer/GlBuffer.java | 4 +- .../flywheel/gl/buffer/GlBufferType.java | 13 +- .../flywheel/gl/shader/GlProgram.java | 2 +- .../jozufozu/flywheel/gl/shader/GlShader.java | 2 +- .../flywheel/lib/layout/CommonItems.java | 19 ++- .../flywheel/lib/layout/MatInput.java | 3 +- .../flywheel/lib/material/SimpleMaterial.java | 2 +- .../flywheel/lib/util/FullscreenQuad.java | 12 +- .../flywheel/lib/util/QuadConverter.java | 15 +- .../com/jozufozu/flywheel/util/FlwUtil.java | 17 +- 29 files changed, 398 insertions(+), 405 deletions(-) create mode 100644 src/main/java/com/jozufozu/flywheel/gl/array/GlVertexArrayDSA.java create mode 100644 src/main/java/com/jozufozu/flywheel/gl/array/GlVertexArrayGL3.java delete mode 100644 src/main/java/com/jozufozu/flywheel/gl/array/VertexArray.java delete mode 100644 src/main/java/com/jozufozu/flywheel/gl/array/VertexAttributeF.java delete mode 100644 src/main/java/com/jozufozu/flywheel/gl/array/VertexAttributeI.java diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectBuffers.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectBuffers.java index 1c1ffaa11..30f9b7538 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectBuffers.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectBuffers.java @@ -1,11 +1,9 @@ package com.jozufozu.flywheel.backend.engine.indirect; -import static org.lwjgl.opengl.GL15.glBindBuffer; import static org.lwjgl.opengl.GL15.glDeleteBuffers; import static org.lwjgl.opengl.GL15.nglDeleteBuffers; import static org.lwjgl.opengl.GL30.GL_MAP_FLUSH_EXPLICIT_BIT; import static org.lwjgl.opengl.GL30.GL_MAP_WRITE_BIT; -import static org.lwjgl.opengl.GL40.GL_DRAW_INDIRECT_BUFFER; import static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BUFFER; import static org.lwjgl.opengl.GL44.GL_DYNAMIC_STORAGE_BIT; import static org.lwjgl.opengl.GL44.GL_MAP_PERSISTENT_BIT; @@ -21,6 +19,7 @@ import static org.lwjgl.opengl.GL45.nglNamedBufferSubData; import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.Pointer; +import com.jozufozu.flywheel.gl.buffer.GlBufferType; import com.jozufozu.flywheel.lib.memory.FlwMemoryTracker; import com.jozufozu.flywheel.lib.memory.MemoryBlock; @@ -49,22 +48,22 @@ public class IndirectBuffers { private static final long BATCH_SIZE_OFFSET = TARGET_SIZE_OFFSET + PTR_SIZE; private static final long DRAW_SIZE_OFFSET = BATCH_SIZE_OFFSET + PTR_SIZE; - final MemoryBlock buffers; - final long objectStride; - int object; - int target; - int batch; - int draw; + private final MemoryBlock buffers; + private final long objectStride; + private int object; + private int target; + private int batch; + private int draw; long objectPtr; long batchPtr; long drawPtr; - int maxObjectCount = 0; - int maxDrawCount = 0; + private int maxObjectCount = 0; + private int maxDrawCount = 0; - float objectGrowthFactor = 2f; - float drawGrowthFactor = 2f; + private static final float OBJECT_GROWTH_FACTOR = 2f; + private static final float DRAW_GROWTH_FACTOR = 2f; IndirectBuffers(long objectStride) { this.objectStride = objectStride; @@ -81,20 +80,11 @@ public class IndirectBuffers { } void updateCounts(int objectCount, int drawCount) { - if (objectCount > maxObjectCount) { - var newObjectCount = maxObjectCount; - while (newObjectCount <= objectCount) { - newObjectCount *= objectGrowthFactor; - } - createObjectStorage(newObjectCount); + createObjectStorage((int) (objectCount * OBJECT_GROWTH_FACTOR)); } if (drawCount > maxDrawCount) { - var newDrawCount = maxDrawCount; - while (newDrawCount <= drawCount) { - newDrawCount *= drawGrowthFactor; - } - createDrawStorage(newDrawCount); + createDrawStorage((int) (drawCount * DRAW_GROWTH_FACTOR)); } final long objectSize = objectStride * objectCount; @@ -114,7 +104,7 @@ public class IndirectBuffers { var targetSize = INT_SIZE * objectCount; if (maxObjectCount > 0) { - var ptr = buffers.ptr(); + final long ptr = buffers.ptr(); nglCreateBuffers(3, ptr); int objectNew = MemoryUtil.memGetInt(ptr); @@ -181,21 +171,17 @@ public class IndirectBuffers { } public void bindForCompute() { - multiBind(BUFFER_COUNT); + multiBind(); } public void bindForDraw() { - multiBind(BUFFER_COUNT); - glBindBuffer(GL_DRAW_INDIRECT_BUFFER, draw); + multiBind(); + GlBufferType.DRAW_INDIRECT_BUFFER.bind(draw); } - private void multiBind(int bufferCount) { - if (bufferCount > BUFFER_COUNT) { - throw new IllegalArgumentException("Can't bind more than " + BUFFER_COUNT + " buffers"); - } - + private void multiBind() { final long ptr = buffers.ptr(); - nglBindBuffersRange(GL_SHADER_STORAGE_BUFFER, 0, bufferCount, ptr, ptr + OFFSET_OFFSET, ptr + SIZE_OFFSET); + nglBindBuffersRange(GL_SHADER_STORAGE_BUFFER, 0, IndirectBuffers.BUFFER_COUNT, ptr, ptr + OFFSET_OFFSET, ptr + SIZE_OFFSET); } void flushBatchIDs(long length) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java index 282ca7e12..31fe39c52 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java @@ -1,6 +1,5 @@ package com.jozufozu.flywheel.backend.engine.indirect; -import static org.lwjgl.opengl.GL30.glBindVertexArray; import static org.lwjgl.opengl.GL42.GL_COMMAND_BARRIER_BIT; import static org.lwjgl.opengl.GL42.glMemoryBarrier; import static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BARRIER_BIT; @@ -9,6 +8,7 @@ import static org.lwjgl.opengl.GL43.glDispatchCompute; import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.InstanceType; +import com.jozufozu.flywheel.api.layout.BufferLayout; import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.backend.compile.IndirectPrograms; import com.jozufozu.flywheel.backend.engine.UniformBuffer; @@ -51,7 +51,7 @@ public class IndirectCullingGroup { meshPool = new IndirectMeshPool(vertexType, 1024); - vertexArray = new GlVertexArray(); + vertexArray = GlVertexArray.create(); elementBuffer = QuadConverter.getInstance() .quads2Tris(2048).glBuffer; @@ -64,7 +64,9 @@ public class IndirectCullingGroup { private void setupVertexArray() { vertexArray.setElementBuffer(elementBuffer); - vertexArray.bindAttributes(vertexType.getLayout(), meshPool.vbo, 0, 0); + BufferLayout type = vertexType.getLayout(); + vertexArray.bindVertexBuffer(0, meshPool.vbo, 0, type.getStride()); + vertexArray.bindAttributes(0, 0, type.attributes()); } void beginFrame() { @@ -116,7 +118,6 @@ public class IndirectCullingGroup { memoryBarrier(); drawSet.submit(stage); - glBindVertexArray(0); } private void memoryBarrier() { diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/DrawCall.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/DrawCall.java index 8736c9841..90762cc70 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/DrawCall.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/DrawCall.java @@ -1,6 +1,5 @@ package com.jozufozu.flywheel.backend.engine.instancing; -import com.jozufozu.flywheel.gl.GlStateTracker; import com.jozufozu.flywheel.gl.array.GlVertexArray; public class DrawCall { @@ -15,7 +14,7 @@ public class DrawCall { this.mesh = mesh; meshAttributes = this.mesh.getAttributeCount(); - vao = new GlVertexArray(); + vao = GlVertexArray.create(); } public boolean isInvalid() { @@ -27,15 +26,19 @@ public class DrawCall { return; } - try (var ignored = GlStateTracker.getRestoreState()) { - instancer.update(); + instancer.update(); - instancer.bindToVAO(vao, meshAttributes); - - if (instancer.getInstanceCount() > 0) { - mesh.drawInstances(vao, instancer.getInstanceCount()); - } + int instanceCount = instancer.getInstanceCount(); + if (instanceCount <= 0 || mesh.isEmpty()) { + return; } + + instancer.bindToVAO(vao, meshAttributes); + mesh.setup(vao); + + vao.bindForDraw(); + + mesh.draw(instanceCount); } public void delete() { diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/GPUInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/GPUInstancer.java index 2164ea4fa..c03390875 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/GPUInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/GPUInstancer.java @@ -79,16 +79,14 @@ public class GPUInstancer extends AbstractInstancer { } } - public void bindToVAO(GlVertexArray vao, int attributeOffset) { + public void bindToVAO(GlVertexArray vao, int startAttrib) { if (!boundTo.add(vao)) { return; } - vao.bindAttributes(instanceFormat, vbo.handle(), attributeOffset, 0L); - - for (int i = 0; i < instanceFormat.getAttributeCount(); i++) { - vao.setAttributeDivisor(attributeOffset + i, 1); - } + vao.bindVertexBuffer(1, vbo.handle(), 0L, instanceStride); + vao.setBindingDivisor(1, 1); + vao.bindAttributes(1, startAttrib, instanceFormat.attributes()); } public void delete() { diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedMeshPool.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedMeshPool.java index 25ed034f1..c2a671b00 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedMeshPool.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedMeshPool.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL32; import com.jozufozu.flywheel.Flywheel; +import com.jozufozu.flywheel.api.layout.BufferLayout; import com.jozufozu.flywheel.api.model.Mesh; import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.gl.GlPrimitive; @@ -172,7 +173,7 @@ public class InstancedMeshPool { return deleted; } - private boolean isEmpty() { + public boolean isEmpty() { return mesh.isEmpty() || isDeleted(); } @@ -182,25 +183,16 @@ public class InstancedMeshPool { boundTo.clear(); } - public void drawInstances(GlVertexArray vao, int instanceCount) { - if (isEmpty()) { - return; - } - - setup(vao); - - draw(instanceCount); - } - - private void setup(GlVertexArray vao) { + public void setup(GlVertexArray vao) { if (boundTo.add(vao)) { - vao.bindAttributes(vertexType.getLayout(), InstancedMeshPool.this.vbo.handle(), 0, byteIndex); + BufferLayout type = vertexType.getLayout(); + vao.bindVertexBuffer(0, InstancedMeshPool.this.vbo.handle(), byteIndex, type.getStride()); + vao.bindAttributes(0, 0, type.attributes()); vao.setElementBuffer(ebo.glBuffer); } - vao.bindForDraw(); } - private void draw(int instanceCount) { + public void draw(int instanceCount) { if (instanceCount > 1) { GL32.glDrawElementsInstanced(GlPrimitive.TRIANGLES.glEnum, ebo.getElementCount(), ebo.getEboIndexType().asGLType, 0, instanceCount); } else { diff --git a/src/main/java/com/jozufozu/flywheel/gl/GlCompat.java b/src/main/java/com/jozufozu/flywheel/gl/GlCompat.java index 6f318ad4c..040819bf5 100644 --- a/src/main/java/com/jozufozu/flywheel/gl/GlCompat.java +++ b/src/main/java/com/jozufozu/flywheel/gl/GlCompat.java @@ -8,8 +8,6 @@ import org.lwjgl.opengl.GL20C; import org.lwjgl.opengl.GLCapabilities; import org.lwjgl.system.MemoryStack; -import com.jozufozu.flywheel.gl.array.GlVertexArray; - import net.minecraft.Util; /** @@ -19,6 +17,7 @@ import net.minecraft.Util; * system. */ public class GlCompat { + public static final boolean ALLOW_DSA = true; public static final GLCapabilities CAPABILITIES = GL.createCapabilities(); private static final boolean amd = _decideIfWeAreAMDWindows(); private static final boolean supportsIndirect = _decideIfWeSupportIndirect(); @@ -31,7 +30,7 @@ public class GlCompat { } public static boolean supportsInstancing() { - return GlVertexArray.IMPL != null; + return true; } public static boolean supportsIndirect() { diff --git a/src/main/java/com/jozufozu/flywheel/gl/GlNumericType.java b/src/main/java/com/jozufozu/flywheel/gl/GlNumericType.java index 0875dc69e..531063490 100644 --- a/src/main/java/com/jozufozu/flywheel/gl/GlNumericType.java +++ b/src/main/java/com/jozufozu/flywheel/gl/GlNumericType.java @@ -17,6 +17,7 @@ public enum GlNumericType { SHORT(2, "short", GL11.GL_SHORT), UINT(4, "uint", GL11.GL_UNSIGNED_INT), INT(4, "int", GL11.GL_INT), + DOUBLE(8, "double", GL11.GL_DOUBLE), ; private static final GlNumericType[] VALUES = values(); diff --git a/src/main/java/com/jozufozu/flywheel/gl/GlObject.java b/src/main/java/com/jozufozu/flywheel/gl/GlObject.java index ba18c18c5..eec6ef813 100644 --- a/src/main/java/com/jozufozu/flywheel/gl/GlObject.java +++ b/src/main/java/com/jozufozu/flywheel/gl/GlObject.java @@ -6,18 +6,18 @@ public abstract class GlObject { private int handle = INVALID_HANDLE; - protected final void setHandle(int handle) { + protected final void handle(int handle) { this.handle = handle; } public final int handle() { - this.checkHandle(); + checkHandle(); return this.handle; } protected final void checkHandle() { - if (this.isInvalid()) { + if (isInvalid()) { throw new IllegalStateException("handle is not valid."); } } @@ -31,7 +31,7 @@ public abstract class GlObject { } public void delete() { - if (this.isInvalid()) { + if (isInvalid()) { throw new IllegalStateException("handle already deleted."); } diff --git a/src/main/java/com/jozufozu/flywheel/gl/GlStateTracker.java b/src/main/java/com/jozufozu/flywheel/gl/GlStateTracker.java index 05197cb78..800286c05 100644 --- a/src/main/java/com/jozufozu/flywheel/gl/GlStateTracker.java +++ b/src/main/java/com/jozufozu/flywheel/gl/GlStateTracker.java @@ -45,6 +45,12 @@ public class GlStateTracker { } } + public static void bindBuffer(GlBufferType type, int buffer) { + if (BUFFERS[type.ordinal()] != buffer || type == GlBufferType.ELEMENT_ARRAY_BUFFER) { + GlStateManager._glBindBuffer(type.glEnum, buffer); + } + } + public record State(int[] buffers, int vao, int program) implements AutoCloseable { public void restore() { if (vao != GlStateTracker.vao) { @@ -54,7 +60,7 @@ public class GlStateTracker { GlBufferType[] values = GlBufferType.values(); for (int i = 0; i < values.length; i++) { - if (buffers[i] != GlStateTracker.BUFFERS[i]) { + if (buffers[i] != GlStateTracker.BUFFERS[i] && values[i] != GlBufferType.ELEMENT_ARRAY_BUFFER) { GlStateManager._glBindBuffer(values[i].glEnum, buffers[i]); } } diff --git a/src/main/java/com/jozufozu/flywheel/gl/GlTexture.java b/src/main/java/com/jozufozu/flywheel/gl/GlTexture.java index 9b6d6b986..97a8defa1 100644 --- a/src/main/java/com/jozufozu/flywheel/gl/GlTexture.java +++ b/src/main/java/com/jozufozu/flywheel/gl/GlTexture.java @@ -7,7 +7,7 @@ public class GlTexture extends GlObject { public GlTexture(int textureType) { this.textureType = textureType; - setHandle(GL20.glGenTextures()); + handle(GL20.glGenTextures()); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/gl/array/GlVertexArray.java b/src/main/java/com/jozufozu/flywheel/gl/array/GlVertexArray.java index cc5d61bb7..d8c355538 100644 --- a/src/main/java/com/jozufozu/flywheel/gl/array/GlVertexArray.java +++ b/src/main/java/com/jozufozu/flywheel/gl/array/GlVertexArray.java @@ -1,99 +1,43 @@ package com.jozufozu.flywheel.gl.array; +import java.util.List; + import org.lwjgl.opengl.GL32; -import com.jozufozu.flywheel.api.layout.BufferLayout; import com.jozufozu.flywheel.gl.GlObject; import com.jozufozu.flywheel.gl.GlStateTracker; import com.mojang.blaze3d.platform.GlStateManager; -public class GlVertexArray extends GlObject { - public static final VertexArray IMPL = new VertexArray.DSA().fallback(); - private static final int MAX_ATTRIBS = GL32.glGetInteger(GL32.GL_MAX_VERTEX_ATTRIBS); +public abstract class GlVertexArray extends GlObject { + protected static final int MAX_ATTRIBS = GL32.glGetInteger(GL32.GL_MAX_VERTEX_ATTRIBS); + protected static final int MAX_ATTRIB_BINDINGS = 16; - /** - * Whether each attribute is enabled. - */ - private final boolean[] enabled = new boolean[MAX_ATTRIBS]; - /** - * Each attribute's divisor. - */ - private final int[] divisors = new int[MAX_ATTRIBS]; - /** - * Each attribute's data type. - */ - private final VertexAttribute[] attributes = new VertexAttribute[MAX_ATTRIBS]; - /** - * The VBO to which each attribute is bound. - */ - private final int[] targets = new int[MAX_ATTRIBS]; - /** - * Each attribute's offset. - */ - private final long[] offsets = new long[MAX_ATTRIBS]; - /** - * Each attribute's stride. - */ - private final int[] strides = new int[MAX_ATTRIBS]; - - private int elementBufferBinding = 0; - - public GlVertexArray() { - setHandle(IMPL.create()); + public static GlVertexArray create() { + if (GlVertexArrayDSA.SUPPORTED) { + return new GlVertexArrayDSA(); + } else if (GlVertexArrayGL3.Core33.SUPPORTED) { + return new GlVertexArrayGL3.Core33(); + } else if (GlVertexArrayGL3.ARB.SUPPORTED) { + return new GlVertexArrayGL3.ARB(); + } else { + return new GlVertexArrayGL3.Core(); + } } public void bindForDraw() { GlStateTracker.bindVao(handle()); } - public static void unbind() { - GlStateManager._glBindVertexArray(0); - } + public abstract void bindVertexBuffer(int bindingIndex, int vbo, long offset, int stride); - public void bindAttributes(BufferLayout type, final int vbo, final int startAttrib, final long startOffset) { - final int vao = handle(); - final int stride = type.getStride(); + public abstract void setBindingDivisor(int bindingIndex, int divisor); - int index = startAttrib; - long offset = startOffset; - for (var attribute : type.attributes()) { - if (!enabled[index]) { - IMPL.enableAttrib(vao, index); - enabled[index] = true; - } + public abstract void bindAttributes(int bindingIndex, int startAttribIndex, List vertexAttributes); - if (shouldSetupAttrib(index, vbo, stride, offset, attribute)) { - IMPL.setupAttrib(vao, index, vbo, stride, offset, attribute); - targets[index] = vbo; - attributes[index] = attribute; - offsets[index] = offset; - strides[index] = stride; - } - - index++; - offset += attribute.getByteWidth(); - } - } - - private boolean shouldSetupAttrib(int index, int vbo, int stride, long offset, VertexAttribute attribute) { - return targets[index] != vbo || offsets[index] != offset || strides[index] != stride || !attribute.equals(attributes[index]); - } + public abstract void setElementBuffer(int ebo); + @Override protected void deleteInternal(int handle) { GlStateManager._glDeleteVertexArrays(handle); } - - public void setAttributeDivisor(int index, int divisor) { - if (divisors[index] != divisor) { - IMPL.setAttribDivisor(handle(), index, divisor); - divisors[index] = divisor; - } - } - - public void setElementBuffer(int ebo) { - if (elementBufferBinding != ebo) { - IMPL.setElementBuffer(handle(), ebo); - elementBufferBinding = ebo; - } - } } diff --git a/src/main/java/com/jozufozu/flywheel/gl/array/GlVertexArrayDSA.java b/src/main/java/com/jozufozu/flywheel/gl/array/GlVertexArrayDSA.java new file mode 100644 index 000000000..b31edc78a --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/gl/array/GlVertexArrayDSA.java @@ -0,0 +1,91 @@ +package com.jozufozu.flywheel.gl.array; + +import java.util.BitSet; +import java.util.List; + +import org.lwjgl.opengl.GL45C; +import org.lwjgl.system.Checks; + +import com.jozufozu.flywheel.gl.GlCompat; +import com.jozufozu.flywheel.util.FlwUtil; + +public class GlVertexArrayDSA extends GlVertexArray { + public static final boolean SUPPORTED = isSupported(); + private final BitSet attributeEnabled = new BitSet(MAX_ATTRIBS); + private final VertexAttribute[] attributes = new VertexAttribute[MAX_ATTRIBS]; + private final int[] attributeBindings = FlwUtil.initArray(MAX_ATTRIBS, -1); + private final int[] bindingBuffers = new int[MAX_ATTRIB_BINDINGS]; + private final long[] bindingOffsets = new long[MAX_ATTRIB_BINDINGS]; + private final int[] bindingStrides = new int[MAX_ATTRIB_BINDINGS]; + private final int[] bindingDivisors = new int[MAX_ATTRIB_BINDINGS]; + + private int elementBufferBinding = 0; + + public GlVertexArrayDSA() { + handle(GL45C.glCreateVertexArrays()); + } + + @Override + public void bindVertexBuffer(final int bindingIndex, final int vbo, final long offset, final int stride) { + if (bindingBuffers[bindingIndex] != vbo || bindingOffsets[bindingIndex] != offset || bindingStrides[bindingIndex] != stride) { + GL45C.glVertexArrayVertexBuffer(handle(), bindingIndex, vbo, offset, stride); + bindingBuffers[bindingIndex] = vbo; + bindingOffsets[bindingIndex] = offset; + bindingStrides[bindingIndex] = stride; + } + } + + @Override + public void setBindingDivisor(final int bindingIndex, final int divisor) { + if (bindingDivisors[bindingIndex] != divisor) { + GL45C.glVertexArrayBindingDivisor(handle(), bindingIndex, divisor); + bindingDivisors[bindingIndex] = divisor; + } + } + + @Override + public void bindAttributes(final int bindingIndex, final int startAttribIndex, List vertexAttributes) { + final int handle = handle(); + int attribIndex = startAttribIndex; + int offset = 0; + + for (var attribute : vertexAttributes) { + if (!attributeEnabled.get(attribIndex)) { + GL45C.glEnableVertexArrayAttrib(handle, attribIndex); + attributeEnabled.set(attribIndex); + } + + if (!attribute.equals(attributes[attribIndex])) { + if (attribute instanceof VertexAttribute.Float f) { + GL45C.glVertexArrayAttribFormat(handle, attribIndex, f.size(), f.type() + .getGlEnum(), f.normalized(), offset); + } else if (attribute instanceof VertexAttribute.Int vi) { + GL45C.glVertexArrayAttribIFormat(handle, attribIndex, vi.size(), vi.type() + .getGlEnum(), offset); + } + attributes[attribIndex] = attribute; + } + + if (attributeBindings[attribIndex] != bindingIndex) { + GL45C.glVertexArrayAttribBinding(handle, attribIndex, bindingIndex); + attributeBindings[attribIndex] = bindingIndex; + } + + attribIndex++; + offset += attribute.getByteWidth(); + } + } + + @Override + public void setElementBuffer(int ebo) { + if (elementBufferBinding != ebo) { + GL45C.glVertexArrayElementBuffer(handle(), ebo); + elementBufferBinding = ebo; + } + } + + private static boolean isSupported() { + var c = GlCompat.CAPABILITIES; + return GlCompat.ALLOW_DSA && Checks.checkFunctions(c.glCreateVertexArrays, c.glVertexArrayElementBuffer, c.glVertexArrayVertexBuffer, c.glVertexArrayBindingDivisor, c.glVertexArrayAttribBinding, c.glEnableVertexArrayAttrib, c.glVertexArrayAttribFormat, c.glVertexArrayAttribIFormat); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/gl/array/GlVertexArrayGL3.java b/src/main/java/com/jozufozu/flywheel/gl/array/GlVertexArrayGL3.java new file mode 100644 index 000000000..7104f840b --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/gl/array/GlVertexArrayGL3.java @@ -0,0 +1,153 @@ +package com.jozufozu.flywheel.gl.array; + +import java.util.BitSet; +import java.util.List; + +import org.lwjgl.opengl.ARBInstancedArrays; +import org.lwjgl.opengl.GL20C; +import org.lwjgl.opengl.GL30; +import org.lwjgl.opengl.GL32; +import org.lwjgl.opengl.GL33C; +import org.lwjgl.system.Checks; + +import com.jozufozu.flywheel.gl.GlCompat; +import com.jozufozu.flywheel.gl.buffer.GlBufferType; +import com.jozufozu.flywheel.util.FlwUtil; + +public abstract class GlVertexArrayGL3 extends GlVertexArray { + private final BitSet attributeDirty = new BitSet(MAX_ATTRIBS); + private final int[] attributeOffsets = new int[MAX_ATTRIBS]; + private final VertexAttribute[] attributes = new VertexAttribute[MAX_ATTRIBS]; + private final int[] attributeBindings = FlwUtil.initArray(MAX_ATTRIBS, -1); + private final int[] bindingBuffers = new int[MAX_ATTRIB_BINDINGS]; + private final long[] bindingOffsets = new long[MAX_ATTRIB_BINDINGS]; + private final int[] bindingStrides = new int[MAX_ATTRIB_BINDINGS]; + private final int[] bindingDivisors = new int[MAX_ATTRIB_BINDINGS]; + private int elementBufferBinding = 0; + + public GlVertexArrayGL3() { + handle(GL30.glGenVertexArrays()); + } + + @Override + public void bindForDraw() { + super.bindForDraw(); + + for (int attribIndex = attributeDirty.nextSetBit(0); attribIndex < MAX_ATTRIB_BINDINGS && attribIndex >= 0; attribIndex = attributeDirty.nextSetBit(attribIndex + 1)) { + + int bindingIndex = attributeBindings[attribIndex]; + var attribute = attributes[attribIndex]; + + if (bindingIndex == -1 || attribute == null) { + continue; + } + + GlBufferType.ARRAY_BUFFER.bind(bindingBuffers[bindingIndex]); + GL20C.glEnableVertexAttribArray(attribIndex); + + long offset = bindingOffsets[bindingIndex] + attributeOffsets[attribIndex]; + int stride = bindingStrides[bindingIndex]; + + if (attribute instanceof VertexAttribute.Float f) { + GL32.glVertexAttribPointer(attribIndex, f.size(), f.type() + .getGlEnum(), f.normalized(), stride, offset); + } else if (attribute instanceof VertexAttribute.Int vi) { + GL32.glVertexAttribIPointer(attribIndex, vi.size(), vi.type() + .getGlEnum(), stride, offset); + } + + int divisor = bindingDivisors[bindingIndex]; + if (divisor != 0) { + setDivisor(attribIndex, divisor); + } + } + + GlBufferType.ELEMENT_ARRAY_BUFFER.bind(elementBufferBinding); + + attributeDirty.clear(); + } + + protected abstract void setDivisor(int attribIndex, int divisor); + + @Override + public void bindVertexBuffer(int bindingIndex, int vbo, long offset, int stride) { + if (bindingBuffers[bindingIndex] != vbo || bindingOffsets[bindingIndex] != offset || bindingStrides[bindingIndex] != stride) { + bindingBuffers[bindingIndex] = vbo; + bindingOffsets[bindingIndex] = offset; + bindingStrides[bindingIndex] = stride; + + for (int attribIndex = 0; attribIndex < attributeBindings.length; attribIndex++) { + if (attributeBindings[attribIndex] == bindingIndex) { + attributeDirty.set(attribIndex); + } + } + } + } + + @Override + public void setBindingDivisor(int bindingIndex, int divisor) { + if (bindingDivisors[bindingIndex] != divisor) { + bindingDivisors[bindingIndex] = divisor; + } + } + + @Override + public void bindAttributes(int bindingIndex, int startAttribIndex, List vertexAttributes) { + int attribIndex = startAttribIndex; + int offset = 0; + + for (VertexAttribute attribute : vertexAttributes) { + attributeBindings[attribIndex] = bindingIndex; + attributes[attribIndex] = attribute; + attributeOffsets[attribIndex] = offset; + + attributeDirty.set(attribIndex); + + attribIndex++; + offset += attribute.getByteWidth(); + } + } + + @Override + public void setElementBuffer(int ebo) { + elementBufferBinding = ebo; + } + + public static class Core33 extends GlVertexArrayGL3 { + public static final boolean SUPPORTED = isSupported(); + + @Override + protected void setDivisor(int attribIndex, int divisor) { + GL33C.glVertexAttribDivisor(attribIndex, divisor); + } + + private static boolean isSupported() { + return Checks.checkFunctions(GlCompat.CAPABILITIES.glVertexAttribDivisor); + } + } + + public static class ARB extends GlVertexArrayGL3 { + public static final boolean SUPPORTED = isSupported(); + + @Override + protected void setDivisor(int attribIndex, int divisor) { + ARBInstancedArrays.glVertexAttribDivisorARB(attribIndex, divisor); + } + + private static boolean isSupported() { + return Checks.checkFunctions(GlCompat.CAPABILITIES.glVertexAttribDivisorARB); + } + } + + public static class Core extends GlVertexArrayGL3 { + @Override + protected void setDivisor(int attribIndex, int divisor) { + throw new UnsupportedOperationException("Instanced arrays are not supported"); + } + + @Override + public void setBindingDivisor(int bindingIndex, int divisor) { + throw new UnsupportedOperationException("Instanced arrays are not supported"); + } + } +} diff --git a/src/main/java/com/jozufozu/flywheel/gl/array/VertexArray.java b/src/main/java/com/jozufozu/flywheel/gl/array/VertexArray.java deleted file mode 100644 index cc7aee929..000000000 --- a/src/main/java/com/jozufozu/flywheel/gl/array/VertexArray.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.jozufozu.flywheel.gl.array; - -import org.lwjgl.opengl.ARBInstancedArrays; -import org.lwjgl.opengl.GL20C; -import org.lwjgl.opengl.GL30C; -import org.lwjgl.opengl.GL33C; -import org.lwjgl.opengl.GL45C; -import org.lwjgl.system.Checks; - -import com.jozufozu.flywheel.gl.GlCompat; -import com.jozufozu.flywheel.gl.GlStateTracker; -import com.jozufozu.flywheel.gl.buffer.GlBufferType; - -public interface VertexArray { - int create(); - - void setElementBuffer(int vao, int elementBuffer); - - void enableAttrib(int vao, int index); - - void setupAttrib(int vao, int index, int vbo, int stride, long offset, VertexAttribute attribute); - - void setAttribDivisor(int vao, int attrib, int divisor); - - abstract class GL3 implements VertexArray { - @Override - public int create() { - return GL30C.glGenVertexArrays(); - } - - @Override - public void setElementBuffer(int vao, int elementBuffer) { - GlStateTracker.bindVao(vao); - GlBufferType.ELEMENT_ARRAY_BUFFER.bind(elementBuffer); - } - - @Override - public void enableAttrib(int vao, int index) { - GlStateTracker.bindVao(vao); - GL20C.glEnableVertexAttribArray(index); - } - - @Override - public void setupAttrib(int vao, int index, int vbo, int stride, long offset, VertexAttribute attribute) { - GlStateTracker.bindVao(vao); - GlBufferType.ARRAY_BUFFER.bind(vbo); - attribute.setup(offset, index, stride); - } - } - - class InstancedArraysARB extends GL3 { - @Override - public void setAttribDivisor(int vao, int attrib, int divisor) { - GlStateTracker.bindVao(vao); - ARBInstancedArrays.glVertexAttribDivisorARB(attrib, divisor); - } - - public VertexArray fallback() { - if (Checks.checkFunctions(GlCompat.CAPABILITIES.glVertexAttribDivisorARB)) { - return this; - } - // null signals that we don't support instancing. - return null; - } - } - - class InstancedArraysCore extends GL3 { - @Override - public void setAttribDivisor(int vao, int attrib, int divisor) { - GlStateTracker.bindVao(vao); - GL33C.glVertexAttribDivisor(attrib, divisor); - } - - public VertexArray fallback() { - // We know vertex arrays are supported because minecraft required GL32. - if (Checks.checkFunctions(GlCompat.CAPABILITIES.glVertexAttribDivisor)) { - return this; - } - return new InstancedArraysARB().fallback(); - } - - } - - class DSA implements VertexArray { - @Override - public int create() { - return GL45C.glCreateVertexArrays(); - } - - @Override - public void setElementBuffer(int vao, int elementBuffer) { - GL45C.glVertexArrayElementBuffer(vao, elementBuffer); - } - - @Override - public void enableAttrib(int vao, int index) { - GL45C.glEnableVertexArrayAttrib(vao, index); - } - - @Override - public void setupAttrib(int vao, int index, int vbo, int stride, long offset, VertexAttribute attribute) { - GL45C.glVertexArrayVertexBuffer(vao, index, vbo, offset, stride); - attribute.setupDSA(vao, index); - } - - @Override - public void setAttribDivisor(int vao, int attrib, int divisor) { - GL45C.glVertexArrayBindingDivisor(vao, attrib, divisor); - } - - public VertexArray fallback() { - var c = GlCompat.CAPABILITIES; - if (Checks.checkFunctions(c.glCreateVertexArrays, c.glVertexArrayElementBuffer, c.glEnableVertexArrayAttrib, c.glVertexArrayVertexBuffer, c.glVertexArrayAttribFormat, c.glVertexArrayAttribIFormat)) { - - if (Checks.checkFunctions(c.glVertexArrayBindingDivisor)) { - return this; - } else if (Checks.checkFunctions(c.glVertexArrayVertexAttribDivisorEXT)) { - // Seems like this may happen when a driver supports - // ARB_direct_state_access but not core instanced arrays? - return new InstancedArraysEXTDSA(); - } - } - return new InstancedArraysCore().fallback(); - } - } - - class InstancedArraysEXTDSA extends DSA { - @Override - public void setAttribDivisor(int vao, int attrib, int divisor) { - ARBInstancedArrays.glVertexArrayVertexAttribDivisorEXT(vao, attrib, divisor); - } - } -} diff --git a/src/main/java/com/jozufozu/flywheel/gl/array/VertexAttribute.java b/src/main/java/com/jozufozu/flywheel/gl/array/VertexAttribute.java index 17e135c79..2ecd54a4b 100644 --- a/src/main/java/com/jozufozu/flywheel/gl/array/VertexAttribute.java +++ b/src/main/java/com/jozufozu/flywheel/gl/array/VertexAttribute.java @@ -1,22 +1,34 @@ package com.jozufozu.flywheel.gl.array; -public interface VertexAttribute { +import com.jozufozu.flywheel.gl.GlNumericType; + +public sealed interface VertexAttribute { int getByteWidth(); /** - * Apply this vertex attribute to the bound vertex array. + * A bindable attribute in a vertex array. * - * @param offset The byte offset to the first element of the attribute. - * @param i The attribute index. - * @param stride The byte stride between consecutive elements of the attribute. + * @param type The type of the attribute, e.g. GL_FLOAT. + * @param size The number of components in the attribute, e.g. 3 for a vec3. + * @param normalized Whether the data is normalized. */ - void setup(long offset, int i, int stride); + record Float(GlNumericType type, int size, boolean normalized) implements VertexAttribute { + @Override + public int getByteWidth() { + return size * type.getByteWidth(); + } + } /** - * Use DSA to apply this vertex attribute to the given vertex array. + * A bindable attribute in a vertex array. * - * @param vaobj The vertex array object to modify. - * @param i The attribute index. + * @param type The type of the attribute, e.g. GL_INT. + * @param size The number of components in the attribute, e.g. 3 for a vec3. */ - void setupDSA(int vaobj, int i); + record Int(GlNumericType type, int size) implements VertexAttribute { + @Override + public int getByteWidth() { + return size * type.getByteWidth(); + } + } } diff --git a/src/main/java/com/jozufozu/flywheel/gl/array/VertexAttributeF.java b/src/main/java/com/jozufozu/flywheel/gl/array/VertexAttributeF.java deleted file mode 100644 index 664949890..000000000 --- a/src/main/java/com/jozufozu/flywheel/gl/array/VertexAttributeF.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.jozufozu.flywheel.gl.array; - -import org.lwjgl.opengl.GL32; -import org.lwjgl.opengl.GL45; - -import com.jozufozu.flywheel.gl.GlNumericType; - -/** - * A bindable attribute in a vertex array. - * - * @param type The type of the attribute, e.g. GL_FLOAT. - * @param size The number of components in the attribute, e.g. 3 for a vec3. - * @param normalized Whether the data is normalized. - */ -public record VertexAttributeF(GlNumericType type, int size, boolean normalized) implements VertexAttribute { - @Override - public int getByteWidth() { - return size * type.getByteWidth(); - } - - @Override - public void setup(long offset, int i, int stride) { - GL32.glVertexAttribPointer(i, size(), type().getGlEnum(), normalized(), stride, offset); - } - - @Override - public void setupDSA(int vaobj, int i) { - GL45.glVertexArrayAttribFormat(vaobj, i, size(), type().getGlEnum(), normalized(), 0); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/gl/array/VertexAttributeI.java b/src/main/java/com/jozufozu/flywheel/gl/array/VertexAttributeI.java deleted file mode 100644 index f99633f8c..000000000 --- a/src/main/java/com/jozufozu/flywheel/gl/array/VertexAttributeI.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.jozufozu.flywheel.gl.array; - -import org.lwjgl.opengl.GL32; -import org.lwjgl.opengl.GL45; - -import com.jozufozu.flywheel.gl.GlNumericType; - -/** - * A bindable attribute in a vertex array. - * - * @param type The type of the attribute, e.g. GL_INT. - * @param size The number of components in the attribute, e.g. 3 for a vec3. - */ -public record VertexAttributeI(GlNumericType type, int size) implements VertexAttribute { - @Override - public int getByteWidth() { - return size * type.getByteWidth(); - } - - @Override - public void setup(long offset, int i, int stride) { - GL32.glVertexAttribIPointer(i, size(), type().getGlEnum(), stride, offset); - } - - @Override - public void setupDSA(int vaobj, int i) { - GL45.glVertexArrayAttribIFormat(vaobj, i, size(), type().getGlEnum(), 0); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/gl/buffer/Buffer.java b/src/main/java/com/jozufozu/flywheel/gl/buffer/Buffer.java index c5d1b03f6..0983f5608 100644 --- a/src/main/java/com/jozufozu/flywheel/gl/buffer/Buffer.java +++ b/src/main/java/com/jozufozu/flywheel/gl/buffer/Buffer.java @@ -46,12 +46,16 @@ public interface Buffer { } public Buffer fallback() { - var c = GlCompat.CAPABILITIES; - if (Checks.checkFunctions(c.glCreateBuffers, c.glNamedBufferData, c.glCopyNamedBufferSubData, c.glMapNamedBufferRange, c.glUnmapNamedBuffer)) { + if (GlCompat.ALLOW_DSA && dsaMethodsAvailable()) { return this; } return new Core(); } + + private static boolean dsaMethodsAvailable() { + var c = GlCompat.CAPABILITIES; + return Checks.checkFunctions(c.glCreateBuffers, c.glNamedBufferData, c.glCopyNamedBufferSubData, c.glMapNamedBufferRange, c.glUnmapNamedBuffer); + } } class Core implements Buffer { diff --git a/src/main/java/com/jozufozu/flywheel/gl/buffer/ElementBuffer.java b/src/main/java/com/jozufozu/flywheel/gl/buffer/ElementBuffer.java index 00dd26e97..8ee468976 100644 --- a/src/main/java/com/jozufozu/flywheel/gl/buffer/ElementBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/gl/buffer/ElementBuffer.java @@ -13,10 +13,6 @@ public class ElementBuffer { this.glBuffer = backing; } - public void bind() { - GlBufferType.ELEMENT_ARRAY_BUFFER.bind(glBuffer); - } - public int getElementCount() { return elementCount; } diff --git a/src/main/java/com/jozufozu/flywheel/gl/buffer/GlBuffer.java b/src/main/java/com/jozufozu/flywheel/gl/buffer/GlBuffer.java index e9c4ba90e..393a84326 100644 --- a/src/main/java/com/jozufozu/flywheel/gl/buffer/GlBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/gl/buffer/GlBuffer.java @@ -26,7 +26,7 @@ public class GlBuffer extends GlObject { } public GlBuffer(GlBufferUsage usage) { - setHandle(IMPL.create()); + handle(IMPL.create()); this.usage = usage; } @@ -71,7 +71,7 @@ public class GlBuffer extends GlObject { IMPL.data(newHandle, size, MemoryUtil.NULL, usage.glEnum); IMPL.copyData(oldHandle, newHandle, 0, 0, oldSize); glDeleteBuffers(oldHandle); - setHandle(newHandle); + handle(newHandle); FlwMemoryTracker._allocGPUMemory(size); } diff --git a/src/main/java/com/jozufozu/flywheel/gl/buffer/GlBufferType.java b/src/main/java/com/jozufozu/flywheel/gl/buffer/GlBufferType.java index f97090f74..179759307 100644 --- a/src/main/java/com/jozufozu/flywheel/gl/buffer/GlBufferType.java +++ b/src/main/java/com/jozufozu/flywheel/gl/buffer/GlBufferType.java @@ -9,7 +9,6 @@ import org.lwjgl.opengl.GL42; import org.lwjgl.opengl.GL43; import com.jozufozu.flywheel.gl.GlStateTracker; -import com.mojang.blaze3d.platform.GlStateManager; public enum GlBufferType { ARRAY_BUFFER(GL15C.GL_ARRAY_BUFFER, GL15C.GL_ARRAY_BUFFER_BINDING), @@ -55,16 +54,6 @@ public enum GlBufferType { } public void bind(int buffer) { - if (getBoundBuffer() != buffer) { - GlStateManager._glBindBuffer(glEnum, buffer); - } - } - - public void unbind() { - bind(0); - } - - public int getBoundBuffer() { - return GlStateTracker.getBuffer(this); + GlStateTracker.bindBuffer(this, buffer); } } diff --git a/src/main/java/com/jozufozu/flywheel/gl/shader/GlProgram.java b/src/main/java/com/jozufozu/flywheel/gl/shader/GlProgram.java index e3dac154e..d2172a2cb 100644 --- a/src/main/java/com/jozufozu/flywheel/gl/shader/GlProgram.java +++ b/src/main/java/com/jozufozu/flywheel/gl/shader/GlProgram.java @@ -14,7 +14,7 @@ public class GlProgram extends GlObject { private static final Logger LOGGER = LogUtils.getLogger(); public GlProgram(int handle) { - setHandle(handle); + handle(handle); } public void bind() { diff --git a/src/main/java/com/jozufozu/flywheel/gl/shader/GlShader.java b/src/main/java/com/jozufozu/flywheel/gl/shader/GlShader.java index 717f0ed53..e27cb4a43 100644 --- a/src/main/java/com/jozufozu/flywheel/gl/shader/GlShader.java +++ b/src/main/java/com/jozufozu/flywheel/gl/shader/GlShader.java @@ -13,7 +13,7 @@ public class GlShader extends GlObject { this.type = type; this.name = name; - setHandle(handle); + handle(handle); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/lib/layout/CommonItems.java b/src/main/java/com/jozufozu/flywheel/lib/layout/CommonItems.java index bd6165595..7ef1c6e0a 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/layout/CommonItems.java +++ b/src/main/java/com/jozufozu/flywheel/lib/layout/CommonItems.java @@ -1,8 +1,7 @@ package com.jozufozu.flywheel.lib.layout; import com.jozufozu.flywheel.gl.GlNumericType; -import com.jozufozu.flywheel.gl.array.VertexAttributeF; -import com.jozufozu.flywheel.gl.array.VertexAttributeI; +import com.jozufozu.flywheel.gl.array.VertexAttribute; public class CommonItems { private static final String VEC2_TYPE = "vec2"; @@ -17,51 +16,51 @@ public class CommonItems { private static final String LIGHT_COORD_TYPE = "LightCoord"; public static final VecInput LIGHT_COORD = VecInput.builder() - .vertexAttribute(new VertexAttributeI(GlNumericType.USHORT, 2)) + .vertexAttribute(new VertexAttribute.Int(GlNumericType.USHORT, 2)) .typeName(IVEC2_TYPE) .packedTypeName(LIGHT_COORD_TYPE) .unpackingFunction(expr -> expr.callFunction("unpackLightCoord")) .build(); public static final VecInput FLOAT = VecInput.builder() - .vertexAttribute(new VertexAttributeF(GlNumericType.FLOAT, 1, false)) + .vertexAttribute(new VertexAttribute.Float(GlNumericType.FLOAT, 1, false)) .typeName(FLOAT_TYPE) .packedTypeName(FLOAT_TYPE) .build(); public static final VecInput NORM_3x8 = VecInput.builder() - .vertexAttribute(new VertexAttributeF(GlNumericType.BYTE, 3, true)) + .vertexAttribute(new VertexAttribute.Float(GlNumericType.BYTE, 3, true)) .typeName(VEC3_TYPE) .packedTypeName(UINT_TYPE) .unpackingFunction(expr -> expr.callFunction("unpackSnorm4x8") .swizzle("xyz")) .build(); public static final VecInput UNORM_4x8 = VecInput.builder() - .vertexAttribute(new VertexAttributeF(GlNumericType.UBYTE, 4, true)) + .vertexAttribute(new VertexAttribute.Float(GlNumericType.UBYTE, 4, true)) .typeName(VEC4_TYPE) .packedTypeName(UINT_TYPE) .unpackingFunction(expr -> expr.callFunction("unpackUnorm4x8")) .build(); public static final VecInput UNORM_3x8 = VecInput.builder() - .vertexAttribute(new VertexAttributeF(GlNumericType.UBYTE, 3, true)) + .vertexAttribute(new VertexAttribute.Float(GlNumericType.UBYTE, 3, true)) .typeName(VEC3_TYPE) .packedTypeName(UINT_TYPE) .unpackingFunction(expr -> expr.callFunction("unpackUnorm4x8") .swizzle("xyz")) .build(); public static final VecInput VEC4 = VecInput.builder() - .vertexAttribute(new VertexAttributeF(GlNumericType.FLOAT, 4, false)) + .vertexAttribute(new VertexAttribute.Float(GlNumericType.FLOAT, 4, false)) .typeName(VEC4_TYPE) .packedTypeName(VEC4F_TYPE) .unpackingFunction(expr -> expr.callFunction("unpackVec4F")) .build(); public static final VecInput VEC3 = VecInput.builder() - .vertexAttribute(new VertexAttributeF(GlNumericType.FLOAT, 3, false)) + .vertexAttribute(new VertexAttribute.Float(GlNumericType.FLOAT, 3, false)) .typeName(VEC3_TYPE) .packedTypeName(VEC3F_TYPE) .unpackingFunction(expr -> expr.callFunction("unpackVec3F")) .build(); public static final VecInput VEC2 = VecInput.builder() - .vertexAttribute(new VertexAttributeF(GlNumericType.FLOAT, 2, false)) + .vertexAttribute(new VertexAttribute.Float(GlNumericType.FLOAT, 2, false)) .typeName(VEC2_TYPE) .packedTypeName(VEC2F_TYPE) .unpackingFunction(expr -> expr.callFunction("unpackVec2F")) diff --git a/src/main/java/com/jozufozu/flywheel/lib/layout/MatInput.java b/src/main/java/com/jozufozu/flywheel/lib/layout/MatInput.java index c9ead3911..096eb9637 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/layout/MatInput.java +++ b/src/main/java/com/jozufozu/flywheel/lib/layout/MatInput.java @@ -5,7 +5,6 @@ import java.util.function.Consumer; import com.jozufozu.flywheel.api.layout.InputType; import com.jozufozu.flywheel.gl.GlNumericType; import com.jozufozu.flywheel.gl.array.VertexAttribute; -import com.jozufozu.flywheel.gl.array.VertexAttributeF; import com.jozufozu.flywheel.glsl.generate.GlslExpr; public record MatInput(int rows, int cols, String typeName, String packedTypeName, @@ -14,7 +13,7 @@ public record MatInput(int rows, int cols, String typeName, String packedTypeNam @Override public void provideAttributes(Consumer consumer) { for (int i = 0; i < rows; i++) { - consumer.accept(new VertexAttributeF(GlNumericType.FLOAT, cols, false)); + consumer.accept(new VertexAttribute.Float(GlNumericType.FLOAT, cols, false)); } } diff --git a/src/main/java/com/jozufozu/flywheel/lib/material/SimpleMaterial.java b/src/main/java/com/jozufozu/flywheel/lib/material/SimpleMaterial.java index e25cb070a..4d0c76c5d 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/material/SimpleMaterial.java +++ b/src/main/java/com/jozufozu/flywheel/lib/material/SimpleMaterial.java @@ -127,7 +127,7 @@ public class SimpleMaterial implements Material { } public static GlStateShard fromVanilla(RenderStateShard vanillaShard) { - return new GlStateShard(() -> vanillaShard.setupRenderState(), () -> vanillaShard.clearRenderState()); + return new GlStateShard(vanillaShard::setupRenderState, vanillaShard::clearRenderState); } public Runnable getSetup() { diff --git a/src/main/java/com/jozufozu/flywheel/lib/util/FullscreenQuad.java b/src/main/java/com/jozufozu/flywheel/lib/util/FullscreenQuad.java index 3be265223..aed6f4591 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/util/FullscreenQuad.java +++ b/src/main/java/com/jozufozu/flywheel/lib/util/FullscreenQuad.java @@ -47,16 +47,20 @@ public class FullscreenQuad { Flywheel.LOGGER.error("Could not create fullscreen quad.", e); } - vao = new GlVertexArray(); + vao = GlVertexArray.create(); - vao.bindAttributes(LAYOUT, vbo.handle(), 0, 0L); - } + vao.bindVertexBuffer(0, vbo.handle(), 0L, LAYOUT.getStride()); + vao.bindAttributes(0, 0, LAYOUT.attributes()); + } } + /** + * Draw the fullscreen quad.
+ * note: may bind a VAO, but will not restore prior state. + */ public void draw() { vao.bindForDraw(); glDrawArrays(GL_TRIANGLES, 0, 6); - GlVertexArray.unbind(); } public void delete() { diff --git a/src/main/java/com/jozufozu/flywheel/lib/util/QuadConverter.java b/src/main/java/com/jozufozu/flywheel/lib/util/QuadConverter.java index 3dd415bf8..8c6dfae49 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/util/QuadConverter.java +++ b/src/main/java/com/jozufozu/flywheel/lib/util/QuadConverter.java @@ -2,15 +2,14 @@ package com.jozufozu.flywheel.lib.util; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.lwjgl.opengl.GL32; -import org.lwjgl.opengl.GL32C; import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.api.event.ReloadRenderersEvent; import com.jozufozu.flywheel.gl.GlNumericType; import com.jozufozu.flywheel.gl.buffer.ElementBuffer; -import com.jozufozu.flywheel.gl.buffer.GlBufferType; +import com.jozufozu.flywheel.gl.buffer.GlBuffer; import com.jozufozu.flywheel.gl.buffer.GlBufferUsage; +import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.vertex.VertexFormat; import it.unimi.dsi.fastutil.ints.Int2ReferenceArrayMap; @@ -41,7 +40,7 @@ public class QuadConverter { private int quadCapacity; public QuadConverter() { - this.ebo = GL32.glGenBuffers(); + this.ebo = GlBuffer.IMPL.create(); this.quadCapacity = 0; } @@ -64,11 +63,7 @@ public class QuadConverter { fillBuffer(ptr, quads); - final var bufferType = GlBufferType.ARRAY_BUFFER; - final int oldBuffer = bufferType.getBoundBuffer(); - bufferType.bind(ebo); - GL32C.nglBufferData(bufferType.glEnum, byteSize, ptr, GlBufferUsage.STATIC_DRAW.glEnum); - bufferType.bind(oldBuffer); + GlBuffer.IMPL.data(ebo, byteSize, ptr, GlBufferUsage.STATIC_DRAW.glEnum); MemoryUtil.nmemFree(ptr); @@ -76,7 +71,7 @@ public class QuadConverter { } public void delete() { - GL32.glDeleteBuffers(ebo); + GlStateManager._glDeleteBuffers(ebo); this.cache.clear(); this.quadCapacity = 0; } diff --git a/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java b/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java index 46456acef..8d7f553ab 100644 --- a/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java +++ b/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java @@ -1,5 +1,6 @@ package com.jozufozu.flywheel.util; +import java.util.Arrays; import java.util.Collections; import java.util.Set; import java.util.WeakHashMap; @@ -49,8 +50,20 @@ public final class FlwUtil { public static PoseStack copyPoseStack(PoseStack stack) { PoseStack copy = new PoseStack(); - copy.last().pose().load(stack.last().pose()); - copy.last().normal().load(stack.last().normal()); + copy.last() + .pose() + .load(stack.last() + .pose()); + copy.last() + .normal() + .load(stack.last() + .normal()); return copy; } + + public static int[] initArray(int size, int fill) { + var out = new int[size]; + Arrays.fill(out, fill); + return out; + } }