From 9cf95ef324359bfeaacabc057c86ed5365551041 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 10 Feb 2020 17:59:09 -0500 Subject: [PATCH 1/7] http-service: increase ge history retention to 90 days --- .../runelite/http/service/ge/GrandExchangeService.java | 10 ++++++++-- http-service/src/main/resources/application.yaml | 4 +++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeService.java b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeService.java index 6456beb85f..f53a9095c6 100644 --- a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeService.java +++ b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeService.java @@ -28,6 +28,7 @@ import java.util.Collection; import net.runelite.http.api.ge.GrandExchangeTrade; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.sql2o.Connection; @@ -51,11 +52,16 @@ public class GrandExchangeService ") ENGINE=InnoDB;"; private final Sql2o sql2o; + private final int historyDays; @Autowired - public GrandExchangeService(@Qualifier("Runelite SQL2O") Sql2o sql2o) + public GrandExchangeService( + @Qualifier("Runelite SQL2O") Sql2o sql2o, + @Value("${runelite.ge.history}") int historyDays + ) { this.sql2o = sql2o; + this.historyDays = historyDays; // Ensure necessary tables exist try (Connection con = sql2o.open()) @@ -106,7 +112,7 @@ public class GrandExchangeService { try (Connection con = sql2o.open()) { - con.createQuery("delete from ge_trades where time < current_timestamp - interval 1 month") + con.createQuery("delete from ge_trades where time < current_timestamp - interval " + historyDays + " day") .executeUpdate(); } } diff --git a/http-service/src/main/resources/application.yaml b/http-service/src/main/resources/application.yaml index f5e1a799d9..4328ccfdc0 100644 --- a/http-service/src/main/resources/application.yaml +++ b/http-service/src/main/resources/application.yaml @@ -39,4 +39,6 @@ runelite: twitter: consumerkey: secretkey: - listid: 1185897074786742273 \ No newline at end of file + listid: 1185897074786742273 + ge: + history: 90 # days \ No newline at end of file From d93497c7fc0f02a3bcd7222a52744426be044ee3 Mon Sep 17 00:00:00 2001 From: Oelderoth Date: Tue, 11 Feb 2020 16:47:29 -0600 Subject: [PATCH 2/7] grandexchange plugin: log cancelled buy/sell offers --- .../grandexchange/GrandExchangePlugin.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java index 1e7636f97a..a769660b93 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java @@ -292,8 +292,14 @@ public class GrandExchangePlugin extends Plugin return; } - // Only interested in offers which are fully bought/sold - if (offer.getState() != GrandExchangeOfferState.BOUGHT && offer.getState() != GrandExchangeOfferState.SOLD) + if (offer.getState() != GrandExchangeOfferState.BOUGHT && offer.getState() != GrandExchangeOfferState.SOLD && + offer.getState() != GrandExchangeOfferState.CANCELLED_BUY && offer.getState() != GrandExchangeOfferState.CANCELLED_SELL) + { + return; + } + + // Cancelled offers may have been cancelled before buying/selling any items + if (offer.getQuantitySold() == 0) { return; } @@ -305,12 +311,12 @@ public class GrandExchangePlugin extends Plugin } // getPrice() is the price of the offer, not necessarily what the item bought at - int priceEach = offer.getSpent() / offer.getTotalQuantity(); + int priceEach = offer.getSpent() / offer.getQuantitySold(); GrandExchangeTrade grandExchangeTrade = new GrandExchangeTrade(); - grandExchangeTrade.setBuy(offer.getState() == GrandExchangeOfferState.BOUGHT); + grandExchangeTrade.setBuy(offer.getState() == GrandExchangeOfferState.BOUGHT || offer.getState() == GrandExchangeOfferState.CANCELLED_BUY); grandExchangeTrade.setItemId(offer.getItemId()); - grandExchangeTrade.setQuantity(offer.getTotalQuantity()); + grandExchangeTrade.setQuantity(offer.getQuantitySold()); grandExchangeTrade.setPrice(priceEach); log.debug("Submitting trade: {}", grandExchangeTrade); From cf9f7fc9fb4d76490995f4afcbceb68d17ff8c1f Mon Sep 17 00:00:00 2001 From: Max Weber Date: Mon, 10 Feb 2020 18:33:27 -0700 Subject: [PATCH 3/7] gpu: refactor shader compilation --- .../runelite/client/plugins/gpu/GLUtil.java | 78 +------ .../client/plugins/gpu/GpuPlugin.java | 150 ++++--------- .../runelite/client/plugins/gpu/Shader.java | 123 +++++++++++ .../client/plugins/gpu/template/Template.java | 52 ++++- .../client/plugins/gpu/ShaderTest.java | 199 ------------------ .../plugins/gpu/template/TemplateTest.java | 4 +- 6 files changed, 214 insertions(+), 392 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/gpu/Shader.java delete mode 100644 runelite-client/src/test/java/net/runelite/client/plugins/gpu/ShaderTest.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GLUtil.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GLUtil.java index af5d5ea018..65da9b96e9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GLUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GLUtil.java @@ -25,8 +25,6 @@ package net.runelite.client.plugins.gpu; import com.jogamp.opengl.GL4; -import java.io.InputStream; -import java.util.Scanner; class GLUtil { @@ -58,14 +56,14 @@ class GLUtil { byte[] err = new byte[ERR_LEN]; gl.glGetShaderInfoLog(shader, ERR_LEN, buf, 0, err, 0); - return new String(err); + return new String(err, 0, buf[0]); } static String glGetProgramInfoLog(GL4 gl, int program) { byte[] err = new byte[ERR_LEN]; gl.glGetProgramInfoLog(program, ERR_LEN, buf, 0, err, 0); - return new String(err); + return new String(err, 0, buf[0]); } static int glGenVertexArrays(GL4 gl) @@ -127,76 +125,4 @@ class GLUtil buf[0] = renderBuffer; gl.glDeleteRenderbuffers(1, buf, 0); } - - static void loadShaders(GL4 gl, int glProgram, int glVertexShader, int glGeometryShader, int glFragmentShader, - String vertexShaderStr, String geomShaderStr, String fragShaderStr) throws ShaderException - { - compileAndAttach(gl, glProgram, glVertexShader, vertexShaderStr); - - if (glGeometryShader != -1) - { - compileAndAttach(gl, glProgram, glGeometryShader, geomShaderStr); - } - - compileAndAttach(gl, glProgram, glFragmentShader, fragShaderStr); - - gl.glLinkProgram(glProgram); - - if (glGetProgram(gl, glProgram, gl.GL_LINK_STATUS) == gl.GL_FALSE) - { - String err = glGetProgramInfoLog(gl, glProgram); - throw new ShaderException(err); - } - - gl.glValidateProgram(glProgram); - - if (glGetProgram(gl, glProgram, gl.GL_VALIDATE_STATUS) == gl.GL_FALSE) - { - String err = glGetProgramInfoLog(gl, glProgram); - throw new ShaderException(err); - } - } - - static void loadComputeShader(GL4 gl, int glProgram, int glComputeShader, String str) throws ShaderException - { - compileAndAttach(gl, glProgram, glComputeShader, str); - - gl.glLinkProgram(glProgram); - - if (glGetProgram(gl, glProgram, gl.GL_LINK_STATUS) == gl.GL_FALSE) - { - String err = glGetProgramInfoLog(gl, glProgram); - throw new ShaderException(err); - } - - gl.glValidateProgram(glProgram); - - if (glGetProgram(gl, glProgram, gl.GL_VALIDATE_STATUS) == gl.GL_FALSE) - { - String err = glGetProgramInfoLog(gl, glProgram); - throw new ShaderException(err); - } - } - - private static void compileAndAttach(GL4 gl, int program, int shader, String source) throws ShaderException - { - gl.glShaderSource(shader, 1, new String[]{source}, null); - gl.glCompileShader(shader); - - if (glGetShader(gl, shader, gl.GL_COMPILE_STATUS) == gl.GL_TRUE) - { - gl.glAttachShader(program, shader); - } - else - { - String err = glGetShaderInfoLog(gl, shader); - throw new ShaderException(err); - } - } - - static String inputStreamToString(InputStream in) - { - Scanner scanner = new Scanner(in).useDelimiter("\\A"); - return scanner.next(); - } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java index e4a0233c0f..3dccef8212 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java @@ -46,7 +46,6 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.IntBuffer; -import java.util.function.Function; import javax.inject.Inject; import javax.swing.SwingUtilities; import jogamp.nativewindow.SurfaceScaleUtils; @@ -124,28 +123,41 @@ public class GpuPlugin extends Plugin implements DrawCallbacks private GLContext glContext; private GLDrawable glDrawable; + static final String LINUX_VERSION_HEADER = + "#version 420\n" + + "#extension GL_ARB_compute_shader : require\n" + + "#extension GL_ARB_shader_storage_buffer_object : require\n" + + "#extension GL_ARB_explicit_attrib_location : require\n"; + static final String WINDOWS_VERSION_HEADER = "#version 430\n"; + + static final Shader PROGRAM = new Shader() + .add(GL4.GL_VERTEX_SHADER, "vert.glsl") + .add(GL4.GL_GEOMETRY_SHADER, "geom.glsl") + .add(GL4.GL_FRAGMENT_SHADER, "frag.glsl"); + + static final Shader COMPUTE_PROGRAM = new Shader() + .add(GL4.GL_COMPUTE_SHADER, "comp.glsl"); + + static final Shader SMALL_COMPUTE_PROGRAM = new Shader() + .add(GL4.GL_COMPUTE_SHADER, "comp_small.glsl"); + + static final Shader UNORDERED_COMPUTE_PROGRAM = new Shader() + .add(GL4.GL_COMPUTE_SHADER, "comp_unordered.glsl"); + + static final Shader UI_PROGRAM = new Shader() + .add(GL4.GL_VERTEX_SHADER, "vertui.glsl") + .add(GL4.GL_FRAGMENT_SHADER, "fragui.glsl"); + private int glProgram; - private int glVertexShader; - private int glGeomShader; - private int glFragmentShader; - private int glComputeProgram; - private int glComputeShader; - private int glSmallComputeProgram; - private int glSmallComputeShader; - private int glUnorderedComputeProgram; - private int glUnorderedComputeShader; + private int glUiProgram; private int vaoHandle; private int interfaceTexture; - private int glUiProgram; - private int glUiVertexShader; - private int glUiFragmentShader; - private int vaoUiHandle; private int vboUiHandle; @@ -434,79 +446,23 @@ public class GpuPlugin extends Plugin implements DrawCallbacks private void initProgram() throws ShaderException { - glProgram = gl.glCreateProgram(); - glVertexShader = gl.glCreateShader(gl.GL_VERTEX_SHADER); - glGeomShader = gl.glCreateShader(gl.GL_GEOMETRY_SHADER); - glFragmentShader = gl.glCreateShader(gl.GL_FRAGMENT_SHADER); - - final String glVersionHeader; - - if (OSType.getOSType() == OSType.Linux) + String versionHeader = OSType.getOSType() == OSType.Linux ? LINUX_VERSION_HEADER : WINDOWS_VERSION_HEADER; + Template template = new Template(); + template.add(key -> { - glVersionHeader = - "#version 420\n" + - "#extension GL_ARB_compute_shader : require\n" + - "#extension GL_ARB_shader_storage_buffer_object : require\n"; - } - else - { - glVersionHeader = "#version 430\n"; - } - - Function resourceLoader = (s) -> - { - if (s.endsWith(".glsl")) + if ("version_header".equals(key)) { - return inputStreamToString(getClass().getResourceAsStream(s)); + return versionHeader; } + return null; + }); + template.addInclude(GpuPlugin.class); - if (s.equals("version_header")) - { - return glVersionHeader; - } - - return ""; - }; - - Template template = new Template(resourceLoader); - String source = template.process(resourceLoader.apply("geom.glsl")); - - template = new Template(resourceLoader); - String vertSource = template.process(resourceLoader.apply("vert.glsl")); - - template = new Template(resourceLoader); - String fragSource = template.process(resourceLoader.apply("frag.glsl")); - - GLUtil.loadShaders(gl, glProgram, glVertexShader, glGeomShader, glFragmentShader, - vertSource, - source, - fragSource); - - glComputeProgram = gl.glCreateProgram(); - glComputeShader = gl.glCreateShader(gl.GL_COMPUTE_SHADER); - template = new Template(resourceLoader); - source = template.process(resourceLoader.apply("comp.glsl")); - GLUtil.loadComputeShader(gl, glComputeProgram, glComputeShader, source); - - glSmallComputeProgram = gl.glCreateProgram(); - glSmallComputeShader = gl.glCreateShader(gl.GL_COMPUTE_SHADER); - template = new Template(resourceLoader); - source = template.process(resourceLoader.apply("comp_small.glsl")); - GLUtil.loadComputeShader(gl, glSmallComputeProgram, glSmallComputeShader, source); - - glUnorderedComputeProgram = gl.glCreateProgram(); - glUnorderedComputeShader = gl.glCreateShader(gl.GL_COMPUTE_SHADER); - template = new Template(resourceLoader); - source = template.process(resourceLoader.apply("comp_unordered.glsl")); - GLUtil.loadComputeShader(gl, glUnorderedComputeProgram, glUnorderedComputeShader, source); - - glUiProgram = gl.glCreateProgram(); - glUiVertexShader = gl.glCreateShader(gl.GL_VERTEX_SHADER); - glUiFragmentShader = gl.glCreateShader(gl.GL_FRAGMENT_SHADER); - GLUtil.loadShaders(gl, glUiProgram, glUiVertexShader, -1, glUiFragmentShader, - inputStreamToString(getClass().getResourceAsStream("vertui.glsl")), - null, - inputStreamToString(getClass().getResourceAsStream("fragui.glsl"))); + glProgram = PROGRAM.compile(gl, template); + glComputeProgram = COMPUTE_PROGRAM.compile(gl, template); + glSmallComputeProgram = SMALL_COMPUTE_PROGRAM.compile(gl, template); + glUnorderedComputeProgram = UNORDERED_COMPUTE_PROGRAM.compile(gl, template); + glUiProgram = UI_PROGRAM.compile(gl, template); initUniforms(); } @@ -532,46 +488,18 @@ public class GpuPlugin extends Plugin implements DrawCallbacks private void shutdownProgram() { - gl.glDeleteShader(glVertexShader); - glVertexShader = -1; - - gl.glDeleteShader(glGeomShader); - glGeomShader = -1; - - gl.glDeleteShader(glFragmentShader); - glFragmentShader = -1; - gl.glDeleteProgram(glProgram); glProgram = -1; - /// - - gl.glDeleteShader(glComputeShader); - glComputeShader = -1; - gl.glDeleteProgram(glComputeProgram); glComputeProgram = -1; - gl.glDeleteShader(glSmallComputeShader); - glSmallComputeShader = -1; - gl.glDeleteProgram(glSmallComputeProgram); glSmallComputeProgram = -1; - gl.glDeleteShader(glUnorderedComputeShader); - glUnorderedComputeShader = -1; - gl.glDeleteProgram(glUnorderedComputeProgram); glUnorderedComputeProgram = -1; - /// - - gl.glDeleteShader(glUiVertexShader); - glUiVertexShader = -1; - - gl.glDeleteShader(glUiFragmentShader); - glUiFragmentShader = -1; - gl.glDeleteProgram(glUiProgram); glUiProgram = -1; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/Shader.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/Shader.java new file mode 100644 index 0000000000..1146fd3332 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/Shader.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2018, Adam + * Copyright (c) 2020 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.plugins.gpu; + +import com.google.common.annotations.VisibleForTesting; +import com.jogamp.opengl.GL4; +import java.util.ArrayList; +import java.util.List; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.runelite.client.plugins.gpu.template.Template; + +public class Shader +{ + @VisibleForTesting + final List units = new ArrayList<>(); + + @RequiredArgsConstructor + @VisibleForTesting + static class Unit + { + @Getter + private final int type; + + @Getter + private final String filename; + } + + public Shader() + { + } + + public Shader add(int type, String name) + { + units.add(new Unit(type, name)); + return this; + } + + public int compile(GL4 gl, Template template) throws ShaderException + { + int program = gl.glCreateProgram(); + int[] shaders = new int[units.size()]; + int i = 0; + boolean ok = false; + try + { + while (i < shaders.length) + { + Unit unit = units.get(i); + int shader = gl.glCreateShader(unit.type); + String source = template.load(unit.filename); + gl.glShaderSource(shader, 1, new String[]{source}, null); + gl.glCompileShader(shader); + + if (GLUtil.glGetShader(gl, shader, gl.GL_COMPILE_STATUS) != gl.GL_TRUE) + { + String err = GLUtil.glGetShaderInfoLog(gl, shader); + gl.glDeleteShader(shader); + throw new ShaderException(err); + } + gl.glAttachShader(program, shader); + shaders[i++] = shader; + } + + gl.glLinkProgram(program); + + if (GLUtil.glGetProgram(gl, program, gl.GL_LINK_STATUS) == gl.GL_FALSE) + { + String err = GLUtil.glGetProgramInfoLog(gl, program); + throw new ShaderException(err); + } + + gl.glValidateProgram(program); + + if (GLUtil.glGetProgram(gl, program, gl.GL_VALIDATE_STATUS) == gl.GL_FALSE) + { + String err = GLUtil.glGetProgramInfoLog(gl, program); + throw new ShaderException(err); + } + + ok = true; + } + finally + { + while (i > 0) + { + int shader = shaders[--i]; + gl.glDetachShader(program, shader); + gl.glDeleteShader(shader); + } + + if (!ok) + { + gl.glDeleteProgram(program); + } + } + + return program; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/template/Template.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/template/Template.java index 1f2ea73549..3bf7059382 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/template/Template.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/template/Template.java @@ -24,15 +24,18 @@ */ package net.runelite.client.plugins.gpu.template; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; import java.util.function.Function; public class Template { - private final Function resourceLoader; + private final List> resourceLoaders = new ArrayList<>(); - public Template(Function resourceLoader) + public Template() { - this.resourceLoader = resourceLoader; } public String process(String str) @@ -43,8 +46,8 @@ public class Template if (line.startsWith("#include ")) { String resource = line.substring(9); - String resourceStr = resourceLoader.apply(resource); - sb.append(process(resourceStr)); + String resourceStr = load(resource); + sb.append(resourceStr); } else { @@ -53,4 +56,43 @@ public class Template } return sb.toString(); } + + public String load(String filename) + { + for (Function loader : resourceLoaders) + { + String value = loader.apply(filename); + if (value != null) + { + return process(value); + } + } + + return ""; + } + + public Template add(Function fn) + { + resourceLoaders.add(fn); + return this; + } + + public Template addInclude(Class clazz) + { + return add(f -> + { + InputStream is = clazz.getResourceAsStream(f); + if (is != null) + { + return inputStreamToString(is); + } + return null; + }); + } + + private static String inputStreamToString(InputStream in) + { + Scanner scanner = new Scanner(in).useDelimiter("\\A"); + return scanner.next(); + } } diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/gpu/ShaderTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/gpu/ShaderTest.java deleted file mode 100644 index bc42b37239..0000000000 --- a/runelite-client/src/test/java/net/runelite/client/plugins/gpu/ShaderTest.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (c) 2018, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.plugins.gpu; - -import com.jogamp.nativewindow.AbstractGraphicsConfiguration; -import com.jogamp.nativewindow.NativeWindowFactory; -import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration; -import com.jogamp.nativewindow.awt.JAWTWindow; -import com.jogamp.opengl.GL4; -import com.jogamp.opengl.GLCapabilities; -import com.jogamp.opengl.GLContext; -import com.jogamp.opengl.GLDrawable; -import com.jogamp.opengl.GLDrawableFactory; -import com.jogamp.opengl.GLProfile; -import java.awt.Canvas; -import java.util.function.Function; -import javax.swing.JFrame; -import static net.runelite.client.plugins.gpu.GLUtil.inputStreamToString; -import net.runelite.client.plugins.gpu.template.Template; -import static org.junit.Assert.fail; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -public class ShaderTest -{ - private static final String VERTEX_SHADER = "" + - "void main() {" + - " gl_Position = vec4(1.0, 1.0, 1.0, 1.0);" + - "}"; - private GL4 gl; - - @Before - public void before() - { - Canvas canvas = new Canvas(); - JFrame frame = new JFrame(); - frame.setSize(100, 100); - frame.add(canvas); - frame.setVisible(true); - - GLProfile glProfile = GLProfile.getMaxFixedFunc(true); - - GLCapabilities glCaps = new GLCapabilities(glProfile); - AbstractGraphicsConfiguration config = AWTGraphicsConfiguration.create(canvas.getGraphicsConfiguration(), - glCaps, glCaps); - - JAWTWindow jawtWindow = (JAWTWindow) NativeWindowFactory.getNativeWindow(canvas, config); - - GLDrawableFactory glDrawableFactory = GLDrawableFactory.getFactory(glProfile); - - GLDrawable glDrawable = glDrawableFactory.createGLDrawable(jawtWindow); - glDrawable.setRealized(true); - - - GLContext glContext = glDrawable.createContext(null); - int res = glContext.makeCurrent(); - if (res == GLContext.CONTEXT_NOT_CURRENT) - { - fail("error making context current"); - } - - gl = glContext.getGL().getGL4(); - } - - @Test - @Ignore - public void testUnordered() throws ShaderException - { - int glComputeProgram = gl.glCreateProgram(); - int glComputeShader = gl.glCreateShader(gl.GL_COMPUTE_SHADER); - try - { - Function func = (s) -> inputStreamToString(getClass().getResourceAsStream(s)); - Template template = new Template(func); - String source = template.process(func.apply("comp_unordered.glsl")); - - int line = 0; - for (String str : source.split("\\n")) - { - System.out.println(++line + " " + str); - } - - GLUtil.loadComputeShader(gl, glComputeProgram, glComputeShader, source); - } - finally - { - gl.glDeleteShader(glComputeShader); - gl.glDeleteProgram(glComputeProgram); - } - } - - @Test - @Ignore - public void testSmall() throws ShaderException - { - int glComputeProgram = gl.glCreateProgram(); - int glComputeShader = gl.glCreateShader(gl.GL_COMPUTE_SHADER); - try - { - Function func = (s) -> inputStreamToString(getClass().getResourceAsStream(s)); - Template template = new Template(func); - String source = template.process(func.apply("comp_small.glsl")); - - int line = 0; - for (String str : source.split("\\n")) - { - System.out.println(++line + " " + str); - } - - GLUtil.loadComputeShader(gl, glComputeProgram, glComputeShader, source); - } - finally - { - gl.glDeleteShader(glComputeShader); - gl.glDeleteProgram(glComputeProgram); - } - } - - @Test - @Ignore - public void testComp() throws ShaderException - { - int glComputeProgram = gl.glCreateProgram(); - int glComputeShader = gl.glCreateShader(gl.GL_COMPUTE_SHADER); - try - { - Function func = (s) -> inputStreamToString(getClass().getResourceAsStream(s)); - Template template = new Template(func); - String source = template.process(func.apply("comp.glsl")); - - int line = 0; - for (String str : source.split("\\n")) - { - System.out.println(++line + " " + str); - } - - GLUtil.loadComputeShader(gl, glComputeProgram, glComputeShader, source); - } - finally - { - gl.glDeleteShader(glComputeShader); - gl.glDeleteProgram(glComputeProgram); - } - } - - @Test - @Ignore - public void testGeom() throws ShaderException - { - int glComputeProgram = gl.glCreateProgram(); - int glVertexShader = gl.glCreateShader(gl.GL_VERTEX_SHADER); - int glGeometryShader = gl.glCreateShader(gl.GL_GEOMETRY_SHADER); - int glFragmentShader = gl.glCreateShader(gl.GL_FRAGMENT_SHADER); - try - { - Function func = (s) -> inputStreamToString(getClass().getResourceAsStream(s)); - Template template = new Template(func); - String source = template.process(func.apply("geom.glsl")); - - int line = 0; - for (String str : source.split("\\n")) - { - System.out.println(++line + " " + str); - } - - GLUtil.loadShaders(gl, glComputeProgram, glVertexShader, glGeometryShader, glFragmentShader, VERTEX_SHADER, source, ""); - } - finally - { - gl.glDeleteShader(glVertexShader); - gl.glDeleteShader(glGeometryShader); - gl.glDeleteShader(glFragmentShader); - gl.glDeleteProgram(glComputeProgram); - } - } -} diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/gpu/template/TemplateTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/gpu/template/TemplateTest.java index 0c35e65d52..2c60d58bd8 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/gpu/template/TemplateTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/gpu/template/TemplateTest.java @@ -58,7 +58,9 @@ public class TemplateTest throw new RuntimeException("unknown resource"); } }; - String out = new Template(func).process(FILE1); + String out = new Template() + .add(func) + .process(FILE1); assertEquals(RESULT, out); } } \ No newline at end of file From 7e8bebc08329b6c9422237eaab9d0e7eba2f4a38 Mon Sep 17 00:00:00 2001 From: Max Weber Date: Mon, 10 Feb 2020 18:35:29 -0700 Subject: [PATCH 4/7] gpu: run glslangValidator on shaders during tests --- pom.xml | 4 + .../client/plugins/gpu/ShaderTest.java | 130 ++++++++++++++++++ travis/build.sh | 8 +- 3 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 runelite-client/src/test/java/net/runelite/client/plugins/gpu/ShaderTest.java diff --git a/pom.xml b/pom.xml index fafd15de44..76ac38187a 100644 --- a/pom.xml +++ b/pom.xml @@ -42,6 +42,7 @@ true true + 188 @@ -171,6 +172,9 @@ true -Xmx512m + + ${glslang.path} + diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/gpu/ShaderTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/gpu/ShaderTest.java new file mode 100644 index 0000000000..7b206cbacd --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/gpu/ShaderTest.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2020 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.plugins.gpu; + +import com.jogamp.opengl.GL4; +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; +import joptsimple.internal.Strings; +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.plugins.gpu.template.Template; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +@Slf4j +public class ShaderTest +{ + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @Test + public void testShaders() throws Exception + { + String verifier = System.getProperty("glslang.path"); + Assume.assumeFalse("glslang.path is not set", Strings.isNullOrEmpty(verifier)); + + Template[] templates = { + new Template() + .addInclude(GpuPlugin.class) + .add(key -> + { + if ("version_header".equals(key)) + { + return GpuPlugin.WINDOWS_VERSION_HEADER; + } + return null; + }), + }; + + Shader[] shaders = { + GpuPlugin.PROGRAM, + GpuPlugin.COMPUTE_PROGRAM, + GpuPlugin.SMALL_COMPUTE_PROGRAM, + GpuPlugin.UNORDERED_COMPUTE_PROGRAM, + GpuPlugin.UI_PROGRAM, + }; + + for (Template t : templates) + { + for (Shader s : shaders) + { + verify(t, s); + } + } + } + + private void verify(Template template, Shader shader) throws Exception + { + File folder = temp.newFolder(); + List args = new ArrayList<>(); + args.add(System.getProperty("glslang.path")); + args.add("-l"); + for (Shader.Unit u : shader.units) + { + String contents = template.load(u.getFilename()); + String ext; + switch (u.getType()) + { + case GL4.GL_VERTEX_SHADER: + ext = "vert"; + break; + case GL4.GL_TESS_CONTROL_SHADER: + ext = "tesc"; + break; + case GL4.GL_TESS_EVALUATION_SHADER: + ext = "tese"; + break; + case GL4.GL_GEOMETRY_SHADER: + ext = "geom"; + break; + case GL4.GL_FRAGMENT_SHADER: + ext = "frag"; + break; + case GL4.GL_COMPUTE_SHADER: + ext = "comp"; + break; + default: + throw new IllegalArgumentException(u.getType() + ""); + } + File file = new File(folder, u.getFilename() + "." + ext); + Files.write(file.toPath(), contents.getBytes(StandardCharsets.UTF_8)); + args.add(file.getAbsolutePath()); + } + + ProcessBuilder pb = new ProcessBuilder(args.toArray(new String[0])); + pb.inheritIO(); + Process proc = pb.start(); + if (proc.waitFor() != 0) + { + Assert.fail(); + } + } +} diff --git a/travis/build.sh b/travis/build.sh index deba275667..d86e56f113 100755 --- a/travis/build.sh +++ b/travis/build.sh @@ -1,3 +1,9 @@ #!/bin/bash -mvn clean install --settings travis/settings.xml +set -e -x + +wget -O/tmp/glslang.zip 'https://github.com/KhronosGroup/glslang/releases/download/8.13.3559/glslang-master-linux-Release.zip' +echo '9adcfdef5b52275e61068aafbb62747936c6c18ab6dc32a6ef707cfc7b0df423 /tmp/glslang.zip' | sha256sum -c +unzip -q /tmp/glslang.zip -d /tmp/glslang + +mvn clean install --settings travis/settings.xml -Dglslang.path=/tmp/glslang/bin/glslangValidator From a330631945855fec65caf86d28fad80ab3a7c8f8 Mon Sep 17 00:00:00 2001 From: Max Weber Date: Mon, 10 Feb 2020 18:38:11 -0700 Subject: [PATCH 5/7] gpu: rename length to size in shaders `.length` has special meaning in glsl, and the verifier got upset that we were shadowing it --- .../net/runelite/client/plugins/gpu/comp.glsl | 2 +- .../client/plugins/gpu/comp_common.glsl | 2 +- .../client/plugins/gpu/comp_unordered.glsl | 4 ++-- .../client/plugins/gpu/priority_render.glsl | 20 +++++++++---------- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp.glsl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp.glsl index f569bceed6..7c7f948ea3 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp.glsl +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp.glsl @@ -44,7 +44,7 @@ void main() { uint groupId = gl_WorkGroupID.x; uint localId = gl_LocalInvocationID.x * 4; modelinfo minfo = ol[groupId]; - int length = minfo.length; + int length = minfo.size; if (localId == 0) { min10 = 1600; diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp_common.glsl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp_common.glsl index c527a942c3..934407b94b 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp_common.glsl +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp_common.glsl @@ -41,7 +41,7 @@ struct modelinfo { int offset; // offset into buffer int uvOffset; // offset into uv buffer - int length; // length in faces + int size; // length in faces int idx; // write idx in target buffer int flags; // radius, orientation int x; // scene position x diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp_unordered.glsl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp_unordered.glsl index b4b526838b..531eb6c935 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp_unordered.glsl +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp_unordered.glsl @@ -37,14 +37,14 @@ void main() { modelinfo minfo = ol[groupId]; int offset = minfo.offset; - int length = minfo.length; + int size = minfo.size; int outOffset = minfo.idx; int uvOffset = minfo.uvOffset; int flags = minfo.flags; int orientation = flags & 0x7ff; ivec4 pos = ivec4(minfo.x, minfo.y, minfo.z, 0); - if (localId >= length) { + if (localId >= size) { return; } diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/priority_render.glsl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/priority_render.glsl index 968f8aec00..5077182e1a 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/priority_render.glsl +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/priority_render.glsl @@ -113,7 +113,7 @@ int count_prio_offset(int priority) { void get_face(uint localId, modelinfo minfo, int cameraYaw, int cameraPitch, int centerX, int centerY, int zoom, out int prio, out int dis, out ivec4 o1, out ivec4 o2, out ivec4 o3) { int offset = minfo.offset; - int length = minfo.length; + int size = minfo.size; int flags = minfo.flags; int radius = (flags & 0x7fffffff) >> 12; int orientation = flags & 0x7ff; @@ -121,7 +121,7 @@ void get_face(uint localId, modelinfo minfo, int cameraYaw, int cameraPitch, int uint ssboOffset; - if (localId < length) { + if (localId < size) { ssboOffset = localId; } else { ssboOffset = 0; @@ -148,7 +148,7 @@ void get_face(uint localId, modelinfo minfo, int cameraYaw, int cameraPitch, int int thisPriority, thisDistance; - if (localId < length) { + if (localId < size) { // rotate for model orientation thisrvA = rotate(thisA, orientation); thisrvB = rotate(thisB, orientation); @@ -186,14 +186,14 @@ void get_face(uint localId, modelinfo minfo, int cameraYaw, int cameraPitch, int } int map_face_priority(uint localId, modelinfo minfo, int thisPriority, int thisDistance, out int prio) { - int length = minfo.length; + int size = minfo.size; // Compute average distances for 0/2, 3/4, and 6/8 int adjPrio; int prioIdx; - if (localId < length) { + if (localId < size) { int avg1 = 0; int avg2 = 0; int avg3 = 0; @@ -224,9 +224,9 @@ int map_face_priority(uint localId, modelinfo minfo, int thisPriority, int thisD } void insert_dfs(uint localId, modelinfo minfo, int adjPrio, int distance, int prioIdx) { - int length = minfo.length; + int size = minfo.size; - if (localId < length) { + if (localId < size) { // calculate base offset into dfs based on number of faces with a lower priority int baseOff = count_prio_offset(adjPrio); // store into face array offset array by unique index @@ -236,14 +236,14 @@ void insert_dfs(uint localId, modelinfo minfo, int adjPrio, int distance, int pr void sort_and_insert(uint localId, modelinfo minfo, int thisPriority, int thisDistance, ivec4 thisrvA, ivec4 thisrvB, ivec4 thisrvC) { /* compute face distance */ - int length = minfo.length; + int size = minfo.size; int outOffset = minfo.idx; int uvOffset = minfo.uvOffset; int flags = minfo.flags; ivec4 pos = ivec4(minfo.x, minfo.y, minfo.z, 0); int start, end, myOffset; - if (localId < length) { + if (localId < size) { const int priorityOffset = count_prio_offset(thisPriority); const int numOfPriority = totalMappedNum[thisPriority]; start = priorityOffset; // index of first face with this priority @@ -253,7 +253,7 @@ void sort_and_insert(uint localId, modelinfo minfo, int thisPriority, int thisDi start = end = myOffset = 0; } - if (localId < length) { + if (localId < size) { // we only have to order faces against others of the same priority // calculate position this face will be in for (int i = start; i < end; ++i) { From 94ff26f3d82eb4ef60ef7bc53f0bf1b2fb3f45ef Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 11 Feb 2020 18:36:39 -0500 Subject: [PATCH 6/7] widgetitemoverlay: clip dragged items when outside of parent bounds Since dragged items are not moved until after the drag is complete, the item still gets queued to be drawn, even if dragged outside of the parent layer. --- .../client/ui/overlay/WidgetItemOverlay.java | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetItemOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetItemOverlay.java index c234a0d4dd..b351dcf808 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetItemOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetItemOverlay.java @@ -89,12 +89,26 @@ public abstract class WidgetItemOverlay extends Overlay Widget parent = widget.getParent(); Rectangle parentBounds = parent.getBounds(); Rectangle itemCanvasBounds = widgetItem.getCanvasBounds(); + boolean dragging = widgetItem.getDraggingCanvasBounds() != null; boolean shouldClip; - shouldClip = itemCanvasBounds.y < parentBounds.y && itemCanvasBounds.y + itemCanvasBounds.height >= parentBounds.y; - shouldClip |= itemCanvasBounds.y < parentBounds.y + parentBounds.height && itemCanvasBounds.y + itemCanvasBounds.height >= parentBounds.y + parentBounds.height; - shouldClip |= itemCanvasBounds.x < parentBounds.x && (itemCanvasBounds.x + itemCanvasBounds.width) >= parentBounds.x; - shouldClip |= itemCanvasBounds.x < parentBounds.x + parentBounds.width && itemCanvasBounds.x + itemCanvasBounds.width >= parentBounds.x + parentBounds.width; + if (dragging) + { + // If dragging, clip if the dragged item is outside of the parent bounds + shouldClip = itemCanvasBounds.x < parentBounds.x; + shouldClip |= itemCanvasBounds.x + itemCanvasBounds.width >= parentBounds.x + parentBounds.width; + shouldClip |= itemCanvasBounds.y < parentBounds.y; + shouldClip |= itemCanvasBounds.y + itemCanvasBounds.height >= parentBounds.y + parentBounds.height; + } + else + { + // Otherwise, we only need to clip the overlay if it intersects the parent bounds, + // since items completely outside of the parent bounds are not drawn + shouldClip = itemCanvasBounds.y < parentBounds.y && itemCanvasBounds.y + itemCanvasBounds.height >= parentBounds.y; + shouldClip |= itemCanvasBounds.y < parentBounds.y + parentBounds.height && itemCanvasBounds.y + itemCanvasBounds.height >= parentBounds.y + parentBounds.height; + shouldClip |= itemCanvasBounds.x < parentBounds.x && itemCanvasBounds.x + itemCanvasBounds.width >= parentBounds.x; + shouldClip |= itemCanvasBounds.x < parentBounds.x + parentBounds.width && itemCanvasBounds.x + itemCanvasBounds.width >= parentBounds.x + parentBounds.width; + } if (shouldClip) { if (curClipParent != parent) From ff8c0115cdd660c53063792d1d1f55d51edbbb6a Mon Sep 17 00:00:00 2001 From: Grahm Larkham Date: Tue, 11 Feb 2020 20:25:25 -0500 Subject: [PATCH 7/7] imp plugin: fix notifications on npc change --- .../runelite/client/plugins/implings/ImplingsPlugin.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/implings/ImplingsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/implings/ImplingsPlugin.java index a20895b8f4..f2c25bcbda 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/implings/ImplingsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/implings/ImplingsPlugin.java @@ -113,14 +113,17 @@ public class ImplingsPlugin extends Plugin NPC npc = npcCompositionChanged.getNpc(); Impling impling = Impling.findImpling(npc.getId()); - if (impling != null && !implings.contains(npc)) + if (impling != null) { if (showImplingType(impling.getImplingType()) == ImplingsConfig.ImplingMode.NOTIFY) { notifier.notify(impling.getImplingType().getName() + " impling is in the area"); } - implings.add(npc); + if (!implings.contains(npc)) + { + implings.add(npc); + } } }