mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-15 19:33:41 +01:00
improve compatibility layer.
This commit is contained in:
parent
e84c6d3abe
commit
b5f9cbc4b3
9 changed files with 289 additions and 51 deletions
|
@ -11,6 +11,7 @@ import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Predicate;
|
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.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.lwjgl.opengl.GL;
|
import org.lwjgl.opengl.GL;
|
||||||
|
@ -44,16 +45,12 @@ public class Backend {
|
||||||
private static boolean enabled;
|
private static boolean enabled;
|
||||||
|
|
||||||
public static GLCapabilities capabilities;
|
public static GLCapabilities capabilities;
|
||||||
private static MapBuffer mapBuffer;
|
public static GlFunctions functions;
|
||||||
|
|
||||||
public Backend() {
|
public Backend() {
|
||||||
throw new IllegalStateException();
|
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?
|
* Register a shader program. TODO: replace with forge registry?
|
||||||
*/
|
*/
|
||||||
|
@ -71,47 +68,21 @@ public class Backend {
|
||||||
return (P) programs.get(spec);
|
return (P) programs.get(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static boolean available() {
|
||||||
* Get the most compatible version of a specific OpenGL feature by iterating over enum constants in order.
|
return canUseVBOs();
|
||||||
*
|
|
||||||
* @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 canUseInstancing() {
|
public static boolean canUseInstancing() {
|
||||||
return enabled && gl33();
|
return enabled &&
|
||||||
|
functions.vertexArrayObjectsSupported() &&
|
||||||
|
functions.drawInstancedSupported() &&
|
||||||
|
functions.instancedArraysSupported();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean canUseVBOs() {
|
public static boolean canUseVBOs() {
|
||||||
return enabled && gl20();
|
return enabled && gl20();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean available() {
|
|
||||||
return enabled && gl20();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean gl33() {
|
public static boolean gl33() {
|
||||||
return capabilities.OpenGL33;
|
return capabilities.OpenGL33;
|
||||||
}
|
}
|
||||||
|
@ -136,7 +107,7 @@ public class Backend {
|
||||||
private static void onResourceManagerReload(IResourceManager manager, Predicate<IResourceType> predicate) {
|
private static void onResourceManagerReload(IResourceManager manager, Predicate<IResourceType> predicate) {
|
||||||
if (predicate.test(VanillaResourceType.SHADERS)) {
|
if (predicate.test(VanillaResourceType.SHADERS)) {
|
||||||
capabilities = GL.createCapabilities();
|
capabilities = GL.createCapabilities();
|
||||||
mapBuffer = getLatest(MapBuffer.class);
|
functions = new GlFunctions(capabilities);
|
||||||
|
|
||||||
OptifineHandler.refresh();
|
OptifineHandler.refresh();
|
||||||
refresh();
|
refresh();
|
||||||
|
|
|
@ -3,9 +3,9 @@ package com.simibubi.create.foundation.render.backend.gl;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.function.Consumer;
|
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.Backend;
|
||||||
|
import com.simibubi.create.foundation.render.backend.gl.versioned.GlFunctions;
|
||||||
|
import org.lwjgl.opengl.GL20;
|
||||||
|
|
||||||
public class GlBuffer extends GlObject {
|
public class GlBuffer extends GlObject {
|
||||||
|
|
||||||
|
@ -35,11 +35,11 @@ public class GlBuffer extends GlObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void map(int length, Consumer<ByteBuffer> upload) {
|
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) {
|
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) {
|
protected void deleteInternal(int handle) {
|
||||||
|
|
|
@ -2,19 +2,20 @@ package com.simibubi.create.foundation.render.backend.gl;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.render.backend.Backend;
|
||||||
import org.lwjgl.opengl.GL30;
|
import org.lwjgl.opengl.GL30;
|
||||||
|
|
||||||
public class GlVertexArray extends GlObject {
|
public class GlVertexArray extends GlObject {
|
||||||
public GlVertexArray() {
|
public GlVertexArray() {
|
||||||
setHandle(GL30.glGenVertexArrays());
|
setHandle(Backend.functions.genVertexArrays());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bind() {
|
public void bind() {
|
||||||
GL30.glBindVertexArray(handle());
|
Backend.functions.bindVertexArray(handle());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unbind() {
|
public void unbind() {
|
||||||
GL30.glBindVertexArray(0);
|
Backend.functions.bindVertexArray(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void with(Consumer<GlVertexArray> action) {
|
public void with(Consumer<GlVertexArray> action) {
|
||||||
|
@ -24,6 +25,6 @@ public class GlVertexArray extends GlObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void deleteInternal(int handle) {
|
protected void deleteInternal(int handle) {
|
||||||
GL30.glDeleteVertexArrays(handle);
|
Backend.functions.deleteVertexArrays(handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,15 @@ package com.simibubi.create.foundation.render.backend.gl.versioned;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GLCapabilities;
|
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 {
|
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);
|
boolean supported(GLCapabilities caps);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
package com.simibubi.create.foundation.render.backend.gl.versioned;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.*;
|
||||||
|
|
||||||
|
public enum VertexArrayObject implements GlVersioned {
|
||||||
|
GL30_VAO {
|
||||||
|
@Override
|
||||||
|
public boolean supported(GLCapabilities caps) {
|
||||||
|
return caps.OpenGL30;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int genVertexArrays() {
|
||||||
|
return GL30.glGenVertexArrays();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bindVertexArray(int array) {
|
||||||
|
GL30.glBindVertexArray(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteVertexArrays(int array) {
|
||||||
|
GL30.glDeleteVertexArrays(array);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ARB_VAO {
|
||||||
|
@Override
|
||||||
|
public boolean supported(GLCapabilities caps) {
|
||||||
|
return caps.GL_ARB_vertex_array_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int genVertexArrays() {
|
||||||
|
return ARBVertexArrayObject.glGenVertexArrays();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bindVertexArray(int array) {
|
||||||
|
ARBVertexArrayObject.glBindVertexArray(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteVertexArrays(int array) {
|
||||||
|
ARBVertexArrayObject.glDeleteVertexArrays(array);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
UNSUPPORTED {
|
||||||
|
@Override
|
||||||
|
public boolean supported(GLCapabilities caps) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int genVertexArrays() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bindVertexArray(int array) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteVertexArrays(int array) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
public abstract int genVertexArrays();
|
||||||
|
|
||||||
|
public abstract void bindVertexArray(int array);
|
||||||
|
|
||||||
|
public abstract void deleteVertexArrays(int array);
|
||||||
|
}
|
|
@ -5,11 +5,10 @@ import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.render.backend.Backend;
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
import org.lwjgl.opengl.GL15;
|
import org.lwjgl.opengl.GL15;
|
||||||
import org.lwjgl.opengl.GL20;
|
import org.lwjgl.opengl.GL20;
|
||||||
import org.lwjgl.opengl.GL31;
|
|
||||||
import org.lwjgl.opengl.GL33;
|
|
||||||
|
|
||||||
import com.simibubi.create.foundation.render.RenderMath;
|
import com.simibubi.create.foundation.render.RenderMath;
|
||||||
import com.simibubi.create.foundation.render.backend.BufferedModel;
|
import com.simibubi.create.foundation.render.backend.BufferedModel;
|
||||||
|
@ -116,7 +115,7 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
|
||||||
protected void doRender() {
|
protected void doRender() {
|
||||||
vao.with(vao -> {
|
vao.with(vao -> {
|
||||||
renderSetup();
|
renderSetup();
|
||||||
GL31.glDrawArraysInstanced(GL11.GL_QUADS, 0, vertexCount, glInstanceCount);
|
Backend.functions.drawArraysInstanced(GL11.GL_QUADS, 0, vertexCount, glInstanceCount);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +162,7 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
|
||||||
instanceFormat.vertexAttribPointers(staticAttributes);
|
instanceFormat.vertexAttribPointers(staticAttributes);
|
||||||
|
|
||||||
for (int i = 0; i < instanceFormat.getShaderAttributeCount(); i++) {
|
for (int i = 0; i < instanceFormat.getShaderAttributeCount(); i++) {
|
||||||
GL33.glVertexAttribDivisor(i + staticAttributes, 1);
|
Backend.functions.vertexAttribDivisor(i + staticAttributes, 1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue