Skip to content

Commit

Permalink
improve compatibility layer.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jozufozu committed Feb 20, 2021
1 parent e84c6d3 commit b5f9cbc
Show file tree
Hide file tree
Showing 9 changed files with 289 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import java.util.function.Consumer;
import java.util.function.Predicate;

import com.simibubi.create.foundation.render.backend.gl.versioned.GlFunctions;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.lwjgl.opengl.GL;
Expand Down Expand Up @@ -44,16 +45,12 @@ public class Backend {
private static boolean enabled;

public static GLCapabilities capabilities;
private static MapBuffer mapBuffer;
public static GlFunctions functions;

public Backend() {
throw new IllegalStateException();
}

public static void mapBuffer(int target, int offset, int length, Consumer<ByteBuffer> upload) {
mapBuffer.mapBuffer(target, offset, length, upload);
}

/**
* Register a shader program. TODO: replace with forge registry?
*/
Expand All @@ -71,47 +68,21 @@ public static <P extends GlProgram, S extends ProgramSpec<P>> P getProgram(S spe
return (P) programs.get(spec);
}

/**
* Get the most compatible version of a specific OpenGL feature by iterating over enum constants in order.
*
* @param clazz The class of the versioning enum.
* @param <V> The type of the versioning enum.
* @return The first defined enum variant to return true.
*/
public static <V extends Enum<V> & GlVersioned> V getLatest(Class<V> clazz) {
return getLatest(clazz, capabilities);
}

/**
* Get the most compatible version of a specific OpenGL feature by iterating over enum constants in order.
*
* @param clazz The class of the versioning enum.
* @param caps The current system's supported features.
* @param <V> The type of the versioning enum.
* @return The first defined enum variant to return true.
*/
public static <V extends Enum<V> & GlVersioned> V getLatest(Class<V> clazz, GLCapabilities caps) {
V[] constants = clazz.getEnumConstants();
V last = constants[constants.length - 1];
if (!last.supported(caps)) {
throw new IllegalStateException("");
}

return Arrays.stream(constants).filter(it -> it.supported(caps)).findFirst().orElse(last);
public static boolean available() {
return canUseVBOs();
}

public static boolean canUseInstancing() {
return enabled && gl33();
return enabled &&
functions.vertexArrayObjectsSupported() &&
functions.drawInstancedSupported() &&
functions.instancedArraysSupported();
}

public static boolean canUseVBOs() {
return enabled && gl20();
}

public static boolean available() {
return enabled && gl20();
}

public static boolean gl33() {
return capabilities.OpenGL33;
}
Expand All @@ -136,7 +107,7 @@ public static void init() {
private static void onResourceManagerReload(IResourceManager manager, Predicate<IResourceType> predicate) {
if (predicate.test(VanillaResourceType.SHADERS)) {
capabilities = GL.createCapabilities();
mapBuffer = getLatest(MapBuffer.class);
functions = new GlFunctions(capabilities);

OptifineHandler.refresh();
refresh();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import java.nio.ByteBuffer;
import java.util.function.Consumer;

import org.lwjgl.opengl.GL20;

import com.simibubi.create.foundation.render.backend.Backend;
import com.simibubi.create.foundation.render.backend.gl.versioned.GlFunctions;
import org.lwjgl.opengl.GL20;

public class GlBuffer extends GlObject {

Expand Down Expand Up @@ -35,11 +35,11 @@ public void with(Consumer<GlBuffer> action) {
}

public void map(int length, Consumer<ByteBuffer> upload) {
Backend.mapBuffer(bufferType, 0, length, upload);
Backend.functions.mapBuffer(bufferType, 0, length, upload);
}

public void map(int offset, int length, Consumer<ByteBuffer> upload) {
Backend.mapBuffer(bufferType, offset, length, upload);
Backend.functions.mapBuffer(bufferType, offset, length, upload);
}

protected void deleteInternal(int handle) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@

import java.util.function.Consumer;

import com.simibubi.create.foundation.render.backend.Backend;
import org.lwjgl.opengl.GL30;

public class GlVertexArray extends GlObject {
public GlVertexArray() {
setHandle(GL30.glGenVertexArrays());
setHandle(Backend.functions.genVertexArrays());
}

public void bind() {
GL30.glBindVertexArray(handle());
Backend.functions.bindVertexArray(handle());
}

public void unbind() {
GL30.glBindVertexArray(0);
Backend.functions.bindVertexArray(0);
}

public void with(Consumer<GlVertexArray> action) {
Expand All @@ -24,6 +25,6 @@ public void with(Consumer<GlVertexArray> action) {
}

protected void deleteInternal(int handle) {
GL30.glDeleteVertexArrays(handle);
Backend.functions.deleteVertexArrays(handle);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.simibubi.create.foundation.render.backend.gl.versioned;

import org.lwjgl.opengl.*;

public enum DrawInstanced implements GlVersioned {
GL31_DRAW_INSTANCED {
@Override
public boolean supported(GLCapabilities caps) {
return caps.OpenGL31;
}

@Override
public void drawArraysInstanced(int mode, int first, int count, int primcount) {
GL31.glDrawArraysInstanced(mode, first, count, primcount);
}
},
ARB_DRAW_INSTANCED {
@Override
public boolean supported(GLCapabilities caps) {
return caps.GL_ARB_draw_instanced;
}

@Override
public void drawArraysInstanced(int mode, int first, int count, int primcount) {
ARBDrawInstanced.glDrawArraysInstancedARB(mode, first, count, primcount);
}
},
EXT_DRAW_INSTANCED {
@Override
public boolean supported(GLCapabilities caps) {
return caps.GL_EXT_draw_instanced;
}

@Override
public void drawArraysInstanced(int mode, int first, int count, int primcount) {
EXTDrawInstanced.glDrawArraysInstancedEXT(mode, first, count, primcount);
}
},
UNSUPPORTED {
@Override
public boolean supported(GLCapabilities caps) {
return true;
}

@Override
public void drawArraysInstanced(int mode, int first, int count, int primcount) {
throw new UnsupportedOperationException();
}
}

;

public abstract void drawArraysInstanced(int mode, int first, int count, int primcount);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.simibubi.create.foundation.render.backend.gl.versioned;

import org.lwjgl.opengl.GLCapabilities;

import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.function.Consumer;

/**
* An instance of this class stores information
* about what OpenGL features are available.
*
* Each field stores an enum variant that provides access to the
* most appropriate version of a feature for the current system.
*/
public class GlFunctions {
public final MapBuffer mapBuffer;

public final VertexArrayObject vertexArrayObject;
public final InstancedArrays instancedArrays;
public final DrawInstanced drawInstanced;

public GlFunctions(GLCapabilities caps) {
mapBuffer = getLatest(MapBuffer.class, caps);

vertexArrayObject = getLatest(VertexArrayObject.class, caps);
instancedArrays = getLatest(InstancedArrays.class, caps);
drawInstanced = getLatest(DrawInstanced.class, caps);
}

public void mapBuffer(int target, int offset, int length, Consumer<ByteBuffer> upload) {
mapBuffer.mapBuffer(target, offset, length, upload);
}

public void vertexAttribDivisor(int index, int divisor) {
instancedArrays.vertexAttribDivisor(index, divisor);
}

public void drawArraysInstanced(int mode, int first, int count, int primcount) {
drawInstanced.drawArraysInstanced(mode, first, count, primcount);
}

public int genVertexArrays() {
return vertexArrayObject.genVertexArrays();
}

public void deleteVertexArrays(int array) {
vertexArrayObject.deleteVertexArrays(array);
}

public void bindVertexArray(int array) {
vertexArrayObject.bindVertexArray(array);
}

public boolean vertexArrayObjectsSupported() {
return vertexArrayObject != VertexArrayObject.UNSUPPORTED;
}

public boolean instancedArraysSupported() {
return instancedArrays != InstancedArrays.UNSUPPORTED;
}

public boolean drawInstancedSupported() {
return drawInstanced != DrawInstanced.UNSUPPORTED;
}

/**
* Get the most compatible version of a specific OpenGL feature by iterating over enum constants in order.
*
* @param clazz The class of the versioning enum.
* @param caps The current system's supported features.
* @param <V> The type of the versioning enum.
* @return The first defined enum variant to return true.
*/
public static <V extends Enum<V> & GlVersioned> V getLatest(Class<V> clazz, GLCapabilities caps) {
V[] constants = clazz.getEnumConstants();
V last = constants[constants.length - 1];
if (!last.supported(caps)) {
throw new IllegalStateException("");
}

return Arrays.stream(constants).filter(it -> it.supported(caps)).findFirst().get();
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@

import org.lwjgl.opengl.GLCapabilities;


/**
* This interface should be implemented by enums such that the
* last defined variant <em>always</em> returns <code>true</code>.
*/
public interface GlVersioned {
/**
* Queries whether this variant is supported by the current system.
* @param caps The {@link GLCapabilities} reported by the current system.
* @return <code>true</code> if this variant is supported, or if this is the last defined variant.
*/
boolean supported(GLCapabilities caps);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.simibubi.create.foundation.render.backend.gl.versioned;

import org.lwjgl.opengl.*;

public enum InstancedArrays implements GlVersioned {
GL33_INSTANCED_ARRAYS {
@Override
public boolean supported(GLCapabilities caps) {
return caps.OpenGL33;
}

@Override
public void vertexAttribDivisor(int index, int divisor) {
GL33.glVertexAttribDivisor(index, divisor);
}
},
ARB_INSTANCED_ARRAYS {
@Override
public boolean supported(GLCapabilities caps) {
return caps.GL_ARB_instanced_arrays;
}

@Override
public void vertexAttribDivisor(int index, int divisor) {
ARBInstancedArrays.glVertexAttribDivisorARB(index, divisor);
}
},
UNSUPPORTED {
@Override
public boolean supported(GLCapabilities caps) {
return true;
}

@Override
public void vertexAttribDivisor(int index, int divisor) {
throw new UnsupportedOperationException();
}
}

;

public abstract void vertexAttribDivisor(int index, int divisor);
}
Loading

0 comments on commit b5f9cbc

Please sign in to comment.