diff --git a/src/main/java/net/coderbot/iris/celeritas/CeleritasTerrainPipeline.java b/src/main/java/net/coderbot/iris/celeritas/CeleritasTerrainPipeline.java index 77bad4b61..5347c3861 100644 --- a/src/main/java/net/coderbot/iris/celeritas/CeleritasTerrainPipeline.java +++ b/src/main/java/net/coderbot/iris/celeritas/CeleritasTerrainPipeline.java @@ -12,6 +12,7 @@ import net.coderbot.iris.gl.program.ProgramUniforms; import net.coderbot.iris.pipeline.PatchedShaderPrinter; import net.coderbot.iris.pipeline.transform.PatchShaderType; import net.coderbot.iris.rendertarget.RenderTargets; +import net.coderbot.iris.gl.state.FogMode; import net.coderbot.iris.uniforms.CommonUniforms; import net.coderbot.iris.uniforms.builtin.BuiltinReplacementUniforms; import net.coderbot.iris.shaderpack.ProgramSource; @@ -146,7 +147,7 @@ public class CeleritasTerrainPipeline { public ProgramUniforms.Builder initUniforms(int programId) { final ProgramUniforms.Builder uniforms = ProgramUniforms.builder("", programId); - CommonUniforms.addDynamicUniforms(uniforms); + CommonUniforms.addDynamicUniforms(uniforms, FogMode.PER_VERTEX); customUniforms.assignTo(uniforms); BuiltinReplacementUniforms.addBuiltinReplacementUniforms(uniforms); diff --git a/src/main/java/net/coderbot/iris/gl/blending/AlphaTest.java b/src/main/java/net/coderbot/iris/gl/blending/AlphaTest.java index 93d8ede42..535047942 100644 --- a/src/main/java/net/coderbot/iris/gl/blending/AlphaTest.java +++ b/src/main/java/net/coderbot/iris/gl/blending/AlphaTest.java @@ -1,6 +1,8 @@ package net.coderbot.iris.gl.blending; public class AlphaTest { + public static final AlphaTest ALWAYS = new AlphaTest(AlphaTestFunction.ALWAYS, 0.0f); + private final AlphaTestFunction function; private final float reference; @@ -16,4 +18,45 @@ public class AlphaTest { public float getReference() { return reference; } + + public String toExpression(String indentation) { + return toExpression("gl_FragData[0].a", "iris_currentAlphaTest", indentation); + } + + public String toExpression(String alphaAccessor, String alphaThreshold, String indentation) { + String expr = function.getExpression(); + + if (function == AlphaTestFunction.ALWAYS) { + return "// alpha test disabled\n"; + } else if (function == AlphaTestFunction.NEVER) { + return "discard;\n"; + } + + return indentation + "if (!(" + alphaAccessor + " " + expr + " " + alphaThreshold + ")) {\n" + + indentation + " discard;\n" + + indentation + "}\n"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((function == null) ? 0 : function.hashCode()); + result = prime * result + Float.floatToIntBits(reference); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AlphaTest other = (AlphaTest) obj; + if (function != other.function) + return false; + return Float.floatToIntBits(reference) == Float.floatToIntBits(other.reference); + } } diff --git a/src/main/java/net/coderbot/iris/gl/blending/AlphaTestFunction.java b/src/main/java/net/coderbot/iris/gl/blending/AlphaTestFunction.java index 6a15e3d61..e06eb3aa8 100644 --- a/src/main/java/net/coderbot/iris/gl/blending/AlphaTestFunction.java +++ b/src/main/java/net/coderbot/iris/gl/blending/AlphaTestFunction.java @@ -5,33 +5,35 @@ import org.lwjgl.opengl.GL11; import java.util.Optional; public enum AlphaTestFunction { - NEVER(GL11.GL_NEVER), - LESS(GL11.GL_LESS), - EQUAL(GL11.GL_EQUAL), - LEQUAL(GL11.GL_LEQUAL), - GREATER(GL11.GL_GREATER), - NOTEQUAL(GL11.GL_NOTEQUAL), - GEQUAL(GL11.GL_GEQUAL), - ALWAYS(GL11.GL_ALWAYS); + NEVER(GL11.GL_NEVER, null), + LESS(GL11.GL_LESS, "<"), + EQUAL(GL11.GL_EQUAL, "=="), + LEQUAL(GL11.GL_LEQUAL, "<="), + GREATER(GL11.GL_GREATER, ">"), + NOTEQUAL(GL11.GL_NOTEQUAL, "!="), + GEQUAL(GL11.GL_GEQUAL, ">="), + ALWAYS(GL11.GL_ALWAYS, null); private final int glId; + private final String expression; - AlphaTestFunction(int glFormat) { + AlphaTestFunction(int glFormat, String expression) { this.glId = glFormat; + this.expression = expression; } public static Optional fromGlId(int glId) { - return switch (glId) { - case GL11.GL_NEVER -> Optional.of(NEVER); - case GL11.GL_LESS -> Optional.of(LESS); - case GL11.GL_EQUAL -> Optional.of(EQUAL); - case GL11.GL_LEQUAL -> Optional.of(LEQUAL); - case GL11.GL_GREATER -> Optional.of(GREATER); - case GL11.GL_NOTEQUAL -> Optional.of(NOTEQUAL); - case GL11.GL_GEQUAL -> Optional.of(GEQUAL); - case GL11.GL_ALWAYS -> Optional.of(ALWAYS); - default -> Optional.empty(); - }; + return switch (glId) { + case GL11.GL_NEVER -> Optional.of(NEVER); + case GL11.GL_LESS -> Optional.of(LESS); + case GL11.GL_EQUAL -> Optional.of(EQUAL); + case GL11.GL_LEQUAL -> Optional.of(LEQUAL); + case GL11.GL_GREATER -> Optional.of(GREATER); + case GL11.GL_NOTEQUAL -> Optional.of(NOTEQUAL); + case GL11.GL_GEQUAL -> Optional.of(GEQUAL); + case GL11.GL_ALWAYS -> Optional.of(ALWAYS); + default -> Optional.empty(); + }; } public static Optional fromString(String name) { @@ -54,4 +56,8 @@ public enum AlphaTestFunction { public int getGlId() { return glId; } + + public String getExpression() { + return expression; + } } diff --git a/src/main/java/net/coderbot/iris/gl/image/ImageBinding.java b/src/main/java/net/coderbot/iris/gl/image/ImageBinding.java index aeab815f8..344bdd78f 100644 --- a/src/main/java/net/coderbot/iris/gl/image/ImageBinding.java +++ b/src/main/java/net/coderbot/iris/gl/image/ImageBinding.java @@ -19,6 +19,6 @@ public class ImageBinding { public void update() { // We can assume that image bindings are supported here as either the EXT extension or 4.2 core, as otherwise ImageLimits // would report that zero image units are supported. - RenderSystem.bindImageTexture(imageUnit, textureID.getAsInt(), 0, false, 0, GL15.GL_READ_WRITE, internalFormat); + RenderSystem.bindImageTexture(imageUnit, textureID.getAsInt(), 0, true, 0, GL15.GL_READ_WRITE, internalFormat); } } diff --git a/src/main/java/net/coderbot/iris/gl/state/FogMode.java b/src/main/java/net/coderbot/iris/gl/state/FogMode.java new file mode 100644 index 000000000..5c6ddef45 --- /dev/null +++ b/src/main/java/net/coderbot/iris/gl/state/FogMode.java @@ -0,0 +1,18 @@ +package net.coderbot.iris.gl.state; + +public enum FogMode { + /** + * Fog is disabled. + */ + OFF, + + /** + * Per-vertex fog, applicable to most geometry. + */ + PER_VERTEX, + + /** + * Per-fragment fog, for extra-long geometry like beacon beams. + */ + PER_FRAGMENT +} diff --git a/src/main/java/net/coderbot/iris/pipeline/ClearPass.java b/src/main/java/net/coderbot/iris/pipeline/ClearPass.java index 0d2558715..e02edbd42 100644 --- a/src/main/java/net/coderbot/iris/pipeline/ClearPass.java +++ b/src/main/java/net/coderbot/iris/pipeline/ClearPass.java @@ -1,5 +1,6 @@ package net.coderbot.iris.pipeline; +import com.gtnewhorizons.angelica.glsm.GLStateManager; import net.coderbot.iris.gl.framebuffer.GlFramebuffer; import net.minecraft.client.Minecraft; import org.joml.Vector4f; @@ -24,7 +25,7 @@ public class ClearPass { } public void execute(Vector4f defaultClearColor) { - GL11.glViewport(0, 0, viewportX.getAsInt(), viewportY.getAsInt()); + GLStateManager.glViewport(0, 0, viewportX.getAsInt(), viewportY.getAsInt()); framebuffer.bind(); Vector4f color = Objects.requireNonNull(defaultClearColor); diff --git a/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java b/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java index ec9f96004..9a4552aa7 100644 --- a/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java +++ b/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java @@ -9,15 +9,13 @@ import com.gtnewhorizons.angelica.glsm.RenderSystem; import com.gtnewhorizons.angelica.glsm.texture.TextureInfoCache; import com.gtnewhorizons.angelica.rendering.RenderingState; import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; -import net.coderbot.iris.gl.buffer.ShaderStorageBufferHolder; -import net.coderbot.iris.gl.buffer.ShaderStorageInfo; -import net.coderbot.iris.gl.image.GlImage; -import net.coderbot.iris.gl.image.ImageInformation; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import net.coderbot.iris.Iris; import net.coderbot.iris.block_rendering.BlockMaterialMapping; +import net.coderbot.iris.block_rendering.BlockRenderingSettings; import net.coderbot.iris.celeritas.CeleritasTerrainPipeline; import net.coderbot.iris.compat.dh.DHCompat; -import net.coderbot.iris.block_rendering.BlockRenderingSettings; +import net.coderbot.iris.features.FeatureFlags; import net.coderbot.iris.gbuffer_overrides.matching.InputAvailability; import net.coderbot.iris.gbuffer_overrides.matching.ProgramTable; import net.coderbot.iris.gbuffer_overrides.matching.RenderCondition; @@ -26,14 +24,20 @@ import net.coderbot.iris.gbuffer_overrides.state.RenderTargetStateListener; import net.coderbot.iris.gl.blending.AlphaTestOverride; import net.coderbot.iris.gl.blending.BlendModeOverride; import net.coderbot.iris.gl.blending.BufferBlendOverride; +import net.coderbot.iris.gl.buffer.ShaderStorageBufferHolder; +import net.coderbot.iris.gl.buffer.ShaderStorageInfo; import net.coderbot.iris.gl.framebuffer.GlFramebuffer; +import net.coderbot.iris.gl.image.GlImage; +import net.coderbot.iris.gl.image.ImageInformation; import net.coderbot.iris.gl.program.ComputeProgram; import net.coderbot.iris.gl.program.Program; import net.coderbot.iris.gl.program.ProgramBuilder; import net.coderbot.iris.gl.program.ProgramImages; import net.coderbot.iris.gl.program.ProgramSamplers; +import net.coderbot.iris.gl.state.FogMode; import net.coderbot.iris.gl.texture.DepthBufferFormat; -import net.coderbot.iris.layer.GbufferPrograms; +import net.coderbot.iris.gl.texture.TextureType; +import net.coderbot.iris.helpers.Tri; import net.coderbot.iris.pipeline.transform.PatchShaderType; import net.coderbot.iris.pipeline.transform.TransformPatcher; import net.coderbot.iris.postprocess.BufferFlipper; @@ -48,7 +52,6 @@ import net.coderbot.iris.samplers.IrisImages; import net.coderbot.iris.samplers.IrisSamplers; import net.coderbot.iris.shaderpack.CloudSetting; import net.coderbot.iris.shaderpack.ComputeSource; -import net.coderbot.iris.shaderpack.IdMap; import net.coderbot.iris.shaderpack.OptionalBoolean; import net.coderbot.iris.shaderpack.PackDirectives; import net.coderbot.iris.shaderpack.PackShadowDirectives; @@ -58,6 +61,7 @@ import net.coderbot.iris.shaderpack.ProgramSet; import net.coderbot.iris.shaderpack.ProgramSource; import net.coderbot.iris.shaderpack.loading.ProgramId; import net.coderbot.iris.shaderpack.texture.TextureStage; +import net.coderbot.iris.shadows.ShadowCompositeRenderer; import net.coderbot.iris.shadows.ShadowRenderTargets; import net.coderbot.iris.texture.format.TextureFormat; import net.coderbot.iris.texture.format.TextureFormatLoader; @@ -121,6 +125,8 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R @Nullable private final ShadowRenderer shadowRenderer; + @Nullable + private final ShadowCompositeRenderer shadowCompositeRenderer; private final CustomUniforms customUniforms; @@ -176,6 +182,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R private int currentNormalTexture; private int currentSpecularTexture; private PackDirectives packDirectives; + private final Set activeFeatures; public DeferredWorldRenderingPipeline(ProgramSet programs) { Objects.requireNonNull(programs); @@ -217,6 +224,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R this.updateNotifier = new FrameUpdateNotifier(); this.packDirectives = programs.getPackDirectives(); + this.activeFeatures = programs.getPack().getActiveFeatures(); final Framebuffer main = Minecraft.getMinecraft().getFramebuffer(); @@ -430,9 +438,17 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R this.shadowClearPasses = ClearPassCreator.createShadowClearPasses(shadowRenderTargets, false, shadowDirectives); this.shadowClearPassesFull = ClearPassCreator.createShadowClearPasses(shadowRenderTargets, true, shadowDirectives); + this.shadowCompositeRenderer = new ShadowCompositeRenderer(this, programs.getPackDirectives(), + programs.getShadowComposite(), programs.getShadowCompCompute(), this.shadowRenderTargets, + ssboHolder, + customTextureManager.getNoiseTexture(), updateNotifier, + customTextureManager.getCustomTextureIdMap(TextureStage.SHADOWCOMP), + customImages, programs.getPackDirectives().getExplicitFlips("shadowcomp_pre"), + customTextureManager.getIrisCustomTextures(), customUniforms); + if (programs.getPackDirectives().getShadowDirectives().isShadowEnabled().orElse(true)) { this.shadowRenderer = new ShadowRenderer(programs.getShadow().orElse(null), - programs.getPackDirectives(), shadowRenderTargets); + programs.getPackDirectives(), shadowRenderTargets, shadowCompositeRenderer); Program shadowProgram = table.match(RenderCondition.SHADOW, new InputAvailability(true, true)).getProgram(); shadowRenderer.setUsesImages(shadowProgram != null && shadowProgram.getActiveImages() > 0); } else { @@ -441,6 +457,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R } else { this.shadowClearPasses = ImmutableList.of(); this.shadowClearPassesFull = ImmutableList.of(); + this.shadowCompositeRenderer = null; this.shadowRenderer = null; } @@ -606,6 +623,16 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R return sunPathRotation; } + @Override + public boolean hasFeature(FeatureFlags flag) { + return activeFeatures.contains(flag); + } + + @Override + public Object2ObjectMap, String> getTextureMap() { + return packDirectives.getTextureMap(); + } + private RenderCondition getCondition(WorldRenderingPhase phase) { if (isRenderingShadow) { return RenderCondition.SHADOW; @@ -722,7 +749,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R private Pass createPassInner(ProgramBuilder builder, ProgramDirectives programDirectives, InputAvailability availability, boolean shadow, ProgramId id) { - CommonUniforms.addDynamicUniforms(builder); + CommonUniforms.addDynamicUniforms(builder, FogMode.PER_VERTEX); this.customUniforms.assignTo(builder); Supplier> flipped; @@ -868,10 +895,10 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R } if (shadowViewport) { - GL11.glViewport(0, 0, shadowMapResolution, shadowMapResolution); + GLStateManager.glViewport(0, 0, shadowMapResolution, shadowMapResolution); } else { final Framebuffer main = Minecraft.getMinecraft().getFramebuffer(); - GL11.glViewport(0, 0, main.framebufferWidth, main.framebufferHeight); + GLStateManager.glViewport(0, 0, main.framebufferWidth, main.framebufferHeight); } if (program != null) { @@ -946,6 +973,11 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R } } + // Destroy shadow composite renderer + if (shadowCompositeRenderer != null) { + shadowCompositeRenderer.destroy(); + } + horizonRenderer.destroy(); // Make sure that any custom framebuffers are not bound before destroying render targets @@ -1109,13 +1141,15 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R ProgramBuilder builder; try { - builder = ProgramBuilder.beginCompute(source.getName(), source.getSource().orElse(null), IrisSamplers.WORLD_RESERVED_TEXTURE_UNITS); + String transformed = TransformPatcher.patchCompute(source.getName(), source.getSource().orElse(null), TextureStage.GBUFFERS_AND_SHADOW, getTextureMap()); + PatchedShaderPrinter.debugPatchedShaders(source.getName() + "_compute", null, null, null, transformed); + builder = ProgramBuilder.beginCompute(source.getName(), transformed, IrisSamplers.WORLD_RESERVED_TEXTURE_UNITS); } catch (RuntimeException e) { // TODO: Better error handling throw new RuntimeException("Shader compilation failed!", e); } - CommonUniforms.addDynamicUniforms(builder); + CommonUniforms.addDynamicUniforms(builder, FogMode.PER_VERTEX); this.customUniforms.assignTo(builder); Supplier> flipped; diff --git a/src/main/java/net/coderbot/iris/pipeline/FixedFunctionWorldRenderingPipeline.java b/src/main/java/net/coderbot/iris/pipeline/FixedFunctionWorldRenderingPipeline.java index df1ea3afa..008b27b76 100644 --- a/src/main/java/net/coderbot/iris/pipeline/FixedFunctionWorldRenderingPipeline.java +++ b/src/main/java/net/coderbot/iris/pipeline/FixedFunctionWorldRenderingPipeline.java @@ -1,13 +1,19 @@ package net.coderbot.iris.pipeline; import com.gtnewhorizons.angelica.compat.mojang.Camera; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; import net.coderbot.iris.block_rendering.BlockRenderingSettings; import net.coderbot.iris.celeritas.CeleritasTerrainPipeline; import net.coderbot.iris.compat.dh.DHCompat; +import net.coderbot.iris.features.FeatureFlags; import net.coderbot.iris.gbuffer_overrides.matching.InputAvailability; import net.coderbot.iris.gbuffer_overrides.matching.SpecialCondition; import net.coderbot.iris.gbuffer_overrides.state.RenderTargetStateListener; +import net.coderbot.iris.gl.texture.TextureType; +import net.coderbot.iris.helpers.Tri; import net.coderbot.iris.shaderpack.CloudSetting; +import net.coderbot.iris.shaderpack.texture.TextureStage; import net.coderbot.iris.uniforms.FrameUpdateNotifier; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.EntityRenderer; @@ -186,4 +192,14 @@ public class FixedFunctionWorldRenderingPipeline implements WorldRenderingPipeli // No sun tilt return 0; } + + @Override + public boolean hasFeature(FeatureFlags flag) { + return false; + } + + @Override + public Object2ObjectMap, String> getTextureMap() { + return Object2ObjectMaps.emptyMap(); + } } diff --git a/src/main/java/net/coderbot/iris/pipeline/PatchedShaderPrinter.java b/src/main/java/net/coderbot/iris/pipeline/PatchedShaderPrinter.java index ee8a4ff89..cae503e8e 100644 --- a/src/main/java/net/coderbot/iris/pipeline/PatchedShaderPrinter.java +++ b/src/main/java/net/coderbot/iris/pipeline/PatchedShaderPrinter.java @@ -27,6 +27,10 @@ public class PatchedShaderPrinter { } public static void debugPatchedShaders(String name, String vertex, String geometry, String fragment) { + debugPatchedShaders(name, vertex, geometry, fragment, null); + } + + public static void debugPatchedShaders(String name, String vertex, String geometry, String fragment, String compute) { if (prettyPrintShaders) { final Path debugOutDir = Minecraft.getMinecraft().mcDataDir.toPath().resolve("patched_shaders"); if (!outputLocationCleared) { @@ -62,6 +66,9 @@ public class PatchedShaderPrinter { if (fragment != null) { Files.write(debugOutDir.resolve(prefix + name + ".fsh"), fragment.getBytes(StandardCharsets.UTF_8)); } + if (compute != null) { + Files.write(debugOutDir.resolve(prefix + name + ".csh"), compute.getBytes(StandardCharsets.UTF_8)); + } } catch (IOException e) { Iris.logger.warn("Failed to write debug patched shader source", e); } diff --git a/src/main/java/net/coderbot/iris/pipeline/ShadowRenderer.java b/src/main/java/net/coderbot/iris/pipeline/ShadowRenderer.java index c097954c9..4c6c6b72d 100644 --- a/src/main/java/net/coderbot/iris/pipeline/ShadowRenderer.java +++ b/src/main/java/net/coderbot/iris/pipeline/ShadowRenderer.java @@ -23,6 +23,7 @@ import net.coderbot.iris.shaderpack.PackShadowDirectives; import net.coderbot.iris.shaderpack.ProgramSource; import net.coderbot.iris.shadow.ShadowMatrices; import net.coderbot.iris.shadows.CullingDataCache; +import net.coderbot.iris.shadows.ShadowCompositeRenderer; import net.coderbot.iris.shadows.ShadowRenderTargets; import net.coderbot.iris.shadows.frustum.BoxCuller; import net.coderbot.iris.shadows.frustum.CullEverythingFrustum; @@ -79,6 +80,7 @@ public class ShadowRenderer { private final Float fov; private final ShadowRenderTargets targets; private final ShadowCullState packCullingState; + private final ShadowCompositeRenderer compositeRenderer; private boolean packHasVoxelization; private final boolean shouldRenderTerrain; private final boolean shouldRenderTranslucent; @@ -108,7 +110,7 @@ public class ShadowRenderer { private double lastAdvancedBoxCullerDistance = -1; private double lastTileEntityCullerDistance = -1; - public ShadowRenderer(ProgramSource shadow, PackDirectives directives, ShadowRenderTargets shadowRenderTargets) { + public ShadowRenderer(ProgramSource shadow, PackDirectives directives, ShadowRenderTargets shadowRenderTargets, ShadowCompositeRenderer compositeRenderer) { this.profiler = Minecraft.getMinecraft().mcProfiler; @@ -125,6 +127,8 @@ public class ShadowRenderer { this.shouldRenderPlayer = shadowDirectives.shouldRenderPlayer(); this.shouldRenderBlockEntities = shadowDirectives.shouldRenderBlockEntities(); + this.compositeRenderer = compositeRenderer; + debugStringOverall = "half plane = " + halfPlaneLength + " meters @ " + resolution + "x" + resolution; this.terrainFrustumHolder = new FrustumHolder(); @@ -382,7 +386,7 @@ public class ShadowRenderer { private void setupGlState(Matrix4f projMatrix) { // Bind shadow framebuffer and set viewport to shadow resolution targets.getDepthSourceFb().bind(); - GL11.glViewport(0, 0, resolution, resolution); + GLStateManager.glViewport(0, 0, resolution, resolution); // Set up our projection matrix and load it into the legacy matrix stack RenderSystem.setupProjectionMatrix(projMatrix); @@ -407,7 +411,7 @@ public class ShadowRenderer { // Restore main framebuffer and viewport Minecraft mc = Minecraft.getMinecraft(); mc.getFramebuffer().bindFramebuffer(false); - GL11.glViewport(0, 0, mc.displayWidth, mc.displayHeight); + GLStateManager.glViewport(0, 0, mc.displayWidth, mc.displayHeight); } private void copyPreTranslucentDepth() { @@ -675,7 +679,7 @@ public class ShadowRenderer { } // Reset viewport in case terrain rendering changed it - GL11.glViewport(0, 0, resolution, resolution); + GLStateManager.glViewport(0, 0, resolution, resolution); profiler.endStartSection("entities"); @@ -750,6 +754,10 @@ public class ShadowRenderer { ((CullingDataCache) levelRenderer).restoreState(); } + profiler.endStartSection("shadowcomp"); + + if (compositeRenderer != null) compositeRenderer.renderAll(); + ACTIVE = false; CURRENT_TARGETS = null; profiler.endSection(); diff --git a/src/main/java/net/coderbot/iris/pipeline/WorldRenderingPipeline.java b/src/main/java/net/coderbot/iris/pipeline/WorldRenderingPipeline.java index 51fa041c3..6957d9214 100644 --- a/src/main/java/net/coderbot/iris/pipeline/WorldRenderingPipeline.java +++ b/src/main/java/net/coderbot/iris/pipeline/WorldRenderingPipeline.java @@ -1,12 +1,17 @@ package net.coderbot.iris.pipeline; import com.gtnewhorizons.angelica.compat.mojang.Camera; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import net.coderbot.iris.compat.dh.DHCompat; +import net.coderbot.iris.features.FeatureFlags; import net.coderbot.iris.gbuffer_overrides.matching.InputAvailability; import net.coderbot.iris.gbuffer_overrides.matching.SpecialCondition; import net.coderbot.iris.gbuffer_overrides.state.RenderTargetStateListener; import net.coderbot.iris.celeritas.CeleritasTerrainPipeline; +import net.coderbot.iris.gl.texture.TextureType; +import net.coderbot.iris.helpers.Tri; import net.coderbot.iris.shaderpack.CloudSetting; +import net.coderbot.iris.shaderpack.texture.TextureStage; import net.coderbot.iris.uniforms.FrameUpdateNotifier; import net.minecraft.client.renderer.EntityRenderer; @@ -54,4 +59,7 @@ public interface WorldRenderingPipeline { boolean allowConcurrentCompute(); float getSunPathRotation(); + + boolean hasFeature(FeatureFlags flag); + Object2ObjectMap, String> getTextureMap(); } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/AttributeTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/AttributeTransformer.java index c93d2482b..73dc3ba66 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/AttributeTransformer.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/AttributeTransformer.java @@ -14,8 +14,12 @@ import java.util.Map; class AttributeTransformer { public static void transform(Transformer transformer, AttributeParameters parameters, String profile, int version) { boolean isCore = profile.equals("core") || (version > 140 && !profile.equals("compatibility")); + + // Common patches (compatibility profile) + CommonTransformer.transform(transformer, parameters, isCore); + if (isCore) { - if (parameters.type == PatchShaderType.VERTEX) { + if (parameters.type == ShaderType.VERTEX) { throw new IllegalStateException("Vertex shaders must be in the compatibility profile to run properly!"); } return; @@ -28,66 +32,49 @@ class AttributeTransformer { transformer.rename("gl_MultiTexCoord2", "gl_MultiTexCoord1"); } - Map texCoordReplacements = new HashMap<>(); - if (!parameters.inputs.lightmap) { - texCoordReplacements.put("gl_MultiTexCoord1", "vec4(240.0, 240.0, 0.0, 1.0)"); - texCoordReplacements.put("gl_MultiTexCoord2", "vec4(240.0, 240.0, 0.0, 1.0)"); - } - if (!parameters.inputs.texture) { - texCoordReplacements.put("gl_MultiTexCoord0", "vec4(240.0, 240.0, 0.0, 1.0)"); - } - texCoordReplacements.forEach(transformer::replaceExpression); + Map texCoordReplacements = new HashMap<>(); + if (!parameters.inputs.lightmap) { + texCoordReplacements.put("gl_MultiTexCoord1", "vec4(240.0, 240.0, 0.0, 1.0)"); + texCoordReplacements.put("gl_MultiTexCoord2", "vec4(240.0, 240.0, 0.0, 1.0)"); + } + if (!parameters.inputs.texture) { + texCoordReplacements.put("gl_MultiTexCoord0", "vec4(240.0, 240.0, 0.0, 1.0)"); + } + texCoordReplacements.forEach(transformer::replaceExpression); patchTextureMatrices(transformer, parameters.inputs.lightmap); - if (parameters.type.glShaderType == ShaderType.VERTEX - && transformer.hasVariable("gl_MultiTexCoord3") - && !transformer.hasVariable("mc_midTexCoord")) { - // TODO: proper type conversion - // gl_MultiTexCoord3 is a super legacy alias of mc_midTexCoord. We don't do this - // replacement if we think mc_midTexCoord could be defined just we can't handle - // an existing declaration robustly. But basically the proper way to do this is - // to define mc_midTexCoord only if it's not defined, and if it is defined, - // figure out its type, then replace all occurrences of gl_MultiTexCoord3 with - // the correct conversion from mc_midTexCoord's declared type to vec4. - transformer.rename("gl_MultiTexCoord3", "mc_midTexCoord"); + if (parameters.type == ShaderType.VERTEX && transformer.hasVariable("gl_MultiTexCoord3") && !transformer.hasVariable("mc_midTexCoord")) { + transformer.rename("gl_MultiTexCoord3", "mc_midTexCoord"); transformer.injectVariable("attribute vec4 mc_midTexCoord;"); } } private static void patchTextureMatrices(Transformer transformer, boolean hasLightmap) { - transformer.rename("gl_TextureMatrix", "iris_TextureMatrix"); + transformer.rename("gl_TextureMatrix", "iris_TextureMatrix"); - // TODO: These were originally marked const, but that breaks things - // If these are marked const, then using them below in the iris_LightmapTextureMatrix creation - // breaks with them being undefined. I suppose the const variables cause them to get defined later than otherwise? - // Similarly, if you make them a const, then iris_ONE_OVER_32 breaks because it references iris_ONE_OVER_256. - // Not sure if it really matters if these are marked const or not. Alternatively they can be marked const - // and the values hardcoded within the places that use them here, that seems to work fine, but this probably - // stayed closer to the original way it worked. - transformer.injectVariable("float iris_ONE_OVER_256 = 0.00390625;"); - transformer.injectVariable("float iris_ONE_OVER_32 = iris_ONE_OVER_256 * 8;"); + transformer.injectVariable("float iris_ONE_OVER_256 = 0.00390625;"); + transformer.injectVariable("float iris_ONE_OVER_32 = iris_ONE_OVER_256 * 8;"); - if (hasLightmap) { - transformer.injectVariable("mat4 iris_LightmapTextureMatrix = gl_TextureMatrix[1];"); - } else { - transformer.injectVariable("mat4 iris_LightmapTextureMatrix =" + - "mat4(iris_ONE_OVER_256, 0.0, 0.0, 0.0," + - " 0.0, iris_ONE_OVER_256, 0.0, 0.0," + - " 0.0, 0.0, iris_ONE_OVER_256, 0.0," + - " iris_ONE_OVER_32, iris_ONE_OVER_32, iris_ONE_OVER_32, iris_ONE_OVER_256);"); - } + if (hasLightmap) { + transformer.injectVariable("mat4 iris_LightmapTextureMatrix = gl_TextureMatrix[1];"); + } else { + transformer.injectVariable("mat4 iris_LightmapTextureMatrix =" + + "mat4(iris_ONE_OVER_256, 0.0, 0.0, 0.0," + + " 0.0, iris_ONE_OVER_256, 0.0, 0.0," + + " 0.0, 0.0, iris_ONE_OVER_256, 0.0," + + " iris_ONE_OVER_32, iris_ONE_OVER_32, iris_ONE_OVER_32, iris_ONE_OVER_256);"); + } - // column major - transformer.injectVariable("mat4 iris_TextureMatrix[8] = mat4[8](" + - "gl_TextureMatrix[0]," + - "iris_LightmapTextureMatrix," + - "mat4(1.0)," + - "mat4(1.0)," + - "mat4(1.0)," + - "mat4(1.0)," + - "mat4(1.0)," + - "mat4(1.0)" + - ");"); + transformer.injectVariable("mat4 iris_TextureMatrix[8] = mat4[8](" + + "gl_TextureMatrix[0]," + + "iris_LightmapTextureMatrix," + + "mat4(1.0)," + + "mat4(1.0)," + + "mat4(1.0)," + + "mat4(1.0)," + + "mat4(1.0)," + + "mat4(1.0)" + + ");"); } } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/CeleritasTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/CeleritasTransformer.java index 26510bfca..72e742cd6 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/CeleritasTransformer.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/CeleritasTransformer.java @@ -1,18 +1,17 @@ package net.coderbot.iris.pipeline.transform; +import net.coderbot.iris.gl.shader.ShaderType; import net.coderbot.iris.pipeline.transform.parameter.Parameters; import org.taumc.glsl.Transformer; import java.util.HashMap; import java.util.Map; -import static net.coderbot.iris.pipeline.transform.PatchShaderType.FRAGMENT; -import static net.coderbot.iris.pipeline.transform.PatchShaderType.VERTEX; - class CeleritasTransformer { public static void transform(Transformer transformer, Parameters parameters) { + CommonTransformer.transform(transformer, parameters, false); + switch (parameters.type) { - // For Celeritas patching, treat fragment and geometry the same case FRAGMENT: case GEOMETRY: transformFragment(transformer, parameters); @@ -26,7 +25,7 @@ class CeleritasTransformer { } public static void transformVertex(Transformer transformer, Parameters parameters) { - transformer.injectVariable("uniform vec3 u_RegionOffset;"); // Per-region offset from setRegionOffset() + transformer.injectVariable("uniform vec3 u_RegionOffset;"); transformer.injectVariable("vec4 iris_LightTexCoord;"); transformer.injectFunction("vec4 iris_ftransform() { return gl_ModelViewProjectionMatrix * _celeritas_getVertexPosition(); }"); transformer.injectFunction( @@ -57,7 +56,6 @@ class CeleritasTransformer { } public static void transformFragment(Transformer transformer, Parameters parameters) { - // interestingly there is nothing that isn't shared transformShared(transformer, parameters); } @@ -82,31 +80,5 @@ class CeleritasTransformer { sharedReplacements.put("gl_TextureMatrix[1]", "iris_LightmapTextureMatrix"); sharedReplacements.put("gl_ModelViewProjectionMatrix", "(iris_ProjectionMatrix * iris_ModelViewMatrix)"); sharedReplacements.forEach(transformer::replaceExpression); - - transformFog(transformer, parameters); - } - - private static void transformFog(Transformer transformer, Parameters parameters) { - transformer.injectVariable("uniform float iris_FogDensity;"); - transformer.injectVariable("uniform float iris_FogStart;"); - transformer.injectVariable("uniform float iris_FogEnd;"); - transformer.injectVariable("uniform vec4 iris_FogColor;"); - - transformer.injectFunction("struct iris_FogParameters { vec4 color; float density; float start; float end; float scale; };"); - transformer.injectFunction( - "iris_FogParameters iris_Fog = iris_FogParameters(iris_FogColor, iris_FogDensity, " + - "iris_FogStart, iris_FogEnd, 1.0 / (iris_FogEnd - iris_FogStart));"); - - final Map fogRenames = new HashMap<>(); - fogRenames.put("gl_Fog", "iris_Fog"); - fogRenames.put("gl_FogFragCoord", "iris_FogFragCoord"); - transformer.rename(fogRenames); - - if (parameters.type == VERTEX) { - transformer.injectVariable("out float iris_FogFragCoord;"); - transformer.prependMain("iris_FogFragCoord = 0.0;"); - } else if (parameters.type == FRAGMENT) { - transformer.injectVariable("in float iris_FogFragCoord;"); - } } } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/CommonTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/CommonTransformer.java new file mode 100644 index 000000000..e6faffaaa --- /dev/null +++ b/src/main/java/net/coderbot/iris/pipeline/transform/CommonTransformer.java @@ -0,0 +1,73 @@ +package net.coderbot.iris.pipeline.transform; + +import net.coderbot.iris.gl.blending.AlphaTest; +import net.coderbot.iris.gl.shader.ShaderType; +import net.coderbot.iris.pipeline.transform.parameter.Parameters; +import org.taumc.glsl.Transformer; + +import java.util.Map; + +public class CommonTransformer { + + private static final Map COMMON_TEXTURE_RENAMES = Map.ofEntries( + Map.entry("texture2D", "texture"), + Map.entry("texture3D", "texture"), + Map.entry("texture2DLod", "textureLod"), + Map.entry("texture3DLod", "textureLod"), + Map.entry("texture2DProj", "textureProj"), + Map.entry("texture3DProj", "textureProj"), + Map.entry("texture2DGrad", "textureGrad"), + Map.entry("texture2DGradARB", "textureGrad"), + Map.entry("texture3DGrad", "textureGrad"), + Map.entry("texelFetch2D", "texelFetch"), + Map.entry("texelFetch3D", "texelFetch"), + Map.entry("textureSize2D", "textureSize") + ); + + public static void transform(Transformer root, Parameters parameters, boolean core) { + root.rename("gl_FogFragCoord", "iris_FogFragCoord"); + if (parameters.type == ShaderType.VERTEX) { + root.injectVariable("out float iris_FogFragCoord;"); + root.prependMain("iris_FogFragCoord = 0.0f;"); + } else if (parameters.type == ShaderType.FRAGMENT) { + root.injectVariable("in float iris_FogFragCoord;"); + } + + if (parameters.type == ShaderType.VERTEX) { + root.injectVariable("vec4 iris_FrontColor;"); + root.rename("gl_FrontColor", "iris_FrontColor"); + } + + if (parameters.type == ShaderType.FRAGMENT) { + if (root.containsCall("gl_FragColor")) { + root.replaceExpression("gl_FragColor", "gl_FragData[0]"); + } + + // Note: In compatibility profile, gl_FragData is a built-in array. + if (!core && parameters.getAlphaTest() != AlphaTest.ALWAYS) { + root.injectVariable("uniform float iris_currentAlphaTest;"); + root.appendMain(parameters.getAlphaTest().toExpression("gl_FragData[0].a", "iris_currentAlphaTest", "")); + } + } + + if (root.containsCall("texture") && root.hasVariable("texture")) { + root.rename("texture", "gtexture"); + } + + if (root.containsCall("gcolor") && root.hasVariable("gcolor")) { + root.rename("gcolor", "gtexture"); + } + + root.rename("gl_Fog", "iris_Fog"); + root.injectVariable("uniform float iris_FogDensity;"); + root.injectVariable("uniform float iris_FogStart;"); + root.injectVariable("uniform float iris_FogEnd;"); + root.injectVariable("uniform vec4 iris_FogColor;"); + root.injectFunction("struct iris_FogParameters {vec4 color;float density;float start;float end;float scale;};"); + root.injectFunction("iris_FogParameters iris_Fog = iris_FogParameters(iris_FogColor, iris_FogDensity, iris_FogStart, iris_FogEnd, 1.0f / (iris_FogEnd - iris_FogStart));"); + + root.renameFunctionCall(COMMON_TEXTURE_RENAMES); + root.renameAndWrapShadow("shadow2D", "texture"); + root.renameAndWrapShadow("shadow2DLod", "textureLod"); + } +} diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/CompatibilityTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/CompatibilityTransformer.java index facd34bbc..228196101 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/CompatibilityTransformer.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/CompatibilityTransformer.java @@ -15,8 +15,7 @@ public class CompatibilityTransformer { public static void transformEach(Transformer transformer, Parameters parameters) { - if (parameters.type == PatchShaderType.VERTEX) { - ; + if (parameters.type == ShaderType.VERTEX) { // TODO: sildur's jankness // This is a hacky patch for sildur's shaders that changes the way it does it's waving water to make it work better? // Why is this the GLSL transformation code in Iris, tell sildur to fix it and remove this? diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/CompositeDepthTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/CompositeDepthTransformer.java index 1fb6aa685..f9aa4db94 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/CompositeDepthTransformer.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/CompositeDepthTransformer.java @@ -1,15 +1,17 @@ package net.coderbot.iris.pipeline.transform; +import net.coderbot.iris.pipeline.transform.parameter.Parameters; import org.taumc.glsl.Transformer; class CompositeDepthTransformer { - public static void transform(Transformer transformer) { - // replace original declaration - int type = transformer.findType("centerDepthSmooth"); - if (type != 0) { - transformer.injectVariable("uniform sampler2D iris_centerDepthSmooth;"); - transformer.replaceExpression("centerDepthSmooth", "texture2D(iris_centerDepthSmooth, vec2(0.5)).r"); - } + public static void transform(Transformer transformer, Parameters parameters) { + CommonTransformer.transform(transformer, parameters, false); + + int type = transformer.findType("centerDepthSmooth"); + if (type != 0) { + transformer.injectVariable("uniform sampler2D iris_centerDepthSmooth;"); + transformer.replaceExpression("centerDepthSmooth", "texture2D(iris_centerDepthSmooth, vec2(0.5)).r"); + } } } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/ComputeTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/ComputeTransformer.java new file mode 100644 index 000000000..2e3d08804 --- /dev/null +++ b/src/main/java/net/coderbot/iris/pipeline/transform/ComputeTransformer.java @@ -0,0 +1,11 @@ +package net.coderbot.iris.pipeline.transform; + +import net.coderbot.iris.pipeline.transform.parameter.Parameters; +import org.taumc.glsl.Transformer; + +public class ComputeTransformer { + + public static void transform(Transformer transformer, Parameters parameters) { + CommonTransformer.transform(transformer, parameters, true); + } +} diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/Patch.java b/src/main/java/net/coderbot/iris/pipeline/transform/Patch.java index 9bf29037a..5158dd7cd 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/Patch.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/Patch.java @@ -3,5 +3,6 @@ package net.coderbot.iris.pipeline.transform; public enum Patch { ATTRIBUTES, CELERITAS_TERRAIN, - COMPOSITE + COMPOSITE, + COMPUTE } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/PatchShaderType.java b/src/main/java/net/coderbot/iris/pipeline/transform/PatchShaderType.java index 729f18188..7137192fe 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/PatchShaderType.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/PatchShaderType.java @@ -5,7 +5,8 @@ import net.coderbot.iris.gl.shader.ShaderType; public enum PatchShaderType { VERTEX(ShaderType.VERTEX), GEOMETRY(ShaderType.GEOMETRY), - FRAGMENT(ShaderType.FRAGMENT); + FRAGMENT(ShaderType.FRAGMENT), + COMPUTE(ShaderType.COMPUTE); public static final PatchShaderType[] VALUES = values(); @@ -20,7 +21,7 @@ public enum PatchShaderType { case VERTEX -> new PatchShaderType[] { VERTEX }; case GEOMETRY -> new PatchShaderType[] { GEOMETRY }; case FRAGMENT -> new PatchShaderType[] { FRAGMENT }; - default -> throw new IllegalArgumentException("Unknown shader type: " + glShaderType); + case COMPUTE -> new PatchShaderType[] { COMPUTE }; }; } } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/ShaderTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/ShaderTransformer.java index cd76d57dc..29dff722a 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/ShaderTransformer.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/ShaderTransformer.java @@ -195,6 +195,117 @@ public class ShaderTransformer { } } + public static

Map transformCompute(String compute, P parameters) { + if (compute == null) { + return null; + } else { + Map result; + + var patchType = parameters.patch; + + EnumMap inputs = new EnumMap<>(PatchShaderType.class); + inputs.put(PatchShaderType.COMPUTE, compute); + + var key = new TransformKey<>(patchType, inputs, parameters); + + synchronized (shaderTransformationCache) { + result = shaderTransformationCache.getAndMoveToLast(key); + } + if (result == null || !useCache) { + result = transformComputeInternal(compute, patchType, parameters); + // Clear this, we don't want whatever random type was last transformed being considered for the key + parameters.type = null; + synchronized (shaderTransformationCache) { + // Double-check in case another thread added it while we were transforming + Map existing = shaderTransformationCache.getAndMoveToLast(key); + if (existing != null) { + return existing; + } + if (shaderTransformationCache.size() >= CACHE_SIZE) { + shaderTransformationCache.removeFirst(); + } + shaderTransformationCache.putAndMoveToLast(key, result); + } + } + + return result; + } + } + + private static

Map transformComputeInternal(String compute, Patch patchType, P parameters) { + EnumMap result = new EnumMap<>(PatchShaderType.class); + + Stopwatch watch = Stopwatch.createStarted(); + + parameters.type = ShaderType.COMPUTE; + + Matcher matcher = versionPattern.matcher(compute); + if (!matcher.find()) { + throw new IllegalArgumentException("No #version directive found in compute shader source code!"); + } + + String versionString = matcher.group(1); + int versionInt = Integer.parseInt(versionString); + + // Check if shader uses features requiring a higher GLSL version + int requiredVersion = getRequiredVersion(compute, versionInt); + if (requiredVersion > versionInt) { + Iris.logger.debug("Compute shader requires GLSL {} for detected features, hoisting from {}", requiredVersion, versionInt); + versionInt = requiredVersion; + versionString = String.valueOf(versionInt); + } + + // Compute shaders always use core profile, minimum 330 + if (versionInt < 330) { + versionString = "330"; + versionInt = 330; + } + String profileString = "#version " + versionString + " core\n"; + + // Rename reserved words + String input = compute; + for (String reservedWord : fullReservedWords) { + String newName = "iris_renamed_" + reservedWord; + input = input.replaceAll("\\b" + reservedWord + "\\b", newName); + } + for (int version : versionedReservedWords.keySet()) { + if (versionInt < version) { + for (String reservedWord : versionedReservedWords.get(version)) { + String newName = "iris_renamed_" + reservedWord; + input = input.replaceAll("\\b" + reservedWord + "\\b", newName); + } + } + } + + var parsedShader = ShaderParser.parseShader(input); + var transformer = new Transformer(parsedShader.full()); + + doTransform(transformer, patchType, parameters, "core", versionInt); + + // Extract extensions + var extensions = versionPattern.matcher(getFormattedShader(parsedShader.pre(), "")).replaceFirst("").trim(); + String header = profileString + (extensions.isEmpty() ? "" : "\n" + extensions); + + final String finalHeader = header; + final StringBuilder formattedShaderBuilder = new StringBuilder(); + + transformer.mutateTree(tree -> { + formattedShaderBuilder.append(getFormattedShader(tree, finalHeader)); + }); + + String formattedShader = formattedShaderBuilder.toString(); + + // Restore identifiers that were temporarily renamed + formattedShader = formattedShader.replace("iris_renamed_texture", "texture"); + formattedShader = formattedShader.replace("iris_renamed_sample", "sample"); + + result.put(PatchShaderType.COMPUTE, formattedShader); + + watch.stop(); + Iris.logger.info("[Load #{}] Transformed compute shader for {} in {}", Iris.getShaderPackLoadId(), patchType.name(), watch); + return result; + } + private static

Map transformInternal(EnumMap inputs, Patch patchType, P parameters) { EnumMap result = new EnumMap<>(PatchShaderType.class); EnumMap types = new EnumMap<>(PatchShaderType.class); @@ -205,7 +316,7 @@ public class ShaderTransformer { Stopwatch watch = Stopwatch.createStarted(); for (PatchShaderType type : PatchShaderType.VALUES) { - parameters.type = type; + parameters.type = type.glShaderType; if (inputs.get(type) == null) { continue; } @@ -352,11 +463,14 @@ public class ShaderTransformer { applyIntelHd4000Workaround(transformer); break; case COMPOSITE: - CompositeDepthTransformer.transform(transformer); + CompositeDepthTransformer.transform(transformer, parameters); break; case ATTRIBUTES: AttributeTransformer.transform(transformer, (AttributeParameters) parameters, profile, versionInt); break; + case COMPUTE: + ComputeTransformer.transform(transformer, parameters); + break; default: throw new IllegalStateException("Unknown patch type: " + patchType.name()); } @@ -375,7 +489,7 @@ public class ShaderTransformer { } public static void patchMultiTexCoord3(Transformer transformer, Parameters parameters) { - if (parameters.type.glShaderType == ShaderType.VERTEX && transformer.hasVariable("gl_MultiTexCoord3") && !transformer.hasVariable("mc_midTexCoord")) { + if (parameters.type == ShaderType.VERTEX && transformer.hasVariable("gl_MultiTexCoord3") && !transformer.hasVariable("mc_midTexCoord")) { transformer.rename("gl_MultiTexCoord3", "mc_midTexCoord"); transformer.injectVariable("attribute vec4 mc_midTexCoord;"); } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/TransformPatcher.java b/src/main/java/net/coderbot/iris/pipeline/transform/TransformPatcher.java index 55fa3a38f..05cc26412 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/TransformPatcher.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/TransformPatcher.java @@ -1,8 +1,15 @@ package net.coderbot.iris.pipeline.transform; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import net.coderbot.iris.gbuffer_overrides.matching.InputAvailability; +import net.coderbot.iris.gl.texture.TextureType; +import net.coderbot.iris.helpers.Tri; import net.coderbot.iris.pipeline.transform.parameter.AttributeParameters; +import net.coderbot.iris.pipeline.transform.parameter.CeleritasTerrainParameters; +import net.coderbot.iris.pipeline.transform.parameter.ComputeParameters; import net.coderbot.iris.pipeline.transform.parameter.Parameters; +import net.coderbot.iris.pipeline.transform.parameter.TextureStageParameters; +import net.coderbot.iris.shaderpack.texture.TextureStage; import java.util.LinkedHashMap; import java.util.Map; @@ -114,11 +121,19 @@ public class TransformPatcher { } public static Map patchCeleritasTerrain(String vertex, String geometry, String fragment) { - return transform(vertex, geometry, fragment, new Parameters(Patch.CELERITAS_TERRAIN)); + return transform(vertex, geometry, fragment, new CeleritasTerrainParameters(Patch.CELERITAS_TERRAIN)); } public static Map patchComposite(String vertex, String geometry, String fragment) { - return transform(vertex, geometry, fragment, new Parameters(Patch.COMPOSITE)); + return transform(vertex, geometry, fragment, new TextureStageParameters(Patch.COMPOSITE, TextureStage.COMPOSITE_AND_FINAL, null)); + } + + public static String patchCompute(String name, String compute, TextureStage stage, Object2ObjectMap, String> textureMap) { + if (compute == null) { + return null; + } + Map result = ShaderTransformer.transformCompute(compute, new ComputeParameters(Patch.COMPUTE, stage, textureMap)); + return result != null ? result.get(PatchShaderType.COMPUTE) : null; } public static void clearCache() { diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/AttributeParameters.java b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/AttributeParameters.java index ff4f6a5f4..284cec99e 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/AttributeParameters.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/AttributeParameters.java @@ -2,42 +2,49 @@ package net.coderbot.iris.pipeline.transform.parameter; import net.coderbot.iris.gbuffer_overrides.matching.InputAvailability; import net.coderbot.iris.pipeline.transform.Patch; +import net.coderbot.iris.shaderpack.texture.TextureStage; public class AttributeParameters extends Parameters { - public final boolean hasGeometry; - public final InputAvailability inputs; + public final boolean hasGeometry; + public final InputAvailability inputs; + // WARNING: adding new fields requires updating hashCode and equals methods! - public AttributeParameters(Patch patch, boolean hasGeometry, InputAvailability inputs) { - super(patch); - this.hasGeometry = hasGeometry; - this.inputs = inputs; - } + public AttributeParameters(Patch patch, boolean hasGeometry, InputAvailability inputs) { + super(patch, null); + this.hasGeometry = hasGeometry; + this.inputs = inputs; + } - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + (hasGeometry ? 1231 : 1237); - result = prime * result + ((inputs == null) ? 0 : inputs.hashCode()); - return result; - } + @Override + public TextureStage getTextureStage() { + return TextureStage.GBUFFERS_AND_SHADOW; + } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - AttributeParameters other = (AttributeParameters) obj; - if (hasGeometry != other.hasGeometry) - return false; - if (inputs == null) { - if (other.inputs != null) - return false; - } else if (!inputs.equals(other.inputs)) - return false; - return true; - } + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + (hasGeometry ? 1231 : 1237); + result = prime * result + ((inputs == null) ? 0 : inputs.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + AttributeParameters other = (AttributeParameters) obj; + if (hasGeometry != other.hasGeometry) + return false; + if (inputs == null) { + if (other.inputs != null) + return false; + } else if (!inputs.equals(other.inputs)) + return false; + return true; + } } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/CeleritasTerrainParameters.java b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/CeleritasTerrainParameters.java new file mode 100644 index 000000000..713338b1c --- /dev/null +++ b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/CeleritasTerrainParameters.java @@ -0,0 +1,19 @@ +package net.coderbot.iris.pipeline.transform.parameter; + +import net.coderbot.iris.pipeline.transform.Patch; +import net.coderbot.iris.shaderpack.texture.TextureStage; + +public class CeleritasTerrainParameters extends Parameters { + // WARNING: adding new fields requires updating hashCode and equals methods! + + public CeleritasTerrainParameters(Patch patch) { + super(patch, null); + } + + @Override + public TextureStage getTextureStage() { + return TextureStage.GBUFFERS_AND_SHADOW; + } + + // since this class has no additional fields, hashCode() and equals() are inherited from Parameters +} diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/ComputeParameters.java b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/ComputeParameters.java new file mode 100644 index 000000000..25cb8199b --- /dev/null +++ b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/ComputeParameters.java @@ -0,0 +1,24 @@ +package net.coderbot.iris.pipeline.transform.parameter; + +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import net.coderbot.iris.gl.blending.AlphaTest; +import net.coderbot.iris.gl.texture.TextureType; +import net.coderbot.iris.helpers.Tri; +import net.coderbot.iris.pipeline.transform.Patch; +import net.coderbot.iris.shaderpack.texture.TextureStage; + +public class ComputeParameters extends TextureStageParameters { + // WARNING: adding new fields requires updating hashCode and equals methods! + + public ComputeParameters(Patch patch, TextureStage stage, Object2ObjectMap, String> textureMap) { + super(patch, stage, textureMap); + } + + @Override + public AlphaTest getAlphaTest() { + return AlphaTest.ALWAYS; + } + + // since this class has no fields, hashCode() and equals() are inherited from + // TextureStageParameters +} diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/JobParameters.java b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/JobParameters.java deleted file mode 100644 index 1aeb5c670..000000000 --- a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/JobParameters.java +++ /dev/null @@ -1,20 +0,0 @@ -package net.coderbot.iris.pipeline.transform.parameter; - -public interface JobParameters { - - JobParameters EMPTY = new JobParameters() { - @Override - public boolean equals(Object other) { - return other == this; - } - - @Override - public int hashCode() { - return 0; - } - }; - - boolean equals(Object other); - - int hashCode(); -} diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/Parameters.java b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/Parameters.java index b05ec8ce0..aef7981ea 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/Parameters.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/Parameters.java @@ -1,37 +1,59 @@ package net.coderbot.iris.pipeline.transform.parameter; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import net.coderbot.iris.gl.blending.AlphaTest; +import net.coderbot.iris.gl.shader.ShaderType; +import net.coderbot.iris.gl.texture.TextureType; +import net.coderbot.iris.helpers.Tri; import net.coderbot.iris.pipeline.transform.Patch; -import net.coderbot.iris.pipeline.transform.PatchShaderType; +import net.coderbot.iris.shaderpack.texture.TextureStage; -public class Parameters implements JobParameters { - public final Patch patch; - public PatchShaderType type; - // WARNING: adding new fields requires updating hashCode and equals methods! +public abstract class Parameters { + public final Patch patch; + private final Object2ObjectMap, String> textureMap; + public ShaderType type; + // WARNING: adding new fields requires updating hashCode and equals methods! - // name of the shader, this should not be part of hash/equals - public String name; // set by TransformPatcher + public Parameters(Patch patch, Object2ObjectMap, String> textureMap) { + this.patch = patch; + this.textureMap = textureMap; + } - public Parameters(Patch patch) { - this.patch = patch; - } + public AlphaTest getAlphaTest() { + return AlphaTest.ALWAYS; + } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((patch == null) ? 0 : patch.hashCode()); - return result; - } + public abstract TextureStage getTextureStage(); - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Parameters other = (Parameters) obj; - return patch == other.patch; - } + public Object2ObjectMap, String> getTextureMap() { + return textureMap; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((patch == null) ? 0 : patch.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + ((textureMap == null) ? 0 : textureMap.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Parameters other = (Parameters) obj; + if (patch != other.patch) + return false; + if (type != other.type) + return false; + if (textureMap == null) { + return other.textureMap == null; + } else return textureMap.equals(other.textureMap); + } } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/TextureStageParameters.java b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/TextureStageParameters.java new file mode 100644 index 000000000..4ae606a6b --- /dev/null +++ b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/TextureStageParameters.java @@ -0,0 +1,48 @@ +package net.coderbot.iris.pipeline.transform.parameter; + +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import net.coderbot.iris.gl.blending.AlphaTest; +import net.coderbot.iris.gl.texture.TextureType; +import net.coderbot.iris.helpers.Tri; +import net.coderbot.iris.pipeline.transform.Patch; +import net.coderbot.iris.shaderpack.texture.TextureStage; + +public class TextureStageParameters extends Parameters { + private final TextureStage stage; + // WARNING: adding new fields requires updating hashCode and equals methods! + + public TextureStageParameters(Patch patch, TextureStage stage, Object2ObjectMap, String> textureMap) { + super(patch, textureMap); + this.stage = stage; + } + + @Override + public TextureStage getTextureStage() { + return stage; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((stage == null) ? 0 : stage.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + TextureStageParameters other = (TextureStageParameters) obj; + return stage == other.stage; + } + + @Override + public AlphaTest getAlphaTest() { + return AlphaTest.ALWAYS; + } +} diff --git a/src/main/java/net/coderbot/iris/postprocess/CenterDepthSampler.java b/src/main/java/net/coderbot/iris/postprocess/CenterDepthSampler.java index 06a6f3fcb..9e3c54cd9 100644 --- a/src/main/java/net/coderbot/iris/postprocess/CenterDepthSampler.java +++ b/src/main/java/net/coderbot/iris/postprocess/CenterDepthSampler.java @@ -82,7 +82,7 @@ public class CenterDepthSampler { this.framebuffer.bind(); this.program.use(); - GL11.glViewport(0, 0, 1, 1); + GLStateManager.glViewport(0, 0, 1, 1); FullScreenQuadRenderer.INSTANCE.render(); diff --git a/src/main/java/net/coderbot/iris/postprocess/CompositeRenderer.java b/src/main/java/net/coderbot/iris/postprocess/CompositeRenderer.java index 412a1fb05..2406e1cde 100644 --- a/src/main/java/net/coderbot/iris/postprocess/CompositeRenderer.java +++ b/src/main/java/net/coderbot/iris/postprocess/CompositeRenderer.java @@ -7,6 +7,7 @@ import com.gtnewhorizons.angelica.glsm.GLStateManager; import com.gtnewhorizons.angelica.glsm.RenderSystem; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import lombok.Getter; +import net.coderbot.iris.features.FeatureFlags; import net.coderbot.iris.gl.framebuffer.GlFramebuffer; import net.coderbot.iris.gl.framebuffer.ViewportData; import net.coderbot.iris.gl.image.GlImage; @@ -29,7 +30,9 @@ import net.coderbot.iris.shaderpack.ComputeSource; import net.coderbot.iris.shaderpack.PackDirectives; import net.coderbot.iris.shaderpack.ProgramDirectives; import net.coderbot.iris.shaderpack.ProgramSource; +import net.coderbot.iris.shaderpack.texture.TextureStage; import net.coderbot.iris.shadows.ShadowRenderTargets; +import net.coderbot.iris.gl.state.FogMode; import net.coderbot.iris.uniforms.CommonUniforms; import net.coderbot.iris.uniforms.FrameUpdateNotifier; import net.coderbot.iris.uniforms.custom.CustomUniforms; @@ -41,6 +44,7 @@ import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL13; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL30; +import org.lwjgl.opengl.GL42; import java.util.Map; import java.util.Objects; @@ -258,7 +262,7 @@ public class CompositeRenderer { } if (ranCompute) { - RenderSystem.memoryBarrier(40); + RenderSystem.memoryBarrier(GL42.GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL42.GL_TEXTURE_FETCH_BARRIER_BIT); } Program.unbind(); @@ -279,7 +283,7 @@ public class CompositeRenderer { final float scaledHeight = renderPass.viewHeight * renderPass.viewportScale.scale(); final float viewportX = renderPass.viewWidth * renderPass.viewportScale.viewportX(); final float viewportY = renderPass.viewHeight * renderPass.viewportScale.viewportY(); - GL11.glViewport((int) viewportX, (int) viewportY, (int) scaledWidth, (int) scaledHeight); + GLStateManager.glViewport((int) viewportX, (int) viewportY, (int) scaledWidth, (int) scaledHeight); renderPass.framebuffer.bind(); renderPass.program.use(); @@ -353,7 +357,7 @@ public class CompositeRenderer { throw new RuntimeException("Shader compilation failed!", e); } - CommonUniforms.addDynamicUniforms(builder); + CommonUniforms.addDynamicUniforms(builder, FogMode.OFF); this.customUniforms.assignTo(builder); ProgramSamplers.CustomTextureSamplerInterceptor customTextureSamplerInterceptor = ProgramSamplers.customTextureSamplerInterceptor(builder, customTextureIds, flippedAtLeastOnceSnapshot); @@ -369,7 +373,7 @@ public class CompositeRenderer { IrisSamplers.addCompositeSamplers(customTextureSamplerInterceptor, renderTargets); if (IrisSamplers.hasShadowSamplers(customTextureSamplerInterceptor)) { - IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowTargetsSupplier.get(), null, false); + IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowTargetsSupplier.get(), null, pipeline != null && pipeline.hasFeature(FeatureFlags.SEPARATE_HARDWARE_SAMPLERS)); IrisImages.addShadowColorImages(builder, shadowTargetsSupplier.get(), null); } @@ -395,7 +399,9 @@ public class CompositeRenderer { ProgramBuilder builder; try { - builder = ProgramBuilder.beginCompute(source.getName(), source.getSource().orElse(null), IrisSamplers.COMPOSITE_RESERVED_TEXTURE_UNITS); + String transformed = TransformPatcher.patchCompute(source.getName(), source.getSource().orElse(null), TextureStage.COMPOSITE_AND_FINAL, pipeline != null ? pipeline.getTextureMap() : null); + PatchedShaderPrinter.debugPatchedShaders(source.getName() + "_compute", null, null, null, transformed); + builder = ProgramBuilder.beginCompute(source.getName(), transformed, IrisSamplers.COMPOSITE_RESERVED_TEXTURE_UNITS); } catch (RuntimeException e) { // TODO: Better error handling throw new RuntimeException("Shader compilation failed!", e); @@ -403,7 +409,7 @@ public class CompositeRenderer { ProgramSamplers.CustomTextureSamplerInterceptor customTextureSamplerInterceptor = ProgramSamplers.customTextureSamplerInterceptor(builder, customTextureIds, flippedAtLeastOnceSnapshot); - CommonUniforms.addDynamicUniforms(builder); + CommonUniforms.addDynamicUniforms(builder, FogMode.OFF); this.customUniforms.assignTo(builder); @@ -418,7 +424,7 @@ public class CompositeRenderer { IrisSamplers.addCompositeSamplers(customTextureSamplerInterceptor, renderTargets); if (IrisSamplers.hasShadowSamplers(customTextureSamplerInterceptor)) { - IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowTargetsSupplier.get(), null, false); + IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowTargetsSupplier.get(), null, pipeline != null && pipeline.hasFeature(FeatureFlags.SEPARATE_HARDWARE_SAMPLERS)); IrisImages.addShadowColorImages(builder, shadowTargetsSupplier.get(), null); } diff --git a/src/main/java/net/coderbot/iris/postprocess/FinalPassRenderer.java b/src/main/java/net/coderbot/iris/postprocess/FinalPassRenderer.java index 5e41223c2..2d4ab044d 100644 --- a/src/main/java/net/coderbot/iris/postprocess/FinalPassRenderer.java +++ b/src/main/java/net/coderbot/iris/postprocess/FinalPassRenderer.java @@ -6,6 +6,7 @@ import com.gtnewhorizons.angelica.glsm.GLStateManager; import com.gtnewhorizons.angelica.glsm.RenderSystem; import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import net.coderbot.iris.features.FeatureFlags; import net.coderbot.iris.gl.framebuffer.GlFramebuffer; import net.coderbot.iris.gl.image.GlImage; import net.coderbot.iris.gl.program.ComputeProgram; @@ -28,7 +29,9 @@ import net.coderbot.iris.shaderpack.ComputeSource; import net.coderbot.iris.shaderpack.ProgramDirectives; import net.coderbot.iris.shaderpack.ProgramSet; import net.coderbot.iris.shaderpack.ProgramSource; +import net.coderbot.iris.shaderpack.texture.TextureStage; import net.coderbot.iris.shadows.ShadowRenderTargets; +import net.coderbot.iris.gl.state.FogMode; import net.coderbot.iris.uniforms.CommonUniforms; import net.coderbot.iris.uniforms.FrameUpdateNotifier; import net.coderbot.iris.uniforms.custom.CustomUniforms; @@ -40,6 +43,7 @@ import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL13; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL30; +import org.lwjgl.opengl.GL42; import java.util.Map; import java.util.Objects; @@ -220,7 +224,7 @@ public class FinalPassRenderer { } } - RenderSystem.memoryBarrier(40); + RenderSystem.memoryBarrier(GL42.GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL42.GL_TEXTURE_FETCH_BARRIER_BIT); if (!finalPass.mipmappedBuffers.isEmpty()) { GLStateManager.glActiveTexture(GL13.GL_TEXTURE0); @@ -367,7 +371,7 @@ public class FinalPassRenderer { final ProgramSamplers.CustomTextureSamplerInterceptor customTextureSamplerInterceptor = ProgramSamplers.customTextureSamplerInterceptor(builder, customTextureIds, flippedAtLeastOnceSnapshot); - CommonUniforms.addDynamicUniforms(builder); + CommonUniforms.addDynamicUniforms(builder, FogMode.OFF); IrisSamplers.addRenderTargetSamplers(customTextureSamplerInterceptor, () -> flipped, renderTargets, true, pipeline); // Bind custom images as samplers BEFORE render target images IrisSamplers.addCustomImages(customTextureSamplerInterceptor, customImages); @@ -382,7 +386,7 @@ public class FinalPassRenderer { IrisSamplers.addCompositeSamplers(customTextureSamplerInterceptor, renderTargets); if (IrisSamplers.hasShadowSamplers(customTextureSamplerInterceptor)) { - IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowTargetsSupplier.get(), null, false); + IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowTargetsSupplier.get(), null, pipeline != null && pipeline.hasFeature(FeatureFlags.SEPARATE_HARDWARE_SAMPLERS)); IrisImages.addShadowColorImages(builder, shadowTargetsSupplier.get(), null); } @@ -408,7 +412,9 @@ public class FinalPassRenderer { final ProgramBuilder builder; try { - builder = ProgramBuilder.beginCompute(source.getName(), source.getSource().orElse(null), IrisSamplers.COMPOSITE_RESERVED_TEXTURE_UNITS); + String transformed = TransformPatcher.patchCompute(source.getName(), source.getSource().orElse(null), TextureStage.COMPOSITE_AND_FINAL, pipeline != null ? pipeline.getTextureMap() : null); + PatchedShaderPrinter.debugPatchedShaders(source.getName() + "_compute", null, null, null, transformed); + builder = ProgramBuilder.beginCompute(source.getName(), transformed, IrisSamplers.COMPOSITE_RESERVED_TEXTURE_UNITS); } catch (RuntimeException e) { // TODO: Better error handling throw new RuntimeException("Shader compilation failed!", e); @@ -418,7 +424,7 @@ public class FinalPassRenderer { customUniforms.assignTo(builder); - CommonUniforms.addDynamicUniforms(builder); + CommonUniforms.addDynamicUniforms(builder, FogMode.OFF); IrisSamplers.addRenderTargetSamplers(customTextureSamplerInterceptor, () -> flipped, renderTargets, true, pipeline); IrisSamplers.addCustomImages(customTextureSamplerInterceptor, customImages); IrisSamplers.addCustomTextures(customTextureSamplerInterceptor, irisCustomTextures); @@ -430,7 +436,7 @@ public class FinalPassRenderer { IrisSamplers.addCompositeSamplers(customTextureSamplerInterceptor, renderTargets); if (IrisSamplers.hasShadowSamplers(customTextureSamplerInterceptor)) { - IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowTargetsSupplier.get(), null, false); + IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowTargetsSupplier.get(), null, pipeline != null && pipeline.hasFeature(FeatureFlags.SEPARATE_HARDWARE_SAMPLERS)); IrisImages.addShadowColorImages(builder, shadowTargetsSupplier.get(), null); } diff --git a/src/main/java/net/coderbot/iris/shaderpack/ProgramDirectives.java b/src/main/java/net/coderbot/iris/shaderpack/ProgramDirectives.java index 3774debe1..246aca9ac 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/ProgramDirectives.java +++ b/src/main/java/net/coderbot/iris/shaderpack/ProgramDirectives.java @@ -21,6 +21,7 @@ public class ProgramDirectives { private static final ImmutableList LEGACY_RENDER_TARGETS = PackRenderTargetDirectives.LEGACY_RENDER_TARGETS; private final int[] drawBuffers; + private boolean unknownDrawBuffers; private final ViewportData viewportScale; @Nullable private final AlphaTestOverride alphaTestOverride; @@ -40,6 +41,7 @@ public class ProgramDirectives { this.bufferBlendInformations = bufferBlendInformations; this.mipmappedBuffers = mipmappedBuffers; this.explicitFlips = explicitFlips; + this.unknownDrawBuffers = false; } ProgramDirectives(ProgramSource source, ShaderProperties properties, Set supportedRenderTargets, @Nullable BlendModeOverride defaultBlendOverride) { @@ -53,7 +55,7 @@ public class ProgramDirectives { final Optional optionalDrawbuffersDirective = findDrawbuffersDirective(source.getFragmentSource()); final Optional optionalRendertargetsDirective = findRendertargetsDirective(source.getFragmentSource()); - final Optional optionalCommentDirective = getAppliedDirective(optionalDrawbuffersDirective, optionalRendertargetsDirective); + Optional optionalCommentDirective = getAppliedDirective(optionalDrawbuffersDirective, optionalRendertargetsDirective); drawBuffers = optionalCommentDirective.map(commentDirective -> { if (commentDirective.getType() == CommentDirective.Type.DRAWBUFFERS) { return parseDigits(commentDirective.getDirective().toCharArray()); @@ -62,7 +64,10 @@ public class ProgramDirectives { } else { throw new IllegalStateException("Unhandled comment directive type!"); } - }).orElse(new int[] { 0 }); + }).orElseGet(() -> { + unknownDrawBuffers = true; + return new int[]{0}; + }); if (properties != null) { viewportScale = properties.getViewportScaleOverrides().getOrDefault(source.getName(), ViewportData.defaultValue()); @@ -160,6 +165,10 @@ public class ProgramDirectives { return drawBuffers; } + public boolean hasUnknownDrawBuffers() { + return unknownDrawBuffers; + } + public ViewportData getViewportScale() { return viewportScale; } diff --git a/src/main/java/net/coderbot/iris/shaderpack/ShaderPack.java b/src/main/java/net/coderbot/iris/shaderpack/ShaderPack.java index 5a337b38f..53cbf0c6a 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/ShaderPack.java +++ b/src/main/java/net/coderbot/iris/shaderpack/ShaderPack.java @@ -70,6 +70,7 @@ public class ShaderPack { public final CustomUniforms.Builder customUniforms; private final ProgramSet base; + private final Set activeFeatures; private final Map dimensionMap; private final Map dimensionProgramSets; @@ -211,15 +212,29 @@ public class ShaderPack { List finalEnvironmentDefines = new ArrayList<>(); environmentDefines.forEach(finalEnvironmentDefines::add); for (FeatureFlags flag : FeatureFlags.values()) { - if (flag.isUsable()) { + boolean usable = flag.isUsable(); + Iris.logger.info("FeatureFlag {} usable: {}", flag.name(), usable); + if (usable) { finalEnvironmentDefines.add(new StringPair("IRIS_FEATURE_" + flag.name(), "")); } } + Iris.logger.info("Environment defines: {}", finalEnvironmentDefines.stream() + .map(p -> p.getKey() + "=" + p.getValue()) + .collect(java.util.stream.Collectors.joining(", "))); this.shaderProperties = Optional.ofNullable(readProperties(root, "shaders.properties")) .map(source -> new ShaderProperties(source, shaderPackOptions, finalEnvironmentDefines)) .orElseGet(ShaderProperties::empty); + // Build the set of active feature flags from required and optional flags + this.activeFeatures = new HashSet<>(); + for (String flag : shaderProperties.getRequiredFeatureFlags()) { + activeFeatures.add(FeatureFlags.getValue(flag)); + } + for (String flag : shaderProperties.getOptionalFeatureFlags()) { + activeFeatures.add(FeatureFlags.getValue(flag)); + } + List invalidFlagList = shaderProperties.getRequiredFeatureFlags().stream().filter(FeatureFlags::isInvalid).map(FeatureFlags::getValue).collect(Collectors.toList()); List invalidFeatureFlags = invalidFlagList.stream().map(FeatureFlags::getHumanReadableName).collect(Collectors.toList()); @@ -717,4 +732,11 @@ public class ShaderPack { return Optional.ofNullable(customNoiseTexture); } + public Set getActiveFeatures() { + return activeFeatures; + } + + public boolean hasFeature(FeatureFlags feature) { + return activeFeatures.contains(feature); + } } diff --git a/src/main/java/net/coderbot/iris/shadows/ShadowCompositeRenderer.java b/src/main/java/net/coderbot/iris/shadows/ShadowCompositeRenderer.java new file mode 100644 index 000000000..2a299e6df --- /dev/null +++ b/src/main/java/net/coderbot/iris/shadows/ShadowCompositeRenderer.java @@ -0,0 +1,392 @@ +package net.coderbot.iris.shadows; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.gtnewhorizons.angelica.glsm.GLStateManager; +import com.gtnewhorizons.angelica.glsm.RenderSystem; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import net.coderbot.iris.features.FeatureFlags; +import net.coderbot.iris.gl.buffer.ShaderStorageBufferHolder; +import net.coderbot.iris.gl.framebuffer.GlFramebuffer; +import net.coderbot.iris.gl.framebuffer.ViewportData; +import net.coderbot.iris.gl.image.GlImage; +import net.coderbot.iris.gl.program.ComputeProgram; +import net.coderbot.iris.gl.program.Program; +import net.coderbot.iris.gl.program.ProgramBuilder; +import net.coderbot.iris.gl.program.ProgramSamplers; +import net.coderbot.iris.gl.program.ProgramUniforms; +import net.coderbot.iris.gl.state.FogMode; +import net.coderbot.iris.gl.texture.TextureAccess; +import net.coderbot.iris.pipeline.PatchedShaderPrinter; +import net.coderbot.iris.pipeline.WorldRenderingPipeline; +import net.coderbot.iris.pipeline.transform.PatchShaderType; +import net.coderbot.iris.pipeline.transform.TransformPatcher; +import net.coderbot.iris.postprocess.FullScreenQuadRenderer; +import net.coderbot.iris.rendertarget.RenderTarget; +import net.coderbot.iris.samplers.IrisImages; +import net.coderbot.iris.samplers.IrisSamplers; +import net.coderbot.iris.shaderpack.ComputeSource; +import net.coderbot.iris.shaderpack.FilledIndirectPointer; +import net.coderbot.iris.shaderpack.PackDirectives; +import net.coderbot.iris.shaderpack.PackRenderTargetDirectives; +import net.coderbot.iris.shaderpack.ProgramDirectives; +import net.coderbot.iris.shaderpack.ProgramSource; +import net.coderbot.iris.shaderpack.texture.TextureStage; +import net.coderbot.iris.uniforms.CommonUniforms; +import net.coderbot.iris.uniforms.FrameUpdateNotifier; +import net.coderbot.iris.uniforms.custom.CustomUniforms; +import net.minecraft.client.Minecraft; +import net.minecraft.client.shader.Framebuffer; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL13; +import org.lwjgl.opengl.GL30; +import org.lwjgl.opengl.GL42; + +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +public class ShadowCompositeRenderer { + + private final ShadowRenderTargets renderTargets; + + private final ImmutableList passes; + private final TextureAccess noiseTexture; + private final FrameUpdateNotifier updateNotifier; + private final Object2ObjectMap customTextureIds; + private final ImmutableSet flippedAtLeastOnceFinal; + private final CustomUniforms customUniforms; + private final Object2ObjectMap irisCustomTextures; + private final WorldRenderingPipeline pipeline; + private final Set irisCustomImages; + @Nullable + private final ShaderStorageBufferHolder ssboHolder; + + public ShadowCompositeRenderer(WorldRenderingPipeline pipeline, PackDirectives packDirectives, ProgramSource[] sources, ComputeSource[][] computes, + ShadowRenderTargets renderTargets, @Nullable ShaderStorageBufferHolder ssboHolder, TextureAccess noiseTexture, FrameUpdateNotifier updateNotifier, + Object2ObjectMap customTextureIds, Set customImages, ImmutableMap explicitPreFlips, + Object2ObjectMap irisCustomTextures, CustomUniforms customUniforms) { + this.pipeline = pipeline; + this.noiseTexture = noiseTexture; + this.updateNotifier = updateNotifier; + this.renderTargets = renderTargets; + this.ssboHolder = ssboHolder; + this.customTextureIds = customTextureIds; + this.irisCustomTextures = irisCustomTextures; + this.irisCustomImages = customImages; + this.customUniforms = customUniforms; + + final PackRenderTargetDirectives renderTargetDirectives = packDirectives.getRenderTargetDirectives(); + final Map renderTargetSettings = renderTargetDirectives.getRenderTargetSettings(); + + final ImmutableList.Builder passes = ImmutableList.builder(); + final ImmutableSet.Builder flippedAtLeastOnce = new ImmutableSet.Builder<>(); + + explicitPreFlips.forEach((buffer, shouldFlip) -> { + if (shouldFlip) { + renderTargets.flip(buffer); + // NB: Flipping deferred_pre or composite_pre does NOT cause the "flippedAtLeastOnce" flag to trigger + } + }); + + for (int i = 0, sourcesLength = sources.length; i < sourcesLength; i++) { + ProgramSource source = sources[i]; + + ImmutableSet flipped = renderTargets.snapshot(); + ImmutableSet flippedAtLeastOnceSnapshot = flippedAtLeastOnce.build(); + + if (source == null || !source.isValid()) { + if (computes[i] != null) { + ComputeOnlyPass pass = new ComputeOnlyPass(); + pass.computes = createComputes(computes[i], flipped, flippedAtLeastOnceSnapshot, renderTargets); + passes.add(pass); + } + continue; + } + + Pass pass = new Pass(); + ProgramDirectives directives = source.getDirectives(); + + pass.program = createProgram(source, flipped, flippedAtLeastOnceSnapshot, renderTargets); + pass.computes = createComputes(computes[i], flipped, flippedAtLeastOnceSnapshot, renderTargets); + int[] drawBuffers = directives.hasUnknownDrawBuffers() ? new int[] { 0, 1 } : directives.getDrawBuffers(); + + GlFramebuffer framebuffer = renderTargets.createColorFramebuffer(flipped, drawBuffers); + + pass.stageReadsFromAlt = flipped; + pass.framebuffer = framebuffer; + pass.viewportScale = directives.getViewportScale(); + pass.mipmappedBuffers = directives.getMipmappedBuffers(); + pass.flippedAtLeastOnce = flippedAtLeastOnceSnapshot; + + passes.add(pass); + + ImmutableMap explicitFlips = directives.getExplicitFlips(); + + // Flip the buffers that this shader wrote to + for (int buffer : drawBuffers) { + // compare with boxed Boolean objects to avoid NPEs + if (explicitFlips.get(buffer) == Boolean.FALSE) { + continue; + } + + renderTargets.flip(buffer); + flippedAtLeastOnce.add(buffer); + } + + explicitFlips.forEach((buffer, shouldFlip) -> { + if (shouldFlip) { + renderTargets.flip(buffer); + flippedAtLeastOnce.add(buffer); + } + }); + } + + this.passes = passes.build(); + this.flippedAtLeastOnceFinal = flippedAtLeastOnce.build(); + + GLStateManager.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, 0); + } + + private static void setupMipmapping(RenderTarget target, boolean readFromAlt) { + if (target == null) { + return; + } + + int texture = readFromAlt ? target.getAltTexture() : target.getMainTexture(); + + // TODO: Only generate the mipmap if a valid mipmap hasn't been generated or if we've written to the buffer + // (since the last mipmap was generated) + // + // NB: We leave mipmapping enabled even if the buffer is written to again, this appears to match the + // behavior of ShadersMod/OptiFine, however I'm not sure if it's desired behavior. It's possible that a + // program could use mipmapped sampling with a stale mipmap, which probably isn't great. However, the + // sampling mode is always reset between frames, so this only persists after the first program to use + // mipmapping on this buffer. + // + // Also note that this only applies to one of the two buffers in a render target buffer pair - making it + // unlikely that this issue occurs in practice with most shader packs. + RenderSystem.generateMipmaps(texture, GL11.GL_TEXTURE_2D); + RenderSystem.texParameteri(texture, GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, target.getInternalFormat().getPixelFormat().isInteger() ? GL11.GL_NEAREST_MIPMAP_NEAREST : GL11.GL_LINEAR_MIPMAP_LINEAR); + } + + private static void resetRenderTarget(RenderTarget target) { + // Resets the sampling mode of the given render target and then unbinds it to prevent accidental sampling of it + // elsewhere. + + int filter = GL11.GL_LINEAR; + if (target.getInternalFormat().getPixelFormat().isInteger()) { + filter = GL11.GL_NEAREST; + } + + RenderSystem.texParameteri(target.getMainTexture(), GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, filter); + RenderSystem.texParameteri(target.getAltTexture(), GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, filter); + } + + public ImmutableSet getFlippedAtLeastOnceFinal() { + return this.flippedAtLeastOnceFinal; + } + + public void renderAll() { + GLStateManager.disableBlend(); + + FullScreenQuadRenderer.INSTANCE.begin(); + + for (Pass renderPass : passes) { + boolean ranCompute = false; + for (ComputeProgram computeProgram : renderPass.computes) { + if (computeProgram != null) { + ranCompute = true; + final Framebuffer main = Minecraft.getMinecraft().getFramebuffer(); + computeProgram.use(); + this.customUniforms.push(computeProgram); + computeProgram.dispatch(main.framebufferWidth, main.framebufferHeight); + } + } + + if (ranCompute) { + // Memory barrier for shader image access and texture fetch + RenderSystem.memoryBarrier(GL42.GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL42.GL_TEXTURE_FETCH_BARRIER_BIT); + } + + Program.unbind(); + + if (renderPass instanceof ComputeOnlyPass) { + continue; + } + + if (!renderPass.mipmappedBuffers.isEmpty()) { + GLStateManager.glActiveTexture(GL13.GL_TEXTURE0); + + for (int index : renderPass.mipmappedBuffers) { + setupMipmapping(renderTargets.get(index), renderPass.stageReadsFromAlt.contains(index)); + } + } + + float scaledWidth = renderTargets.getResolution() * renderPass.viewportScale.scale(); + float scaledHeight = renderTargets.getResolution() * renderPass.viewportScale.scale(); + int beginWidth = (int) (renderTargets.getResolution() * renderPass.viewportScale.viewportX()); + int beginHeight = (int) (renderTargets.getResolution() * renderPass.viewportScale.viewportY()); + GLStateManager.glViewport(beginWidth, beginHeight, (int) scaledWidth, (int) scaledHeight); + + renderPass.framebuffer.bind(); + renderPass.program.use(); + + this.customUniforms.push(renderPass.program); + + FullScreenQuadRenderer.INSTANCE.renderQuad(); + } + + FullScreenQuadRenderer.INSTANCE.end(); + + ProgramUniforms.clearActiveUniforms(); + ProgramSamplers.clearActiveSamplers(); + + for (int i = 0; i < renderTargets.getRenderTargetCount(); i++) { + // Reset mipmapping states at the end of the frame. + if (renderTargets.get(i) != null) { + resetRenderTarget(renderTargets.get(i)); + } + } + + GLStateManager.glActiveTexture(GL13.GL_TEXTURE0); + } + + // TODO: Don't just copy this from DeferredWorldRenderingPipeline + private Program createProgram(ProgramSource source, ImmutableSet flipped, ImmutableSet flippedAtLeastOnceSnapshot, + ShadowRenderTargets targets) { + // TODO: Properly handle empty shaders + Map transformed = TransformPatcher.patchComposite( + source.getVertexSource().orElseThrow(NullPointerException::new), + source.getGeometrySource().orElse(null), + source.getFragmentSource().orElseThrow(NullPointerException::new)); + String vertex = transformed.get(PatchShaderType.VERTEX); + String geometry = transformed.get(PatchShaderType.GEOMETRY); + String fragment = transformed.get(PatchShaderType.FRAGMENT); + PatchedShaderPrinter.debugPatchedShaders(source.getName(), vertex, geometry, fragment); + + Objects.requireNonNull(flipped); + ProgramBuilder builder; + + try { + builder = ProgramBuilder.begin(source.getName(), vertex, geometry, fragment, IrisSamplers.COMPOSITE_RESERVED_TEXTURE_UNITS); + } catch (RuntimeException e) { + // TODO: Better error handling + throw new RuntimeException("Shader compilation failed for shadow composite " + source.getName() + "!", e); + } + + ProgramSamplers.CustomTextureSamplerInterceptor customTextureSamplerInterceptor = ProgramSamplers.customTextureSamplerInterceptor( + builder, + customTextureIds, + flippedAtLeastOnceSnapshot); + + CommonUniforms.addDynamicUniforms(builder, FogMode.OFF); + this.customUniforms.assignTo(builder); + + IrisSamplers.addNoiseSampler(customTextureSamplerInterceptor, noiseTexture); + IrisSamplers.addCustomTextures(customTextureSamplerInterceptor, irisCustomTextures); + + IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, targets, flipped, pipeline.hasFeature(FeatureFlags.SEPARATE_HARDWARE_SAMPLERS)); + IrisImages.addShadowColorImages(builder, targets, flipped); + IrisImages.addCustomImages(builder, irisCustomImages); + IrisSamplers.addCustomImages(customTextureSamplerInterceptor, irisCustomImages); + Program build = builder.build(); + this.customUniforms.mapholderToPass(builder, build); + + return build; + } + + private ComputeProgram[] createComputes(ComputeSource[] sources, ImmutableSet flipped, ImmutableSet flippedAtLeastOnceSnapshot, + ShadowRenderTargets targets) { + if (sources == null) { + return new ComputeProgram[0]; + } + + ComputeProgram[] programs = new ComputeProgram[sources.length]; + for (int i = 0; i < programs.length; i++) { + ComputeSource source = sources[i]; + if (source == null || !source.getSource().isPresent()) { + continue; + } else { + Objects.requireNonNull(flipped); + ProgramBuilder builder; + + try { + String transformed = TransformPatcher.patchCompute(source.getName(), source.getSource().orElse(null), + TextureStage.SHADOWCOMP, pipeline.getTextureMap()); + PatchedShaderPrinter.debugPatchedShaders(source.getName() + "_compute", null, null, null, transformed); + builder = ProgramBuilder.beginCompute(source.getName(), transformed, IrisSamplers.COMPOSITE_RESERVED_TEXTURE_UNITS); + } catch (RuntimeException e) { + // TODO: Better error handling + throw new RuntimeException("Shader compilation failed for shadowcomp compute " + source.getName() + "!", e); + } + + ProgramSamplers.CustomTextureSamplerInterceptor customTextureSamplerInterceptor = ProgramSamplers.customTextureSamplerInterceptor( + builder, + customTextureIds, + flippedAtLeastOnceSnapshot); + + CommonUniforms.addDynamicUniforms(builder, FogMode.OFF); + this.customUniforms.assignTo(builder); + IrisSamplers.addNoiseSampler(customTextureSamplerInterceptor, noiseTexture); + IrisSamplers.addCustomTextures(customTextureSamplerInterceptor, irisCustomTextures); + + IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, targets, flipped, pipeline.hasFeature(FeatureFlags.SEPARATE_HARDWARE_SAMPLERS)); + IrisImages.addShadowColorImages(builder, targets, flipped); + + IrisImages.addCustomImages(builder, irisCustomImages); + IrisSamplers.addCustomImages(customTextureSamplerInterceptor, irisCustomImages); + programs[i] = builder.buildCompute(); + + this.customUniforms.mapholderToPass(builder, programs[i]); + + programs[i].setWorkGroupInfo( + source.getWorkGroupRelative(), + source.getWorkGroups(), + ssboHolder != null ? FilledIndirectPointer.basedOff(ssboHolder, source.getIndirectPointer()) : null); + } + } + + return programs; + } + + public void destroy() { + for (Pass renderPass : passes) { + renderPass.destroy(); + } + } + + private static class Pass { + + Program program; + GlFramebuffer framebuffer; + ImmutableSet flippedAtLeastOnce; + ImmutableSet stageReadsFromAlt; + ImmutableSet mipmappedBuffers; + ViewportData viewportScale; + ComputeProgram[] computes; + + protected void destroy() { + this.program.destroy(); + for (ComputeProgram compute : this.computes) { + if (compute != null) { + compute.destroy(); + } + } + } + } + + private static class ComputeOnlyPass extends Pass { + + @Override + protected void destroy() { + for (ComputeProgram compute : this.computes) { + if (compute != null) { + compute.destroy(); + } + } + } + } +} diff --git a/src/main/java/net/coderbot/iris/texture/util/TextureManipulationUtil.java b/src/main/java/net/coderbot/iris/texture/util/TextureManipulationUtil.java index 80232437c..ad89b3088 100644 --- a/src/main/java/net/coderbot/iris/texture/util/TextureManipulationUtil.java +++ b/src/main/java/net/coderbot/iris/texture/util/TextureManipulationUtil.java @@ -38,7 +38,7 @@ public class TextureManipulationUtil { for (int level = 0; level <= maxLevel; ++level) { final int width = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, level, GL11.GL_TEXTURE_WIDTH); final int height = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, level, GL11.GL_TEXTURE_HEIGHT); - GL11.glViewport(0, 0, width, height); + GLStateManager.glViewport(0, 0, width, height); GL30.glFramebufferTexture2D( GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, @@ -65,7 +65,7 @@ public class TextureManipulationUtil { previousClearColorBuffer.get(2), previousClearColorBuffer.get(3)); GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, previousTextureId); - GL11.glViewport( + GLStateManager.glViewport( previousViewportBuffer.get(0), previousViewportBuffer.get(1), previousViewportBuffer.get(2), diff --git a/src/main/java/net/coderbot/iris/uniforms/CommonUniforms.java b/src/main/java/net/coderbot/iris/uniforms/CommonUniforms.java index e3324fa5f..4964dd78b 100644 --- a/src/main/java/net/coderbot/iris/uniforms/CommonUniforms.java +++ b/src/main/java/net/coderbot/iris/uniforms/CommonUniforms.java @@ -7,6 +7,7 @@ import com.gtnewhorizons.angelica.glsm.texture.TextureInfo; import com.gtnewhorizons.angelica.glsm.texture.TextureInfoCache; import com.gtnewhorizons.angelica.glsm.texture.TextureTracker; import com.gtnewhorizons.angelica.mixins.interfaces.EntityRendererAccessor; +import net.coderbot.iris.gl.state.FogMode; import net.coderbot.iris.gl.state.ValueUpdateNotifier; import net.coderbot.iris.gl.uniform.DynamicUniformHolder; import net.coderbot.iris.gl.uniform.UniformHolder; @@ -64,11 +65,11 @@ public final class CommonUniforms { } // Needs to use a LocationalUniformHolder as we need it for the common uniforms - public static void addDynamicUniforms(DynamicUniformHolder uniforms) { + public static void addDynamicUniforms(DynamicUniformHolder uniforms, FogMode fogMode) { ExternallyManagedUniforms.addExternallyManagedUniforms116(uniforms); IdMapUniforms.addEntityIdMapUniforms(uniforms); - FogUniforms.addFogUniforms(uniforms); - IrisInternalUniforms.addFogUniforms(uniforms); + FogUniforms.addFogUniforms(uniforms, fogMode); + IrisInternalUniforms.addFogUniforms(uniforms, fogMode); uniforms.uniform2i("atlasSize", () -> { final int glId = GLStateManager.getBoundTextureForServerState(0); diff --git a/src/main/java/net/coderbot/iris/uniforms/FogUniforms.java b/src/main/java/net/coderbot/iris/uniforms/FogUniforms.java index f7033a256..30ef38d56 100644 --- a/src/main/java/net/coderbot/iris/uniforms/FogUniforms.java +++ b/src/main/java/net/coderbot/iris/uniforms/FogUniforms.java @@ -1,25 +1,30 @@ package net.coderbot.iris.uniforms; import com.gtnewhorizons.angelica.glsm.GLStateManager; +import net.coderbot.iris.gl.state.FogMode; import net.coderbot.iris.gl.state.ValueUpdateNotifier; import net.coderbot.iris.gl.uniform.DynamicUniformHolder; +import net.coderbot.iris.gl.uniform.UniformUpdateFrequency; public class FogUniforms { private FogUniforms() { // no construction } - public static void addFogUniforms(DynamicUniformHolder uniforms) { - uniforms.uniform1i("fogMode", () -> { - if(!GLStateManager.getFogMode().isEnabled()) return 0; - - return GLStateManager.getFogState().getFogMode(); - }, ValueUpdateNotifier.NONE); + public static void addFogUniforms(DynamicUniformHolder uniforms, FogMode fogMode) { + if (fogMode == FogMode.OFF) { + uniforms.uniform1i(UniformUpdateFrequency.ONCE, "fogMode", () -> 0); + uniforms.uniform1i(UniformUpdateFrequency.ONCE, "fogShape", () -> -1); + } else { + uniforms.uniform1i("fogMode", () -> { + if (!GLStateManager.getFogMode().isEnabled()) return 0; + return GLStateManager.getFogState().getFogMode(); + }, ValueUpdateNotifier.NONE); + uniforms.uniform1i("fogShape", () -> 0, ValueUpdateNotifier.NONE); + } uniforms.uniform1f("fogDensity", () -> GLStateManager.getFogState().getDensity(), ValueUpdateNotifier.NONE); - uniforms.uniform1f("fogStart", () -> GLStateManager.getFogState().getStart(), ValueUpdateNotifier.NONE); - uniforms.uniform1f("fogEnd", () -> GLStateManager.getFogState().getEnd(), ValueUpdateNotifier.NONE); } } diff --git a/src/main/java/net/coderbot/iris/uniforms/IrisInternalUniforms.java b/src/main/java/net/coderbot/iris/uniforms/IrisInternalUniforms.java index 7a2b396ce..35804e1f1 100644 --- a/src/main/java/net/coderbot/iris/uniforms/IrisInternalUniforms.java +++ b/src/main/java/net/coderbot/iris/uniforms/IrisInternalUniforms.java @@ -1,6 +1,7 @@ package net.coderbot.iris.uniforms; import com.gtnewhorizons.angelica.glsm.GLStateManager; +import net.coderbot.iris.gl.state.FogMode; import net.coderbot.iris.gl.uniform.DynamicUniformHolder; import org.joml.Vector3d; import org.joml.Vector4f; @@ -13,7 +14,7 @@ public class IrisInternalUniforms { private IrisInternalUniforms() { } - public static void addFogUniforms(DynamicUniformHolder uniforms) { + public static void addFogUniforms(DynamicUniformHolder uniforms, FogMode fogMode) { uniforms.uniform4f(PER_FRAME, "iris_FogColor", () -> { final Vector3d color = GLStateManager.getFogState().getFogColor(); return FOG_COLOR.set((float) color.x, (float) color.y, (float) color.z, GLStateManager.getFogState().getFogAlpha());