gpu: add support for osx

Compute shaders must be forced off due to macos not supporting opengl
4.3
This commit is contained in:
Adam
2020-04-29 18:24:57 -04:00
parent f95c5af4e4
commit 0e6f9f9aec
2 changed files with 180 additions and 94 deletions

View File

@@ -117,6 +117,13 @@
<classifier>natives-linux-amd64</classifier>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>net.runelite.jogl</groupId>
<artifactId>jogl-all</artifactId>
<version>${jogl.version}</version>
<classifier>natives-macosx-universal</classifier>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>net.runelite.gluegen</groupId>
<artifactId>gluegen-rt</artifactId>
@@ -143,6 +150,13 @@
<classifier>natives-linux-amd64</classifier>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>net.runelite.gluegen</groupId>
<artifactId>gluegen-rt</artifactId>
<version>${jogl.version}</version>
<classifier>natives-macosx-universal</classifier>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>net.runelite</groupId>
<artifactId>archive-patcher</artifactId>

View File

@@ -35,6 +35,7 @@ import com.jogamp.opengl.GLContext;
import com.jogamp.opengl.GLDrawable;
import com.jogamp.opengl.GLDrawableFactory;
import com.jogamp.opengl.GLException;
import com.jogamp.opengl.GLFBODrawable;
import com.jogamp.opengl.GLProfile;
import java.awt.Canvas;
import java.awt.Dimension;
@@ -51,6 +52,7 @@ import javax.inject.Inject;
import javax.swing.SwingUtilities;
import jogamp.nativewindow.SurfaceScaleUtils;
import jogamp.nativewindow.jawt.x11.X11JAWTWindow;
import jogamp.nativewindow.macosx.OSXUtil;
import jogamp.newt.awt.NewtFactoryAWT;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.BufferProvider;
@@ -286,7 +288,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
return false;
}
useComputeShaders = config.useComputeShaders();
// OSX supports up to OpenGL 4.1, however 4.3 is required for compute shaders
useComputeShaders = config.useComputeShaders() && OSType.getOSType() != OSType.MacOS;
canvas.setIgnoreRepaint(true);
@@ -304,55 +307,73 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
GLProfile.initSingleton();
GLProfile glProfile = GLProfile.get(GLProfile.GL4);
GLCapabilities glCaps = new GLCapabilities(glProfile);
AWTGraphicsConfiguration config = AWTGraphicsConfiguration.create(canvas.getGraphicsConfiguration(), glCaps, glCaps);
jawtWindow = NewtFactoryAWT.getNativeWindow(canvas, config);
canvas.setFocusable(true);
GLDrawableFactory glDrawableFactory = GLDrawableFactory.getFactory(glProfile);
glDrawable = glDrawableFactory.createGLDrawable(jawtWindow);
glDrawable.setRealized(true);
glContext = glDrawable.createContext(null);
if (log.isDebugEnabled())
invokeOnMainThread(() ->
{
// Debug config on context needs to be set before .makeCurrent call
glContext.enableGLDebugMessage(true);
}
GLProfile glProfile = GLProfile.get(GLProfile.GL4);
int res = glContext.makeCurrent();
if (res == GLContext.CONTEXT_NOT_CURRENT)
{
throw new GLException("Unable to make context current");
}
GLCapabilities glCaps = new GLCapabilities(glProfile);
AWTGraphicsConfiguration config = AWTGraphicsConfiguration.create(canvas.getGraphicsConfiguration(), glCaps, glCaps);
// Surface needs to be unlocked on X11 window otherwise input is blocked
if (jawtWindow instanceof X11JAWTWindow && jawtWindow.getLock().isLocked())
{
jawtWindow.unlockSurface();
}
jawtWindow = NewtFactoryAWT.getNativeWindow(canvas, config);
canvas.setFocusable(true);
this.gl = glContext.getGL().getGL4();
gl.setSwapInterval(0);
GLDrawableFactory glDrawableFactory = GLDrawableFactory.getFactory(glProfile);
if (log.isDebugEnabled())
{
gl.glEnable(gl.GL_DEBUG_OUTPUT);
jawtWindow.lockSurface();
try
{
glDrawable = glDrawableFactory.createGLDrawable(jawtWindow);
glDrawable.setRealized(true);
// Suppress warning messages which flood the log on NVIDIA systems.
gl.getContext().glDebugMessageControl(gl.GL_DEBUG_SOURCE_API, gl.GL_DEBUG_TYPE_OTHER,
gl.GL_DEBUG_SEVERITY_NOTIFICATION, 0, null, 0, false);
}
glContext = glDrawable.createContext(null);
if (log.isDebugEnabled())
{
// Debug config on context needs to be set before .makeCurrent call
glContext.enableGLDebugMessage(true);
}
}
finally
{
jawtWindow.unlockSurface();
}
initVao();
initProgram();
initInterfaceTexture();
initUniformBuffer();
initBuffers();
int res = glContext.makeCurrent();
if (res == GLContext.CONTEXT_NOT_CURRENT)
{
throw new GLException("Unable to make context current");
}
// Surface needs to be unlocked on X11 window otherwise input is blocked
if (jawtWindow instanceof X11JAWTWindow && jawtWindow.getLock().isLocked())
{
jawtWindow.unlockSurface();
}
this.gl = glContext.getGL().getGL4();
gl.setSwapInterval(0);
if (log.isDebugEnabled())
{
gl.glEnable(gl.GL_DEBUG_OUTPUT);
// Suppress warning messages which flood the log on NVIDIA systems.
gl.getContext().glDebugMessageControl(gl.GL_DEBUG_SOURCE_API, gl.GL_DEBUG_TYPE_OTHER,
gl.GL_DEBUG_SEVERITY_NOTIFICATION, 0, null, 0, false);
}
initVao();
try
{
initProgram();
}
catch (ShaderException ex)
{
throw new RuntimeException(ex);
}
initInterfaceTexture();
initUniformBuffer();
initBuffers();
});
client.setDrawCallbacks(this);
client.setGpu(true);
@@ -408,41 +429,51 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
client.setGpu(false);
client.setDrawCallbacks(null);
if (gl != null)
invokeOnMainThread(() ->
{
if (textureArrayId != -1)
if (gl != null)
{
textureManager.freeTextureArray(gl, textureArrayId);
textureArrayId = -1;
if (textureArrayId != -1)
{
textureManager.freeTextureArray(gl, textureArrayId);
textureArrayId = -1;
}
if (uniformBufferId != -1)
{
GLUtil.glDeleteBuffer(gl, uniformBufferId);
uniformBufferId = -1;
}
shutdownBuffers();
shutdownInterfaceTexture();
shutdownProgram();
shutdownVao();
shutdownAAFbo();
}
if (uniformBufferId != -1)
if (jawtWindow != null)
{
GLUtil.glDeleteBuffer(gl, uniformBufferId);
uniformBufferId = -1;
if (!jawtWindow.getLock().isLocked())
{
jawtWindow.lockSurface();
}
if (glContext != null)
{
glContext.destroy();
}
// this crashes on osx when the plugin is turned back on, don't know why
// we'll just leak the window...
if (OSType.getOSType() != OSType.MacOS)
{
NewtFactoryAWT.destroyNativeWindow(jawtWindow);
}
}
});
shutdownBuffers();
shutdownInterfaceTexture();
shutdownProgram();
shutdownVao();
shutdownAAFbo();
}
if (jawtWindow != null)
{
if (!jawtWindow.getLock().isLocked())
{
jawtWindow.lockSurface();
}
if (glContext != null)
{
glContext.destroy();
}
NewtFactoryAWT.destroyNativeWindow(jawtWindow);
}
GLProfile.shutdown();
jawtWindow = null;
gl = null;
@@ -839,6 +870,42 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
@Override
public void draw()
{
invokeOnMainThread(this::drawFrame);
}
private void resize(int canvasWidth, int canvasHeight, int viewportWidth, int viewportHeight)
{
// If the viewport has changed, update the projection matrix
if (viewportWidth > 0 && viewportHeight > 0 && (viewportWidth != lastViewportWidth || viewportHeight != lastViewportHeight))
{
lastViewportWidth = viewportWidth;
lastViewportHeight = viewportHeight;
createProjectionMatrix(0, viewportWidth, viewportHeight, 0, 0, Constants.SCENE_SIZE * Perspective.LOCAL_TILE_SIZE);
}
if (canvasWidth != lastCanvasWidth || canvasHeight != lastCanvasHeight)
{
lastCanvasWidth = canvasWidth;
lastCanvasHeight = canvasHeight;
gl.glBindTexture(gl.GL_TEXTURE_2D, interfaceTexture);
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, canvasWidth, canvasHeight, 0, gl.GL_BGRA, gl.GL_UNSIGNED_INT_8_8_8_8_REV, null);
gl.glBindTexture(gl.GL_TEXTURE_2D, 0);
if (OSType.getOSType() == OSType.MacOS && glDrawable instanceof GLFBODrawable)
{
// GLDrawables created with createGLDrawable() do not have a resize listener
// I don't know why this works with Windows/Linux, but on OSX
// it prevents JOGL from resizing its FBOs and underlying GL textures. So,
// we manually trigger a resize here.
GLFBODrawable glfboDrawable = (GLFBODrawable) glDrawable;
glfboDrawable.resetSize(gl);
}
}
}
private void drawFrame()
{
if (jawtWindow.getAWTComponent() != client.getCanvas())
{
@@ -862,13 +929,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
final int viewportHeight = client.getViewportHeight();
final int viewportWidth = client.getViewportWidth();
// If the viewport has changed, update the projection matrix
if (viewportWidth > 0 && viewportHeight > 0 && (viewportWidth != lastViewportWidth || viewportHeight != lastViewportHeight))
{
createProjectionMatrix(0, viewportWidth, viewportHeight, 0, 0, Constants.SCENE_SIZE * Perspective.LOCAL_TILE_SIZE);
lastViewportWidth = viewportWidth;
lastViewportHeight = viewportHeight;
}
resize(canvasWidth, canvasHeight, viewportWidth, viewportHeight);
// Setup anti-aliasing
final AntiAliasingMode antiAliasingMode = config.antiAliasingMode();
@@ -1176,16 +1237,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
gl.glBlendFunc(gl.GL_ONE, gl.GL_ONE_MINUS_SRC_ALPHA);
gl.glBindTexture(gl.GL_TEXTURE_2D, interfaceTexture);
if (canvasWidth != lastCanvasWidth || canvasHeight != lastCanvasHeight)
{
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, width, height, 0, gl.GL_BGRA, gl.GL_UNSIGNED_INT_8_8_8_8_REV, interfaceBuffer);
lastCanvasWidth = canvasWidth;
lastCanvasHeight = canvasHeight;
}
else
{
gl.glTexSubImage2D(gl.GL_TEXTURE_2D, 0, 0, 0, width, height, gl.GL_BGRA, gl.GL_UNSIGNED_INT_8_8_8_8_REV, interfaceBuffer);
}
gl.glTexSubImage2D(gl.GL_TEXTURE_2D, 0, 0, 0, width, height, gl.GL_BGRA, gl.GL_UNSIGNED_INT_8_8_8_8_REV, interfaceBuffer);
// Use the texture bound in the first pass
final UIScalingMode uiScalingMode = config.uiScalingMode();
@@ -1526,12 +1578,20 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
private void glDpiAwareViewport(final int x, final int y, final int width, final int height)
{
final AffineTransform t = ((Graphics2D) canvas.getGraphics()).getTransform();
gl.glViewport(
getScaledValue(t.getScaleX(), x),
getScaledValue(t.getScaleY(), y),
getScaledValue(t.getScaleX(), width),
getScaledValue(t.getScaleY(), height));
if (OSType.getOSType() == OSType.MacOS)
{
// JOGL seems to handle DPI scaling for us already
gl.glViewport(x, y, width, height);
}
else
{
final AffineTransform t = ((Graphics2D) canvas.getGraphics()).getTransform();
gl.glViewport(
getScaledValue(t.getScaleX(), x),
getScaledValue(t.getScaleY(), y),
getScaledValue(t.getScaleX(), width),
getScaledValue(t.getScaleY(), height));
}
}
private int getDrawDistance()
@@ -1539,4 +1599,16 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
final int limit = useComputeShaders ? MAX_DISTANCE : DEFAULT_DISTANCE;
return Ints.constrainToRange(config.drawDistance(), 0, limit);
}
private static void invokeOnMainThread(Runnable runnable)
{
if (OSType.getOSType() == OSType.MacOS)
{
OSXUtil.RunOnMainThread(true, false, runnable);
}
else
{
runnable.run();
}
}
}