diff --git a/src/main/java/rs117/hd/HdPlugin.java b/src/main/java/rs117/hd/HdPlugin.java index ae81387139..9b127a76fd 100644 --- a/src/main/java/rs117/hd/HdPlugin.java +++ b/src/main/java/rs117/hd/HdPlugin.java @@ -133,9 +133,10 @@ import static net.runelite.api.Constants.*; import static org.lwjgl.opengl.GL33C.*; import static rs117.hd.HdPluginConfig.*; +import static rs117.hd.HdPluginFeatures.PROVOKING_VERTEX; +import static rs117.hd.HdPluginFeatures.SHADER_IMAGE_STORE; import static rs117.hd.utils.MathUtils.*; import static rs117.hd.utils.ResourcePath.path; -import static rs117.hd.utils.buffer.GLBuffer.DEBUG_MAC_OS; import static rs117.hd.utils.buffer.GLBuffer.MAP_WRITE; import static rs117.hd.utils.buffer.GLBuffer.STORAGE_IMMUTABLE; import static rs117.hd.utils.buffer.GLBuffer.STORAGE_PERSISTENT; @@ -329,9 +330,6 @@ public class HdPlugin extends Plugin { public static boolean APPLE; public static boolean APPLE_ARM; - public static boolean SUPPORTS_INDIRECT_DRAW; - public static boolean SUPPORTS_STORAGE_BUFFERS; - public Canvas canvas; public JFrame clientJFrame; public AWTContext awtContext; @@ -570,14 +568,6 @@ protected void startUp() { INTEL_GPU = glRenderer.contains("Intel"); NVIDIA_GPU = glRenderer.toLowerCase().contains("nvidia"); - SUPPORTS_INDIRECT_DRAW = config.indirectDraw().get(NVIDIA_GPU && !APPLE); - SUPPORTS_STORAGE_BUFFERS = GL_CAPS.GL_ARB_buffer_storage && !DEBUG_MAC_OS && config.storageBuffers().get(!INTEL_GPU); - log.info( - "Using features: indirectDraw={}, storageBuffers={}", - SUPPORTS_INDIRECT_DRAW, - SUPPORTS_STORAGE_BUFFERS - ); - renderer = config.legacyRenderer() ? injector.getInstance(LegacyRenderer.class) : injector.getInstance(ZoneRenderer.class); @@ -600,6 +590,8 @@ protected void startUp() { } } + HdPluginFeatures.evaluate(config); + lwjglInitialized = true; checkGLErrors(); @@ -715,6 +707,9 @@ protected void startUp() { if (client.getGameState() == GameState.LOGGED_IN) client.setGameState(GameState.LOADING); + if(PROVOKING_VERTEX.isSupported()) + glProvokingVertex(GL_LAST_VERTEX_CONVENTION); + checkGLErrors(); clientThread.invokeLater(this::displayUpdateMessage); @@ -940,6 +935,7 @@ public ShaderIncludes getShaderIncludes() { .addUniformBuffer(uboUI) .addUniformBuffer(materialManager.uboMaterials) .addUniformBuffer(waterTypeManager.uboWaterTypes); + HdPluginFeatures.addShaderIncludes(includes); renderer.addShaderIncludes(includes); return includes; } @@ -955,7 +951,7 @@ private void initializeShaders() throws ShaderException, IOException { if (configDynamicLights != DynamicLights.NONE && configTiledLighting) { if (!AMD_GPU && configTiledLightingImageLoadStore && - GL_CAPS.GL_ARB_shader_image_load_store && + SHADER_IMAGE_STORE.isSupported() && tiledLightingImageStoreProgram.isViable() ) { try { diff --git a/src/main/java/rs117/hd/HdPluginFeatures.java b/src/main/java/rs117/hd/HdPluginFeatures.java new file mode 100644 index 0000000000..6f4b7bbe6e --- /dev/null +++ b/src/main/java/rs117/hd/HdPluginFeatures.java @@ -0,0 +1,128 @@ +package rs117.hd; + +import java.util.ArrayList; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import rs117.hd.opengl.shader.ShaderIncludes; + +import static rs117.hd.HdPlugin.APPLE; +import static rs117.hd.HdPlugin.GL_CAPS; +import static rs117.hd.HdPlugin.INTEL_GPU; +import static rs117.hd.HdPlugin.NVIDIA_GPU; +import static rs117.hd.utils.buffer.GLBuffer.DEBUG_MAC_OS; + +@Slf4j +public final class HdPluginFeatures { + private static final ArrayList FEATURES = new ArrayList<>(); + + public static final FeatureCompat INDIRECT_DRAW = + new FeatureCompat( + "INDIRECT_DRAW", + (config) -> config.indirectDraw().get(NVIDIA_GPU && !APPLE) + ); + + public static final FeatureCompat STORAGE_BUFFERS = + new FeatureCompat( + "STORAGE_BUFFERS", + (config) -> GL_CAPS.GL_ARB_buffer_storage && !DEBUG_MAC_OS && config.storageBuffers().get(!INTEL_GPU) + ); + + public static final FeatureCompat DRAW_INDIRECT = + new FeatureCompat( + "DRAW_ARRAYS_INDIRECT", + (config) -> GL_CAPS.OpenGL40 && HdPluginFeatures.INDIRECT_DRAW.isSupported() + ); + + public static final FeatureCompat MULTI_DRAW_INDIRECT = + new FeatureCompat( + "MULTI_DRAW_INDIRECT", + (config) -> GL_CAPS.OpenGL43 && HdPluginFeatures.INDIRECT_DRAW.isSupported() + ); + + public static final FeatureCompat MAP_BUFFER_RANGE = + new FeatureCompat( + "MAP_BUFFER_RANGE", + (config) -> GL_CAPS.GL_ARB_map_buffer_range + ); + + public static final FeatureCompat TEXTURE_STORAGE = + new FeatureCompat( + "TEXTURE_STORAGE", + (config) -> GL_CAPS.GL_ARB_texture_storage + ); + + public static final FeatureCompat TEXTURE_STORAGE_3D = + new FeatureCompat( + "TEXTURE_STORAGE_3D", + (config) -> GL_CAPS.GL_ARB_texture_storage && GL_CAPS.glTextureStorage3D != 0 + ); + + public static final FeatureCompat PROVOKING_VERTEX = + new FeatureCompat( + "PROVOKING_VERTEX", + true, + (config) -> GL_CAPS.GL_ARB_provoking_vertex + ); + + public static final FeatureCompat SHADER_IMAGE_STORE = + new FeatureCompat( + "SHADER_IMAGE_STORE", + true, + (config) -> GL_CAPS.GL_ARB_shader_image_load_store + ); + + public static void addShaderIncludes(ShaderIncludes includes) { + for (int i = 0; i < FEATURES.size(); i++) { + final FeatureCompat feature = FEATURES.get(i); + if(feature.shaderDefine) + includes.define(feature.name + "_SUPPORT", feature.supported); + } + } + + public static void evaluate(HdPluginConfig config) { + int maxNameLen = 0; + for(int i = 0; i < FEATURES.size(); i++) + maxNameLen = Math.max(maxNameLen, FEATURES.get(i).name.length()); + maxNameLen++; + + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < FEATURES.size(); i++) { + final FeatureCompat feature = FEATURES.get(i); + feature.supported = feature.check.isSupported(config); + if(i > 0) + sb.append("\n"); + + sb.append(" * ").append(feature.name); + + int padding = Math.max(0, maxNameLen - feature.name.length()); + if (padding > 0) + sb.append(" ".repeat(padding)); + + sb.append(": ").append(feature.supported); + } + log.info("Features:\n{}", sb); + } + + public static final class FeatureCompat { + @Getter + private boolean supported; + + public final String name; + public final boolean shaderDefine; + public final CheckFunction check; + + private FeatureCompat(String name, boolean shaderDefine, CheckFunction check) { + FEATURES.add(this); + this.name = name; + this.shaderDefine = shaderDefine; + this.check = check; + } + + private FeatureCompat(String name, CheckFunction check) { + this(name, false, check); + } + + @FunctionalInterface + public interface CheckFunction { boolean isSupported(HdPluginConfig config); } + } +} diff --git a/src/main/java/rs117/hd/renderer/zone/DynamicModelVAO.java b/src/main/java/rs117/hd/renderer/zone/DynamicModelVAO.java index e87cff8996..7633ea05a0 100644 --- a/src/main/java/rs117/hd/renderer/zone/DynamicModelVAO.java +++ b/src/main/java/rs117/hd/renderer/zone/DynamicModelVAO.java @@ -14,10 +14,10 @@ import rs117.hd.utils.buffer.GLTextureBuffer; import static org.lwjgl.opengl.GL33C.*; -import static rs117.hd.HdPlugin.GL_CAPS; import static rs117.hd.HdPlugin.NVIDIA_GPU; -import static rs117.hd.HdPlugin.SUPPORTS_INDIRECT_DRAW; -import static rs117.hd.HdPlugin.SUPPORTS_STORAGE_BUFFERS; +import static rs117.hd.HdPluginFeatures.DRAW_INDIRECT; +import static rs117.hd.HdPluginFeatures.MULTI_DRAW_INDIRECT; +import static rs117.hd.HdPluginFeatures.STORAGE_BUFFERS; import static rs117.hd.renderer.zone.ZoneRenderer.TEXTURE_UNIT_TEXTURED_FACES; import static rs117.hd.utils.MathUtils.*; import static rs117.hd.utils.buffer.GLBuffer.STORAGE_IMMUTABLE; @@ -64,7 +64,7 @@ public class DynamicModelVAO implements Destructible { private long[] copyNumBytes = new long[16]; DynamicModelVAO(String name, boolean useStagingBuffer) { - if (useStagingBuffer && SUPPORTS_STORAGE_BUFFERS) { + if (useStagingBuffer && STORAGE_BUFFERS.isSupported()) { this.vboRender = new GLBuffer("VAO::VBO::" + name, GL_ARRAY_BUFFER, GL_STATIC_DRAW, 0); this.vboStaging = new GLBuffer( "VAO::VBO_STAGING::" + name, @@ -287,13 +287,13 @@ void draw(CommandBuffer cmd) { cmd.BindTextureUnit(GL_TEXTURE_BUFFER, tbo.getTexId(), TEXTURE_UNIT_TEXTURED_FACES); if (drawRangeCount == 1) { - if (GL_CAPS.OpenGL40 && SUPPORTS_INDIRECT_DRAW) { + if (DRAW_INDIRECT.isSupported()) { cmd.DrawArraysIndirect(GL_TRIANGLES, drawOffsets[0], drawCounts[0], ZoneRenderer.indirectDrawCmdsStaging); } else { cmd.DrawArrays(GL_TRIANGLES, drawOffsets[0], drawCounts[0]); } } else { - if (GL_CAPS.OpenGL43 && SUPPORTS_INDIRECT_DRAW) { + if (MULTI_DRAW_INDIRECT.isSupported()) { cmd.MultiDrawArraysIndirect(GL_TRIANGLES, drawOffsets, drawCounts, drawRangeCount, ZoneRenderer.indirectDrawCmdsStaging); } else { cmd.MultiDrawArrays(GL_TRIANGLES, drawOffsets, drawCounts, drawRangeCount); diff --git a/src/main/java/rs117/hd/renderer/zone/Zone.java b/src/main/java/rs117/hd/renderer/zone/Zone.java index e8821e930f..b19033e89e 100644 --- a/src/main/java/rs117/hd/renderer/zone/Zone.java +++ b/src/main/java/rs117/hd/renderer/zone/Zone.java @@ -29,9 +29,9 @@ import rs117.hd.utils.buffer.GLTextureBuffer; import static org.lwjgl.opengl.GL33C.*; -import static rs117.hd.HdPlugin.GL_CAPS; -import static rs117.hd.HdPlugin.SUPPORTS_INDIRECT_DRAW; import static rs117.hd.HdPlugin.checkGLErrors; +import static rs117.hd.HdPluginFeatures.DRAW_INDIRECT; +import static rs117.hd.HdPluginFeatures.MULTI_DRAW_INDIRECT; import static rs117.hd.renderer.zone.ZoneRenderer.TEXTURE_UNIT_TEXTURED_FACES; import static rs117.hd.renderer.zone.ZoneRenderer.eboAlpha; import static rs117.hd.utils.MathUtils.*; @@ -795,7 +795,7 @@ private void flush(CommandBuffer cmd) { cmd.BindVertexArray(lastVao, eboAlpha); cmd.BindTextureUnit(GL_TEXTURE_BUFFER, lastTboF, TEXTURE_UNIT_TEXTURED_FACES); // The EBO & IDO is bound by in ZoneRenderer - if (GL_CAPS.OpenGL40 && SUPPORTS_INDIRECT_DRAW) { + if (DRAW_INDIRECT.isSupported()) { cmd.DrawElementsIndirect(GL_TRIANGLES, vertexCount, (int) (byteOffset / 4L), ZoneRenderer.indirectDrawCmdsStaging); } else { cmd.DrawElements(GL_TRIANGLES, vertexCount, byteOffset); @@ -807,13 +807,13 @@ private void flush(CommandBuffer cmd) { cmd.BindVertexArray(lastVao); cmd.BindTextureUnit(GL_TEXTURE_BUFFER, lastTboF, TEXTURE_UNIT_TEXTURED_FACES); if (drawIdx == 1) { - if (GL_CAPS.OpenGL40 && SUPPORTS_INDIRECT_DRAW) { + if (DRAW_INDIRECT.isSupported()) { cmd.DrawArraysIndirect(GL_TRIANGLES, drawOff[0], drawEnd[0], ZoneRenderer.indirectDrawCmdsStaging); } else { cmd.DrawArrays(GL_TRIANGLES, drawOff[0], drawEnd[0]); } } else { - if (GL_CAPS.OpenGL43 && SUPPORTS_INDIRECT_DRAW) { + if (MULTI_DRAW_INDIRECT.isSupported()) { cmd.MultiDrawArraysIndirect(GL_TRIANGLES, glDrawOffset, glDrawLength, drawIdx, ZoneRenderer.indirectDrawCmdsStaging); } else { cmd.MultiDrawArrays(GL_TRIANGLES, glDrawOffset, glDrawLength, drawIdx); diff --git a/src/main/java/rs117/hd/scene/MaterialManager.java b/src/main/java/rs117/hd/scene/MaterialManager.java index 1666e889e4..42e5760e27 100644 --- a/src/main/java/rs117/hd/scene/MaterialManager.java +++ b/src/main/java/rs117/hd/scene/MaterialManager.java @@ -57,6 +57,7 @@ import static org.lwjgl.opengl.GL33C.*; import static rs117.hd.HdPlugin.TEXTURE_UNIT_GAME; +import static rs117.hd.HdPluginFeatures.TEXTURE_STORAGE_3D; import static rs117.hd.utils.MathUtils.*; import static rs117.hd.utils.ResourcePath.path; @@ -405,7 +406,7 @@ private void swapMaterials(Material[] parsedMaterials, boolean skipSceneReload) log.debug("Allocating {}x{} texture array with {} layers", textureSize, textureSize, textureLayers.size()); int mipLevels = 1 + floor(log2(textureSize)); int format = GL_SRGB8_ALPHA8; - if (HdPlugin.GL_CAPS.glTexStorage3D != 0) { + if (TEXTURE_STORAGE_3D.isSupported()) { ARBTextureStorage.glTexStorage3D(GL_TEXTURE_2D_ARRAY, mipLevels, format, textureSize, textureSize, textureLayers.size()); } else { // Allocate each mip level separately diff --git a/src/main/java/rs117/hd/utils/buffer/GLBuffer.java b/src/main/java/rs117/hd/utils/buffer/GLBuffer.java index 755ba238e3..b303623e96 100644 --- a/src/main/java/rs117/hd/utils/buffer/GLBuffer.java +++ b/src/main/java/rs117/hd/utils/buffer/GLBuffer.java @@ -39,8 +39,8 @@ import static org.lwjgl.opengl.GL44.GL_MAP_PERSISTENT_BIT; import static org.lwjgl.opengl.GL44.glBufferStorage; import static rs117.hd.HdPlugin.GL_CAPS; -import static rs117.hd.HdPlugin.SUPPORTS_STORAGE_BUFFERS; import static rs117.hd.HdPlugin.checkGLErrors; +import static rs117.hd.HdPluginFeatures.STORAGE_BUFFERS; import static rs117.hd.utils.MathUtils.*; @Slf4j @@ -522,7 +522,7 @@ public boolean ensureCapacity(long byteOffset, long numBytes) { } public boolean isStorageBuffer() { - return storageFlags != STORAGE_NONE && SUPPORTS_STORAGE_BUFFERS; + return storageFlags != STORAGE_NONE && STORAGE_BUFFERS.isSupported(); } public boolean isMapped() { diff --git a/src/main/java/rs117/hd/utils/buffer/GLMappedBuffer.java b/src/main/java/rs117/hd/utils/buffer/GLMappedBuffer.java index 92ab6c747a..7dbd6c13ff 100644 --- a/src/main/java/rs117/hd/utils/buffer/GLMappedBuffer.java +++ b/src/main/java/rs117/hd/utils/buffer/GLMappedBuffer.java @@ -7,8 +7,8 @@ import lombok.experimental.Accessors; import static org.lwjgl.opengl.GL33C.*; -import static rs117.hd.HdPlugin.GL_CAPS; import static rs117.hd.HdPlugin.checkGLErrors; +import static rs117.hd.HdPluginFeatures.MAP_BUFFER_RANGE; import static rs117.hd.utils.MathUtils.*; import static rs117.hd.utils.buffer.GLBuffer.MAP_INVALIDATE; import static rs117.hd.utils.buffer.GLBuffer.MAP_READ; @@ -69,7 +69,7 @@ public GLMappedBuffer map(int flags, long offsetBytes, long sizeBytes) { owner.bind(); final ByteBuffer buf; - if (owner.target != GL_STATIC_DRAW && GL_CAPS.GL_ARB_map_buffer_range && !GLBuffer.DEBUG_MAC_OS) { + if (owner.target != GL_STATIC_DRAW && MAP_BUFFER_RANGE.isSupported() && !GLBuffer.DEBUG_MAC_OS) { int glFlags = 0; if ((flags & MAP_WRITE) != 0) glFlags |= GL_MAP_WRITE_BIT; if ((flags & MAP_READ) != 0) glFlags |= GL_MAP_READ_BIT; @@ -157,7 +157,7 @@ public void unmap() { syncViews(); owner.bind(); - if (owner.target != GL_STATIC_DRAW && GL_CAPS.GL_ARB_map_buffer_range && !GLBuffer.DEBUG_MAC_OS) { + if (owner.target != GL_STATIC_DRAW && MAP_BUFFER_RANGE.isSupported() && !GLBuffer.DEBUG_MAC_OS) { byteView.flip(); glFlushMappedBufferRange(owner.target, byteView.position(), byteView.remaining()); byteView.clear(); diff --git a/src/main/resources/rs117/hd/scene_vert.glsl b/src/main/resources/rs117/hd/scene_vert.glsl index 06b5268582..df2c0a85fa 100644 --- a/src/main/resources/rs117/hd/scene_vert.glsl +++ b/src/main/resources/rs117/hd/scene_vert.glsl @@ -68,7 +68,7 @@ layout (location = 0) in vec3 vPosition; void main() { int vertex = gl_VertexID % 3; - bool isProvoking = vertex == 2; + bool isProvoking = vertex == 2 || PROVOKING_VERTEX_SUPPORT == 0; // When lacking support, all vertexs are treated as provoking int materialData = 0; int alphaBiasHsl = 0; diff --git a/src/main/resources/rs117/hd/utils/constants.glsl b/src/main/resources/rs117/hd/utils/constants.glsl index 1ef390944e..ec67791575 100644 --- a/src/main/resources/rs117/hd/utils/constants.glsl +++ b/src/main/resources/rs117/hd/utils/constants.glsl @@ -72,3 +72,4 @@ #include TILED_LIGHTING_TILE_SIZE #define TILED_LIGHTING_MAX_TILE_LIGHT_COUNT (TILED_LIGHTING_LAYER_COUNT * 4 * 2) #include WINDOWS_HDR_CORRECTION +#include PROVOKING_VERTEX_SUPPORT