mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-08 13:26:39 +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;
|
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.glDeleteBuffers;
|
||||||
import static org.lwjgl.opengl.GL15.nglDeleteBuffers;
|
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_FLUSH_EXPLICIT_BIT;
|
||||||
import static org.lwjgl.opengl.GL30.GL_MAP_WRITE_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.GL43.GL_SHADER_STORAGE_BUFFER;
|
||||||
import static org.lwjgl.opengl.GL44.GL_DYNAMIC_STORAGE_BIT;
|
import static org.lwjgl.opengl.GL44.GL_DYNAMIC_STORAGE_BIT;
|
||||||
import static org.lwjgl.opengl.GL44.GL_MAP_PERSISTENT_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.MemoryUtil;
|
||||||
import org.lwjgl.system.Pointer;
|
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.FlwMemoryTracker;
|
||||||
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
|
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 BATCH_SIZE_OFFSET = TARGET_SIZE_OFFSET + PTR_SIZE;
|
||||||
private static final long DRAW_SIZE_OFFSET = BATCH_SIZE_OFFSET + PTR_SIZE;
|
private static final long DRAW_SIZE_OFFSET = BATCH_SIZE_OFFSET + PTR_SIZE;
|
||||||
|
|
||||||
final MemoryBlock buffers;
|
private final MemoryBlock buffers;
|
||||||
final long objectStride;
|
private final long objectStride;
|
||||||
int object;
|
private int object;
|
||||||
int target;
|
private int target;
|
||||||
int batch;
|
private int batch;
|
||||||
int draw;
|
private int draw;
|
||||||
|
|
||||||
long objectPtr;
|
long objectPtr;
|
||||||
long batchPtr;
|
long batchPtr;
|
||||||
long drawPtr;
|
long drawPtr;
|
||||||
|
|
||||||
int maxObjectCount = 0;
|
private int maxObjectCount = 0;
|
||||||
int maxDrawCount = 0;
|
private int maxDrawCount = 0;
|
||||||
|
|
||||||
float objectGrowthFactor = 2f;
|
private static final float OBJECT_GROWTH_FACTOR = 2f;
|
||||||
float drawGrowthFactor = 2f;
|
private static final float DRAW_GROWTH_FACTOR = 2f;
|
||||||
|
|
||||||
IndirectBuffers(long objectStride) {
|
IndirectBuffers(long objectStride) {
|
||||||
this.objectStride = objectStride;
|
this.objectStride = objectStride;
|
||||||
|
@ -81,20 +80,11 @@ public class IndirectBuffers {
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateCounts(int objectCount, int drawCount) {
|
void updateCounts(int objectCount, int drawCount) {
|
||||||
|
|
||||||
if (objectCount > maxObjectCount) {
|
if (objectCount > maxObjectCount) {
|
||||||
var newObjectCount = maxObjectCount;
|
createObjectStorage((int) (objectCount * OBJECT_GROWTH_FACTOR));
|
||||||
while (newObjectCount <= objectCount) {
|
|
||||||
newObjectCount *= objectGrowthFactor;
|
|
||||||
}
|
|
||||||
createObjectStorage(newObjectCount);
|
|
||||||
}
|
}
|
||||||
if (drawCount > maxDrawCount) {
|
if (drawCount > maxDrawCount) {
|
||||||
var newDrawCount = maxDrawCount;
|
createDrawStorage((int) (drawCount * DRAW_GROWTH_FACTOR));
|
||||||
while (newDrawCount <= drawCount) {
|
|
||||||
newDrawCount *= drawGrowthFactor;
|
|
||||||
}
|
|
||||||
createDrawStorage(newDrawCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final long objectSize = objectStride * objectCount;
|
final long objectSize = objectStride * objectCount;
|
||||||
|
@ -114,7 +104,7 @@ public class IndirectBuffers {
|
||||||
var targetSize = INT_SIZE * objectCount;
|
var targetSize = INT_SIZE * objectCount;
|
||||||
|
|
||||||
if (maxObjectCount > 0) {
|
if (maxObjectCount > 0) {
|
||||||
var ptr = buffers.ptr();
|
final long ptr = buffers.ptr();
|
||||||
nglCreateBuffers(3, ptr);
|
nglCreateBuffers(3, ptr);
|
||||||
|
|
||||||
int objectNew = MemoryUtil.memGetInt(ptr);
|
int objectNew = MemoryUtil.memGetInt(ptr);
|
||||||
|
@ -181,21 +171,17 @@ public class IndirectBuffers {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bindForCompute() {
|
public void bindForCompute() {
|
||||||
multiBind(BUFFER_COUNT);
|
multiBind();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bindForDraw() {
|
public void bindForDraw() {
|
||||||
multiBind(BUFFER_COUNT);
|
multiBind();
|
||||||
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, draw);
|
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();
|
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) {
|
void flushBatchIDs(long length) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.jozufozu.flywheel.backend.engine.indirect;
|
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.GL_COMMAND_BARRIER_BIT;
|
||||||
import static org.lwjgl.opengl.GL42.glMemoryBarrier;
|
import static org.lwjgl.opengl.GL42.glMemoryBarrier;
|
||||||
import static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BARRIER_BIT;
|
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.event.RenderStage;
|
||||||
import com.jozufozu.flywheel.api.instance.Instance;
|
import com.jozufozu.flywheel.api.instance.Instance;
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
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.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.backend.compile.IndirectPrograms;
|
import com.jozufozu.flywheel.backend.compile.IndirectPrograms;
|
||||||
import com.jozufozu.flywheel.backend.engine.UniformBuffer;
|
import com.jozufozu.flywheel.backend.engine.UniformBuffer;
|
||||||
|
@ -51,7 +51,7 @@ public class IndirectCullingGroup<I extends Instance> {
|
||||||
|
|
||||||
meshPool = new IndirectMeshPool(vertexType, 1024);
|
meshPool = new IndirectMeshPool(vertexType, 1024);
|
||||||
|
|
||||||
vertexArray = new GlVertexArray();
|
vertexArray = GlVertexArray.create();
|
||||||
|
|
||||||
elementBuffer = QuadConverter.getInstance()
|
elementBuffer = QuadConverter.getInstance()
|
||||||
.quads2Tris(2048).glBuffer;
|
.quads2Tris(2048).glBuffer;
|
||||||
|
@ -64,7 +64,9 @@ public class IndirectCullingGroup<I extends Instance> {
|
||||||
|
|
||||||
private void setupVertexArray() {
|
private void setupVertexArray() {
|
||||||
vertexArray.setElementBuffer(elementBuffer);
|
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() {
|
void beginFrame() {
|
||||||
|
@ -116,7 +118,6 @@ public class IndirectCullingGroup<I extends Instance> {
|
||||||
memoryBarrier();
|
memoryBarrier();
|
||||||
|
|
||||||
drawSet.submit(stage);
|
drawSet.submit(stage);
|
||||||
glBindVertexArray(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void memoryBarrier() {
|
private void memoryBarrier() {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.jozufozu.flywheel.backend.engine.instancing;
|
package com.jozufozu.flywheel.backend.engine.instancing;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.gl.GlStateTracker;
|
|
||||||
import com.jozufozu.flywheel.gl.array.GlVertexArray;
|
import com.jozufozu.flywheel.gl.array.GlVertexArray;
|
||||||
|
|
||||||
public class DrawCall {
|
public class DrawCall {
|
||||||
|
@ -15,7 +14,7 @@ public class DrawCall {
|
||||||
this.mesh = mesh;
|
this.mesh = mesh;
|
||||||
|
|
||||||
meshAttributes = this.mesh.getAttributeCount();
|
meshAttributes = this.mesh.getAttributeCount();
|
||||||
vao = new GlVertexArray();
|
vao = GlVertexArray.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInvalid() {
|
public boolean isInvalid() {
|
||||||
|
@ -27,15 +26,19 @@ public class DrawCall {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try (var ignored = GlStateTracker.getRestoreState()) {
|
|
||||||
instancer.update();
|
instancer.update();
|
||||||
|
|
||||||
instancer.bindToVAO(vao, meshAttributes);
|
int instanceCount = instancer.getInstanceCount();
|
||||||
|
if (instanceCount <= 0 || mesh.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (instancer.getInstanceCount() > 0) {
|
instancer.bindToVAO(vao, meshAttributes);
|
||||||
mesh.drawInstances(vao, instancer.getInstanceCount());
|
mesh.setup(vao);
|
||||||
}
|
|
||||||
}
|
vao.bindForDraw();
|
||||||
|
|
||||||
|
mesh.draw(instanceCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
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)) {
|
if (!boundTo.add(vao)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vao.bindAttributes(instanceFormat, vbo.handle(), attributeOffset, 0L);
|
vao.bindVertexBuffer(1, vbo.handle(), 0L, instanceStride);
|
||||||
|
vao.setBindingDivisor(1, 1);
|
||||||
for (int i = 0; i < instanceFormat.getAttributeCount(); i++) {
|
vao.bindAttributes(1, startAttrib, instanceFormat.attributes());
|
||||||
vao.setAttributeDivisor(attributeOffset + i, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable;
|
||||||
import org.lwjgl.opengl.GL32;
|
import org.lwjgl.opengl.GL32;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.Flywheel;
|
import com.jozufozu.flywheel.Flywheel;
|
||||||
|
import com.jozufozu.flywheel.api.layout.BufferLayout;
|
||||||
import com.jozufozu.flywheel.api.model.Mesh;
|
import com.jozufozu.flywheel.api.model.Mesh;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.gl.GlPrimitive;
|
import com.jozufozu.flywheel.gl.GlPrimitive;
|
||||||
|
@ -172,7 +173,7 @@ public class InstancedMeshPool {
|
||||||
return deleted;
|
return deleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return mesh.isEmpty() || isDeleted();
|
return mesh.isEmpty() || isDeleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,25 +183,16 @@ public class InstancedMeshPool {
|
||||||
boundTo.clear();
|
boundTo.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawInstances(GlVertexArray vao, int instanceCount) {
|
public void setup(GlVertexArray vao) {
|
||||||
if (isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setup(vao);
|
|
||||||
|
|
||||||
draw(instanceCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setup(GlVertexArray vao) {
|
|
||||||
if (boundTo.add(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.setElementBuffer(ebo.glBuffer);
|
||||||
}
|
}
|
||||||
vao.bindForDraw();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void draw(int instanceCount) {
|
public void draw(int instanceCount) {
|
||||||
if (instanceCount > 1) {
|
if (instanceCount > 1) {
|
||||||
GL32.glDrawElementsInstanced(GlPrimitive.TRIANGLES.glEnum, ebo.getElementCount(), ebo.getEboIndexType().asGLType, 0, instanceCount);
|
GL32.glDrawElementsInstanced(GlPrimitive.TRIANGLES.glEnum, ebo.getElementCount(), ebo.getEboIndexType().asGLType, 0, instanceCount);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -8,8 +8,6 @@ import org.lwjgl.opengl.GL20C;
|
||||||
import org.lwjgl.opengl.GLCapabilities;
|
import org.lwjgl.opengl.GLCapabilities;
|
||||||
import org.lwjgl.system.MemoryStack;
|
import org.lwjgl.system.MemoryStack;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.gl.array.GlVertexArray;
|
|
||||||
|
|
||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,6 +17,7 @@ import net.minecraft.Util;
|
||||||
* system.
|
* system.
|
||||||
*/
|
*/
|
||||||
public class GlCompat {
|
public class GlCompat {
|
||||||
|
public static final boolean ALLOW_DSA = true;
|
||||||
public static final GLCapabilities CAPABILITIES = GL.createCapabilities();
|
public static final GLCapabilities CAPABILITIES = GL.createCapabilities();
|
||||||
private static final boolean amd = _decideIfWeAreAMDWindows();
|
private static final boolean amd = _decideIfWeAreAMDWindows();
|
||||||
private static final boolean supportsIndirect = _decideIfWeSupportIndirect();
|
private static final boolean supportsIndirect = _decideIfWeSupportIndirect();
|
||||||
|
@ -31,7 +30,7 @@ public class GlCompat {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean supportsInstancing() {
|
public static boolean supportsInstancing() {
|
||||||
return GlVertexArray.IMPL != null;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean supportsIndirect() {
|
public static boolean supportsIndirect() {
|
||||||
|
|
|
@ -17,6 +17,7 @@ public enum GlNumericType {
|
||||||
SHORT(2, "short", GL11.GL_SHORT),
|
SHORT(2, "short", GL11.GL_SHORT),
|
||||||
UINT(4, "uint", GL11.GL_UNSIGNED_INT),
|
UINT(4, "uint", GL11.GL_UNSIGNED_INT),
|
||||||
INT(4, "int", GL11.GL_INT),
|
INT(4, "int", GL11.GL_INT),
|
||||||
|
DOUBLE(8, "double", GL11.GL_DOUBLE),
|
||||||
;
|
;
|
||||||
|
|
||||||
private static final GlNumericType[] VALUES = values();
|
private static final GlNumericType[] VALUES = values();
|
||||||
|
|
|
@ -6,18 +6,18 @@ public abstract class GlObject {
|
||||||
|
|
||||||
private int handle = INVALID_HANDLE;
|
private int handle = INVALID_HANDLE;
|
||||||
|
|
||||||
protected final void setHandle(int handle) {
|
protected final void handle(int handle) {
|
||||||
this.handle = handle;
|
this.handle = handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int handle() {
|
public final int handle() {
|
||||||
this.checkHandle();
|
checkHandle();
|
||||||
|
|
||||||
return this.handle;
|
return this.handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void checkHandle() {
|
protected final void checkHandle() {
|
||||||
if (this.isInvalid()) {
|
if (isInvalid()) {
|
||||||
throw new IllegalStateException("handle is not valid.");
|
throw new IllegalStateException("handle is not valid.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ public abstract class GlObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
if (this.isInvalid()) {
|
if (isInvalid()) {
|
||||||
throw new IllegalStateException("handle already deleted.");
|
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 record State(int[] buffers, int vao, int program) implements AutoCloseable {
|
||||||
public void restore() {
|
public void restore() {
|
||||||
if (vao != GlStateTracker.vao) {
|
if (vao != GlStateTracker.vao) {
|
||||||
|
@ -54,7 +60,7 @@ public class GlStateTracker {
|
||||||
GlBufferType[] values = GlBufferType.values();
|
GlBufferType[] values = GlBufferType.values();
|
||||||
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
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]);
|
GlStateManager._glBindBuffer(values[i].glEnum, buffers[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ public class GlTexture extends GlObject {
|
||||||
|
|
||||||
public GlTexture(int textureType) {
|
public GlTexture(int textureType) {
|
||||||
this.textureType = textureType;
|
this.textureType = textureType;
|
||||||
setHandle(GL20.glGenTextures());
|
handle(GL20.glGenTextures());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,99 +1,43 @@
|
||||||
package com.jozufozu.flywheel.gl.array;
|
package com.jozufozu.flywheel.gl.array;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL32;
|
import org.lwjgl.opengl.GL32;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.layout.BufferLayout;
|
|
||||||
import com.jozufozu.flywheel.gl.GlObject;
|
import com.jozufozu.flywheel.gl.GlObject;
|
||||||
import com.jozufozu.flywheel.gl.GlStateTracker;
|
import com.jozufozu.flywheel.gl.GlStateTracker;
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
|
|
||||||
public class GlVertexArray extends GlObject {
|
public abstract class GlVertexArray extends GlObject {
|
||||||
public static final VertexArray IMPL = new VertexArray.DSA().fallback();
|
protected static final int MAX_ATTRIBS = GL32.glGetInteger(GL32.GL_MAX_VERTEX_ATTRIBS);
|
||||||
private static final int MAX_ATTRIBS = GL32.glGetInteger(GL32.GL_MAX_VERTEX_ATTRIBS);
|
protected static final int MAX_ATTRIB_BINDINGS = 16;
|
||||||
|
|
||||||
/**
|
public static GlVertexArray create() {
|
||||||
* Whether each attribute is enabled.
|
if (GlVertexArrayDSA.SUPPORTED) {
|
||||||
*/
|
return new GlVertexArrayDSA();
|
||||||
private final boolean[] enabled = new boolean[MAX_ATTRIBS];
|
} else if (GlVertexArrayGL3.Core33.SUPPORTED) {
|
||||||
/**
|
return new GlVertexArrayGL3.Core33();
|
||||||
* Each attribute's divisor.
|
} else if (GlVertexArrayGL3.ARB.SUPPORTED) {
|
||||||
*/
|
return new GlVertexArrayGL3.ARB();
|
||||||
private final int[] divisors = new int[MAX_ATTRIBS];
|
} else {
|
||||||
/**
|
return new GlVertexArrayGL3.Core();
|
||||||
* 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 void bindForDraw() {
|
public void bindForDraw() {
|
||||||
GlStateTracker.bindVao(handle());
|
GlStateTracker.bindVao(handle());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void unbind() {
|
public abstract void bindVertexBuffer(int bindingIndex, int vbo, long offset, int stride);
|
||||||
GlStateManager._glBindVertexArray(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void bindAttributes(BufferLayout type, final int vbo, final int startAttrib, final long startOffset) {
|
public abstract void setBindingDivisor(int bindingIndex, int divisor);
|
||||||
final int vao = handle();
|
|
||||||
final int stride = type.getStride();
|
|
||||||
|
|
||||||
int index = startAttrib;
|
public abstract void bindAttributes(int bindingIndex, int startAttribIndex, List<VertexAttribute> vertexAttributes);
|
||||||
long offset = startOffset;
|
|
||||||
for (var attribute : type.attributes()) {
|
|
||||||
if (!enabled[index]) {
|
|
||||||
IMPL.enableAttrib(vao, index);
|
|
||||||
enabled[index] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldSetupAttrib(index, vbo, stride, offset, attribute)) {
|
public abstract void setElementBuffer(int ebo);
|
||||||
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]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
protected void deleteInternal(int handle) {
|
protected void deleteInternal(int handle) {
|
||||||
GlStateManager._glDeleteVertexArrays(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;
|
package com.jozufozu.flywheel.gl.array;
|
||||||
|
|
||||||
public interface VertexAttribute {
|
import com.jozufozu.flywheel.gl.GlNumericType;
|
||||||
|
|
||||||
|
public sealed interface VertexAttribute {
|
||||||
int getByteWidth();
|
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 type The type of the attribute, e.g. GL_FLOAT.
|
||||||
* @param i The attribute index.
|
* @param size The number of components in the attribute, e.g. 3 for a vec3.
|
||||||
* @param stride The byte stride between consecutive elements of the attribute.
|
* @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 type The type of the attribute, e.g. GL_INT.
|
||||||
* @param i The attribute index.
|
* @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() {
|
public Buffer fallback() {
|
||||||
var c = GlCompat.CAPABILITIES;
|
if (GlCompat.ALLOW_DSA && dsaMethodsAvailable()) {
|
||||||
if (Checks.checkFunctions(c.glCreateBuffers, c.glNamedBufferData, c.glCopyNamedBufferSubData, c.glMapNamedBufferRange, c.glUnmapNamedBuffer)) {
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
return new Core();
|
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 {
|
class Core implements Buffer {
|
||||||
|
|
|
@ -13,10 +13,6 @@ public class ElementBuffer {
|
||||||
this.glBuffer = backing;
|
this.glBuffer = backing;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bind() {
|
|
||||||
GlBufferType.ELEMENT_ARRAY_BUFFER.bind(glBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getElementCount() {
|
public int getElementCount() {
|
||||||
return elementCount;
|
return elementCount;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ public class GlBuffer extends GlObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public GlBuffer(GlBufferUsage usage) {
|
public GlBuffer(GlBufferUsage usage) {
|
||||||
setHandle(IMPL.create());
|
handle(IMPL.create());
|
||||||
this.usage = usage;
|
this.usage = usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ public class GlBuffer extends GlObject {
|
||||||
IMPL.data(newHandle, size, MemoryUtil.NULL, usage.glEnum);
|
IMPL.data(newHandle, size, MemoryUtil.NULL, usage.glEnum);
|
||||||
IMPL.copyData(oldHandle, newHandle, 0, 0, oldSize);
|
IMPL.copyData(oldHandle, newHandle, 0, 0, oldSize);
|
||||||
glDeleteBuffers(oldHandle);
|
glDeleteBuffers(oldHandle);
|
||||||
setHandle(newHandle);
|
handle(newHandle);
|
||||||
|
|
||||||
FlwMemoryTracker._allocGPUMemory(size);
|
FlwMemoryTracker._allocGPUMemory(size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ import org.lwjgl.opengl.GL42;
|
||||||
import org.lwjgl.opengl.GL43;
|
import org.lwjgl.opengl.GL43;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.gl.GlStateTracker;
|
import com.jozufozu.flywheel.gl.GlStateTracker;
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
|
||||||
|
|
||||||
public enum GlBufferType {
|
public enum GlBufferType {
|
||||||
ARRAY_BUFFER(GL15C.GL_ARRAY_BUFFER, GL15C.GL_ARRAY_BUFFER_BINDING),
|
ARRAY_BUFFER(GL15C.GL_ARRAY_BUFFER, GL15C.GL_ARRAY_BUFFER_BINDING),
|
||||||
|
@ -55,16 +54,6 @@ public enum GlBufferType {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bind(int buffer) {
|
public void bind(int buffer) {
|
||||||
if (getBoundBuffer() != buffer) {
|
GlStateTracker.bindBuffer(this, buffer);
|
||||||
GlStateManager._glBindBuffer(glEnum, buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unbind() {
|
|
||||||
bind(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getBoundBuffer() {
|
|
||||||
return GlStateTracker.getBuffer(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ public class GlProgram extends GlObject {
|
||||||
private static final Logger LOGGER = LogUtils.getLogger();
|
private static final Logger LOGGER = LogUtils.getLogger();
|
||||||
|
|
||||||
public GlProgram(int handle) {
|
public GlProgram(int handle) {
|
||||||
setHandle(handle);
|
handle(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bind() {
|
public void bind() {
|
||||||
|
|
|
@ -13,7 +13,7 @@ public class GlShader extends GlObject {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
||||||
setHandle(handle);
|
handle(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
package com.jozufozu.flywheel.lib.layout;
|
package com.jozufozu.flywheel.lib.layout;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.gl.GlNumericType;
|
import com.jozufozu.flywheel.gl.GlNumericType;
|
||||||
import com.jozufozu.flywheel.gl.array.VertexAttributeF;
|
import com.jozufozu.flywheel.gl.array.VertexAttribute;
|
||||||
import com.jozufozu.flywheel.gl.array.VertexAttributeI;
|
|
||||||
|
|
||||||
public class CommonItems {
|
public class CommonItems {
|
||||||
private static final String VEC2_TYPE = "vec2";
|
private static final String VEC2_TYPE = "vec2";
|
||||||
|
@ -17,51 +16,51 @@ public class CommonItems {
|
||||||
private static final String LIGHT_COORD_TYPE = "LightCoord";
|
private static final String LIGHT_COORD_TYPE = "LightCoord";
|
||||||
|
|
||||||
public static final VecInput LIGHT_COORD = VecInput.builder()
|
public static final VecInput LIGHT_COORD = VecInput.builder()
|
||||||
.vertexAttribute(new VertexAttributeI(GlNumericType.USHORT, 2))
|
.vertexAttribute(new VertexAttribute.Int(GlNumericType.USHORT, 2))
|
||||||
.typeName(IVEC2_TYPE)
|
.typeName(IVEC2_TYPE)
|
||||||
.packedTypeName(LIGHT_COORD_TYPE)
|
.packedTypeName(LIGHT_COORD_TYPE)
|
||||||
.unpackingFunction(expr -> expr.callFunction("unpackLightCoord"))
|
.unpackingFunction(expr -> expr.callFunction("unpackLightCoord"))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
public static final VecInput FLOAT = VecInput.builder()
|
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)
|
.typeName(FLOAT_TYPE)
|
||||||
.packedTypeName(FLOAT_TYPE)
|
.packedTypeName(FLOAT_TYPE)
|
||||||
.build();
|
.build();
|
||||||
public static final VecInput NORM_3x8 = VecInput.builder()
|
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)
|
.typeName(VEC3_TYPE)
|
||||||
.packedTypeName(UINT_TYPE)
|
.packedTypeName(UINT_TYPE)
|
||||||
.unpackingFunction(expr -> expr.callFunction("unpackSnorm4x8")
|
.unpackingFunction(expr -> expr.callFunction("unpackSnorm4x8")
|
||||||
.swizzle("xyz"))
|
.swizzle("xyz"))
|
||||||
.build();
|
.build();
|
||||||
public static final VecInput UNORM_4x8 = VecInput.builder()
|
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)
|
.typeName(VEC4_TYPE)
|
||||||
.packedTypeName(UINT_TYPE)
|
.packedTypeName(UINT_TYPE)
|
||||||
.unpackingFunction(expr -> expr.callFunction("unpackUnorm4x8"))
|
.unpackingFunction(expr -> expr.callFunction("unpackUnorm4x8"))
|
||||||
.build();
|
.build();
|
||||||
public static final VecInput UNORM_3x8 = VecInput.builder()
|
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)
|
.typeName(VEC3_TYPE)
|
||||||
.packedTypeName(UINT_TYPE)
|
.packedTypeName(UINT_TYPE)
|
||||||
.unpackingFunction(expr -> expr.callFunction("unpackUnorm4x8")
|
.unpackingFunction(expr -> expr.callFunction("unpackUnorm4x8")
|
||||||
.swizzle("xyz"))
|
.swizzle("xyz"))
|
||||||
.build();
|
.build();
|
||||||
public static final VecInput VEC4 = VecInput.builder()
|
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)
|
.typeName(VEC4_TYPE)
|
||||||
.packedTypeName(VEC4F_TYPE)
|
.packedTypeName(VEC4F_TYPE)
|
||||||
.unpackingFunction(expr -> expr.callFunction("unpackVec4F"))
|
.unpackingFunction(expr -> expr.callFunction("unpackVec4F"))
|
||||||
.build();
|
.build();
|
||||||
public static final VecInput VEC3 = VecInput.builder()
|
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)
|
.typeName(VEC3_TYPE)
|
||||||
.packedTypeName(VEC3F_TYPE)
|
.packedTypeName(VEC3F_TYPE)
|
||||||
.unpackingFunction(expr -> expr.callFunction("unpackVec3F"))
|
.unpackingFunction(expr -> expr.callFunction("unpackVec3F"))
|
||||||
.build();
|
.build();
|
||||||
public static final VecInput VEC2 = VecInput.builder()
|
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)
|
.typeName(VEC2_TYPE)
|
||||||
.packedTypeName(VEC2F_TYPE)
|
.packedTypeName(VEC2F_TYPE)
|
||||||
.unpackingFunction(expr -> expr.callFunction("unpackVec2F"))
|
.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.api.layout.InputType;
|
||||||
import com.jozufozu.flywheel.gl.GlNumericType;
|
import com.jozufozu.flywheel.gl.GlNumericType;
|
||||||
import com.jozufozu.flywheel.gl.array.VertexAttribute;
|
import com.jozufozu.flywheel.gl.array.VertexAttribute;
|
||||||
import com.jozufozu.flywheel.gl.array.VertexAttributeF;
|
|
||||||
import com.jozufozu.flywheel.glsl.generate.GlslExpr;
|
import com.jozufozu.flywheel.glsl.generate.GlslExpr;
|
||||||
|
|
||||||
public record MatInput(int rows, int cols, String typeName, String packedTypeName,
|
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
|
@Override
|
||||||
public void provideAttributes(Consumer<VertexAttribute> consumer) {
|
public void provideAttributes(Consumer<VertexAttribute> consumer) {
|
||||||
for (int i = 0; i < rows; i++) {
|
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) {
|
public static GlStateShard fromVanilla(RenderStateShard vanillaShard) {
|
||||||
return new GlStateShard(() -> vanillaShard.setupRenderState(), () -> vanillaShard.clearRenderState());
|
return new GlStateShard(vanillaShard::setupRenderState, vanillaShard::clearRenderState);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Runnable getSetup() {
|
public Runnable getSetup() {
|
||||||
|
|
|
@ -47,16 +47,20 @@ public class FullscreenQuad {
|
||||||
Flywheel.LOGGER.error("Could not create fullscreen quad.", e);
|
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() {
|
public void draw() {
|
||||||
vao.bindForDraw();
|
vao.bindForDraw();
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||||
GlVertexArray.unbind();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
|
|
|
@ -2,15 +2,14 @@ package com.jozufozu.flywheel.lib.util;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.lwjgl.opengl.GL32;
|
|
||||||
import org.lwjgl.opengl.GL32C;
|
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.event.ReloadRenderersEvent;
|
import com.jozufozu.flywheel.api.event.ReloadRenderersEvent;
|
||||||
import com.jozufozu.flywheel.gl.GlNumericType;
|
import com.jozufozu.flywheel.gl.GlNumericType;
|
||||||
import com.jozufozu.flywheel.gl.buffer.ElementBuffer;
|
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.jozufozu.flywheel.gl.buffer.GlBufferUsage;
|
||||||
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ReferenceArrayMap;
|
import it.unimi.dsi.fastutil.ints.Int2ReferenceArrayMap;
|
||||||
|
@ -41,7 +40,7 @@ public class QuadConverter {
|
||||||
private int quadCapacity;
|
private int quadCapacity;
|
||||||
|
|
||||||
public QuadConverter() {
|
public QuadConverter() {
|
||||||
this.ebo = GL32.glGenBuffers();
|
this.ebo = GlBuffer.IMPL.create();
|
||||||
this.quadCapacity = 0;
|
this.quadCapacity = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,11 +63,7 @@ public class QuadConverter {
|
||||||
|
|
||||||
fillBuffer(ptr, quads);
|
fillBuffer(ptr, quads);
|
||||||
|
|
||||||
final var bufferType = GlBufferType.ARRAY_BUFFER;
|
GlBuffer.IMPL.data(ebo, byteSize, ptr, GlBufferUsage.STATIC_DRAW.glEnum);
|
||||||
final int oldBuffer = bufferType.getBoundBuffer();
|
|
||||||
bufferType.bind(ebo);
|
|
||||||
GL32C.nglBufferData(bufferType.glEnum, byteSize, ptr, GlBufferUsage.STATIC_DRAW.glEnum);
|
|
||||||
bufferType.bind(oldBuffer);
|
|
||||||
|
|
||||||
MemoryUtil.nmemFree(ptr);
|
MemoryUtil.nmemFree(ptr);
|
||||||
|
|
||||||
|
@ -76,7 +71,7 @@ public class QuadConverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
GL32.glDeleteBuffers(ebo);
|
GlStateManager._glDeleteBuffers(ebo);
|
||||||
this.cache.clear();
|
this.cache.clear();
|
||||||
this.quadCapacity = 0;
|
this.quadCapacity = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.jozufozu.flywheel.util;
|
package com.jozufozu.flywheel.util;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
@ -49,8 +50,20 @@ public final class FlwUtil {
|
||||||
|
|
||||||
public static PoseStack copyPoseStack(PoseStack stack) {
|
public static PoseStack copyPoseStack(PoseStack stack) {
|
||||||
PoseStack copy = new PoseStack();
|
PoseStack copy = new PoseStack();
|
||||||
copy.last().pose().load(stack.last().pose());
|
copy.last()
|
||||||
copy.last().normal().load(stack.last().normal());
|
.pose()
|
||||||
|
.load(stack.last()
|
||||||
|
.pose());
|
||||||
|
copy.last()
|
||||||
|
.normal()
|
||||||
|
.load(stack.last()
|
||||||
|
.normal());
|
||||||
return copy;
|
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