diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java b/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java
index 20292f6d7..b8393ae4a 100644
--- a/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java
+++ b/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java
@@ -1,19 +1,17 @@
package com.simibubi.create.foundation.render.backend;
-import java.nio.FloatBuffer;
import java.util.HashMap;
import java.util.Map;
import com.simibubi.create.foundation.render.backend.gl.GlFog;
import com.simibubi.create.foundation.render.backend.gl.shader.*;
-import com.simibubi.create.foundation.render.backend.gl.versioned.GlFeatureCompat;
+import com.simibubi.create.foundation.render.backend.gl.versioned.GlCompat;
import com.simibubi.create.foundation.render.backend.instancing.IFlywheelWorld;
import net.minecraft.world.World;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GLCapabilities;
-import org.lwjgl.system.MemoryUtil;
import com.simibubi.create.foundation.config.AllConfigs;
@@ -28,7 +26,7 @@ public class Backend {
public static final Logger log = LogManager.getLogger(Backend.class);
public static GLCapabilities capabilities;
- public static GlFeatureCompat compat;
+ public static GlCompat compat;
private static boolean instancingAvailable;
private static boolean enabled;
@@ -97,7 +95,7 @@ public class Backend {
public static void refresh() {
capabilities = GL.createCapabilities();
- compat = new GlFeatureCompat(capabilities);
+ compat = new GlCompat(capabilities);
instancingAvailable = compat.vertexArrayObjectsSupported() &&
compat.drawInstancedSupported() &&
diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/ShaderLoader.java b/src/main/java/com/simibubi/create/foundation/render/backend/ShaderLoader.java
index c512fd8a7..4c6592720 100644
--- a/src/main/java/com/simibubi/create/foundation/render/backend/ShaderLoader.java
+++ b/src/main/java/com/simibubi/create/foundation/render/backend/ShaderLoader.java
@@ -1,17 +1,16 @@
package com.simibubi.create.foundation.render.backend;
import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.render.backend.gl.GlFogMode;
import com.simibubi.create.foundation.render.backend.gl.shader.*;
-import com.simibubi.create.foundation.render.backend.gl.versioned.GlFeatureCompat;
+
import net.minecraft.resources.IResource;
import net.minecraft.resources.IResourceManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.resource.IResourceType;
import net.minecraftforge.resource.VanillaResourceType;
-import org.lwjgl.opengl.GL;
+
import org.lwjgl.system.MemoryUtil;
import java.io.*;
diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GlShader.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GlShader.java
index 922b81b47..dc54e425b 100644
--- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GlShader.java
+++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GlShader.java
@@ -4,6 +4,7 @@ import org.lwjgl.opengl.GL20;
import com.simibubi.create.foundation.render.backend.Backend;
import com.simibubi.create.foundation.render.backend.gl.GlObject;
+import com.simibubi.create.foundation.render.backend.gl.versioned.GlCompat;
import net.minecraft.util.ResourceLocation;
@@ -17,7 +18,7 @@ public class GlShader extends GlObject {
this.name = name;
int handle = GL20.glCreateShader(type.glEnum);
- GL20.glShaderSource(handle, source);
+ GlCompat.safeShaderSource(handle, source);
GL20.glCompileShader(handle);
String log = GL20.glGetShaderInfoLog(handle);
diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/GlFeatureCompat.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/GlCompat.java
similarity index 66%
rename from src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/GlFeatureCompat.java
rename to src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/GlCompat.java
index b2eba08e1..9cb150a51 100644
--- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/GlFeatureCompat.java
+++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/GlCompat.java
@@ -1,6 +1,10 @@
package com.simibubi.create.foundation.render.backend.gl.versioned;
+import org.lwjgl.PointerBuffer;
+import org.lwjgl.opengl.GL20C;
import org.lwjgl.opengl.GLCapabilities;
+import org.lwjgl.system.MemoryStack;
+import org.lwjgl.system.MemoryUtil;
import java.nio.ByteBuffer;
import java.util.Arrays;
@@ -13,7 +17,7 @@ import java.util.function.Consumer;
* Each field stores an enum variant that provides access to the
* most appropriate version of a feature for the current system.
*/
-public class GlFeatureCompat {
+public class GlCompat {
public final MapBuffer mapBuffer;
public final VertexArrayObject vertexArrayObject;
@@ -22,7 +26,7 @@ public class GlFeatureCompat {
public final RGPixelFormat pixelFormat;
- public GlFeatureCompat(GLCapabilities caps) {
+ public GlCompat(GLCapabilities caps) {
mapBuffer = getLatest(MapBuffer.class, caps);
vertexArrayObject = getLatest(VertexArrayObject.class, caps);
@@ -85,5 +89,33 @@ public class GlFeatureCompat {
return Arrays.stream(constants).filter(it -> it.supported(caps)).findFirst().get();
}
+
+ /**
+ * Copied from:
+ *
https://github.com/grondag/canvas/commit/820bf754092ccaf8d0c169620c2ff575722d7d96
+ *
+ *
Identical in function to {@link GL20C#glShaderSource(int, CharSequence)} but + * passes a null pointer for string length to force the driver to rely on the null + * terminator for string length. This is a workaround for an apparent flaw with some + * AMD drivers that don't receive or interpret the length correctly, resulting in + * an access violation when the driver tries to read past the string memory. + * + *
Hat tip to fewizz for the find and the fix. + */ + public static void safeShaderSource(int glId, CharSequence source) { + final MemoryStack stack = MemoryStack.stackGet(); + final int stackPointer = stack.getPointer(); + + try { + final ByteBuffer sourceBuffer = MemoryUtil.memUTF8(source, true); + final PointerBuffer pointers = stack.mallocPointer(1); + pointers.put(sourceBuffer); + + GL20C.nglShaderSource(glId, 1, pointers.address0(), 0); + org.lwjgl.system.APIUtil.apiArrayFree(pointers.address0(), 1); + } finally { + stack.setPointer(stackPointer); + } + } }