Fix startup crash on some AMD drivers.

- The fix comes from Grondag's work on canvas.
 - Original commit: 820bf75409
This commit is contained in:
JozsefA 2021-03-31 20:53:02 -07:00
parent 6ef88c3bd8
commit c21a8bcbde
4 changed files with 41 additions and 11 deletions

View file

@ -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() &&

View file

@ -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.*;

View file

@ -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);

View file

@ -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:
* <br> https://github.com/grondag/canvas/commit/820bf754092ccaf8d0c169620c2ff575722d7d96
*
* <p>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.
*
* <p>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);
}
}
}