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> <classifier>natives-linux-amd64</classifier>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </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> <dependency>
<groupId>net.runelite.gluegen</groupId> <groupId>net.runelite.gluegen</groupId>
<artifactId>gluegen-rt</artifactId> <artifactId>gluegen-rt</artifactId>
@@ -143,6 +150,13 @@
<classifier>natives-linux-amd64</classifier> <classifier>natives-linux-amd64</classifier>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </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> <dependency>
<groupId>net.runelite</groupId> <groupId>net.runelite</groupId>
<artifactId>archive-patcher</artifactId> <artifactId>archive-patcher</artifactId>

View File

@@ -35,6 +35,7 @@ import com.jogamp.opengl.GLContext;
import com.jogamp.opengl.GLDrawable; import com.jogamp.opengl.GLDrawable;
import com.jogamp.opengl.GLDrawableFactory; import com.jogamp.opengl.GLDrawableFactory;
import com.jogamp.opengl.GLException; import com.jogamp.opengl.GLException;
import com.jogamp.opengl.GLFBODrawable;
import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.GLProfile;
import java.awt.Canvas; import java.awt.Canvas;
import java.awt.Dimension; import java.awt.Dimension;
@@ -51,6 +52,7 @@ import javax.inject.Inject;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import jogamp.nativewindow.SurfaceScaleUtils; import jogamp.nativewindow.SurfaceScaleUtils;
import jogamp.nativewindow.jawt.x11.X11JAWTWindow; import jogamp.nativewindow.jawt.x11.X11JAWTWindow;
import jogamp.nativewindow.macosx.OSXUtil;
import jogamp.newt.awt.NewtFactoryAWT; import jogamp.newt.awt.NewtFactoryAWT;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.api.BufferProvider; import net.runelite.api.BufferProvider;
@@ -286,7 +288,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
return false; 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); canvas.setIgnoreRepaint(true);
@@ -304,55 +307,73 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
GLProfile.initSingleton(); GLProfile.initSingleton();
GLProfile glProfile = GLProfile.get(GLProfile.GL4); invokeOnMainThread(() ->
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())
{ {
// Debug config on context needs to be set before .makeCurrent call GLProfile glProfile = GLProfile.get(GLProfile.GL4);
glContext.enableGLDebugMessage(true);
}
int res = glContext.makeCurrent(); GLCapabilities glCaps = new GLCapabilities(glProfile);
if (res == GLContext.CONTEXT_NOT_CURRENT) AWTGraphicsConfiguration config = AWTGraphicsConfiguration.create(canvas.getGraphicsConfiguration(), glCaps, glCaps);
{
throw new GLException("Unable to make context current");
}
// Surface needs to be unlocked on X11 window otherwise input is blocked jawtWindow = NewtFactoryAWT.getNativeWindow(canvas, config);
if (jawtWindow instanceof X11JAWTWindow && jawtWindow.getLock().isLocked()) canvas.setFocusable(true);
{
jawtWindow.unlockSurface();
}
this.gl = glContext.getGL().getGL4(); GLDrawableFactory glDrawableFactory = GLDrawableFactory.getFactory(glProfile);
gl.setSwapInterval(0);
if (log.isDebugEnabled()) jawtWindow.lockSurface();
{ try
gl.glEnable(gl.GL_DEBUG_OUTPUT); {
glDrawable = glDrawableFactory.createGLDrawable(jawtWindow);
glDrawable.setRealized(true);
// Suppress warning messages which flood the log on NVIDIA systems. glContext = glDrawable.createContext(null);
gl.getContext().glDebugMessageControl(gl.GL_DEBUG_SOURCE_API, gl.GL_DEBUG_TYPE_OTHER, if (log.isDebugEnabled())
gl.GL_DEBUG_SEVERITY_NOTIFICATION, 0, null, 0, false); {
} // Debug config on context needs to be set before .makeCurrent call
glContext.enableGLDebugMessage(true);
}
}
finally
{
jawtWindow.unlockSurface();
}
initVao(); int res = glContext.makeCurrent();
initProgram(); if (res == GLContext.CONTEXT_NOT_CURRENT)
initInterfaceTexture(); {
initUniformBuffer(); throw new GLException("Unable to make context current");
initBuffers(); }
// 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.setDrawCallbacks(this);
client.setGpu(true); client.setGpu(true);
@@ -408,41 +429,51 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
client.setGpu(false); client.setGpu(false);
client.setDrawCallbacks(null); client.setDrawCallbacks(null);
if (gl != null) invokeOnMainThread(() ->
{ {
if (textureArrayId != -1) if (gl != null)
{ {
textureManager.freeTextureArray(gl, textureArrayId); if (textureArrayId != -1)
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); if (!jawtWindow.getLock().isLocked())
uniformBufferId = -1; {
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(); GLProfile.shutdown();
shutdownInterfaceTexture();
shutdownProgram();
shutdownVao();
shutdownAAFbo();
}
if (jawtWindow != null)
{
if (!jawtWindow.getLock().isLocked())
{
jawtWindow.lockSurface();
}
if (glContext != null)
{
glContext.destroy();
}
NewtFactoryAWT.destroyNativeWindow(jawtWindow);
}
jawtWindow = null; jawtWindow = null;
gl = null; gl = null;
@@ -839,6 +870,42 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
@Override @Override
public void draw() 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()) if (jawtWindow.getAWTComponent() != client.getCanvas())
{ {
@@ -862,13 +929,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
final int viewportHeight = client.getViewportHeight(); final int viewportHeight = client.getViewportHeight();
final int viewportWidth = client.getViewportWidth(); final int viewportWidth = client.getViewportWidth();
// If the viewport has changed, update the projection matrix resize(canvasWidth, canvasHeight, viewportWidth, viewportHeight);
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;
}
// Setup anti-aliasing // Setup anti-aliasing
final AntiAliasingMode antiAliasingMode = config.antiAliasingMode(); 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.glBlendFunc(gl.GL_ONE, gl.GL_ONE_MINUS_SRC_ALPHA);
gl.glBindTexture(gl.GL_TEXTURE_2D, interfaceTexture); gl.glBindTexture(gl.GL_TEXTURE_2D, interfaceTexture);
if (canvasWidth != lastCanvasWidth || canvasHeight != lastCanvasHeight) 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.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);
}
// Use the texture bound in the first pass // Use the texture bound in the first pass
final UIScalingMode uiScalingMode = config.uiScalingMode(); 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) private void glDpiAwareViewport(final int x, final int y, final int width, final int height)
{ {
final AffineTransform t = ((Graphics2D) canvas.getGraphics()).getTransform(); if (OSType.getOSType() == OSType.MacOS)
gl.glViewport( {
getScaledValue(t.getScaleX(), x), // JOGL seems to handle DPI scaling for us already
getScaledValue(t.getScaleY(), y), gl.glViewport(x, y, width, height);
getScaledValue(t.getScaleX(), width), }
getScaledValue(t.getScaleY(), 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() private int getDrawDistance()
@@ -1539,4 +1599,16 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
final int limit = useComputeShaders ? MAX_DISTANCE : DEFAULT_DISTANCE; final int limit = useComputeShaders ? MAX_DISTANCE : DEFAULT_DISTANCE;
return Ints.constrainToRange(config.drawDistance(), 0, limit); 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();
}
}
} }