From c21a8bcbde4fe28cc2b438de1075215fd5cc1720 Mon Sep 17 00:00:00 2001 From: JozsefA Date: Wed, 31 Mar 2021 20:53:02 -0700 Subject: [PATCH] Fix startup crash on some AMD drivers. - The fix comes from Grondag's work on canvas. - Original commit: https://github.com/grondag/canvas/commit/820bf754092ccaf8d0c169620c2ff575722d7d96 --- .../foundation/render/backend/Backend.java | 8 ++--- .../render/backend/ShaderLoader.java | 5 ++- .../render/backend/gl/shader/GlShader.java | 3 +- .../{GlFeatureCompat.java => GlCompat.java} | 36 +++++++++++++++++-- 4 files changed, 41 insertions(+), 11 deletions(-) rename src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/{GlFeatureCompat.java => GlCompat.java} (66%) 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); + } + } }