mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-06 04:16:36 +01:00
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.
This commit is contained in:
parent
19824e7a3c
commit
e2bcc5f325
29 changed files with 398 additions and 405 deletions
|
@ -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) {
|
||||
|
|
|
@ -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<I extends Instance> {
|
|||
|
||||
meshPool = new IndirectMeshPool(vertexType, 1024);
|
||||
|
||||
vertexArray = new GlVertexArray();
|
||||
vertexArray = GlVertexArray.create();
|
||||
|
||||
elementBuffer = QuadConverter.getInstance()
|
||||
.quads2Tris(2048).glBuffer;
|
||||
|
@ -64,7 +64,9 @@ public class IndirectCullingGroup<I extends Instance> {
|
|||
|
||||
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<I extends Instance> {
|
|||
memoryBarrier();
|
||||
|
||||
drawSet.submit(stage);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
private void memoryBarrier() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -79,16 +79,14 @@ public class GPUInstancer<I extends Instance> extends AbstractInstancer<I> {
|
|||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ public class GlTexture extends GlObject {
|
|||
|
||||
public GlTexture(int textureType) {
|
||||
this.textureType = textureType;
|
||||
setHandle(GL20.glGenTextures());
|
||||
handle(GL20.glGenTextures());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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<VertexAttribute> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<VertexAttribute> 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);
|
||||
}
|
||||
}
|
|
@ -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<VertexAttribute> 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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -13,10 +13,6 @@ public class ElementBuffer {
|
|||
this.glBuffer = backing;
|
||||
}
|
||||
|
||||
public void bind() {
|
||||
GlBufferType.ELEMENT_ARRAY_BUFFER.bind(glBuffer);
|
||||
}
|
||||
|
||||
public int getElementCount() {
|
||||
return elementCount;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -13,7 +13,7 @@ public class GlShader extends GlObject {
|
|||
this.type = type;
|
||||
this.name = name;
|
||||
|
||||
setHandle(handle);
|
||||
handle(handle);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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"))
|
||||
|
|
|
@ -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<VertexAttribute> 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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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.<br>
|
||||
* 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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue