diff --git a/build.gradle b/build.gradle index 72e97efaf..b8b9555a8 100644 --- a/build.gradle +++ b/build.gradle @@ -161,6 +161,5 @@ curseforge { changelog = file('changelog.txt') releaseType = project.curse_type mainArtifact jar - addArtifact sourcesJar } } diff --git a/changelog.txt b/changelog.txt index bd10b8520..4b5166b4d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,7 +2,7 @@ New - Flywheel driven chest and bell rendering, ~20x performance improvement in contrived cases Fixes - - Fix potential crash related to rendering breaking overlay + - Fix crash rendering breaking overlay after reloading resource packs Technical/API - Deprecate instance registration functions in favor of builders - Refactor breaking overlay renderer to be cleaner and more contained diff --git a/src/main/java/com/jozufozu/flywheel/backend/Backend.java b/src/main/java/com/jozufozu/flywheel/backend/Backend.java index 8c5da8088..325b5653d 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Backend.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Backend.java @@ -60,7 +60,9 @@ public class Backend { void clearContexts() { SpecMetaRegistry.clear(); + programSpecRegistry.clear(); contexts.forEach(IShaderContext::delete); + contexts.clear(); materialRegistry.clear(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java b/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java index df35aa754..92cd9dba2 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java +++ b/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java @@ -28,6 +28,7 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.backend.gl.shader.ShaderType; +import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.loading.Shader; import com.jozufozu.flywheel.backend.loading.ShaderLoadingException; @@ -111,7 +112,9 @@ public class ShaderSources implements ISelectiveResourceReloadListener { ClientWorld world = Minecraft.getInstance().world; if (Backend.isFlywheelWorld(world)) { + // TODO: looks like it might be good to have another event here InstancedRenderDispatcher.loadAllInWorld(world); + CrumblingRenderer.reset(); } } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java index 5800b0f5a..6f85062d4 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java @@ -102,8 +102,7 @@ public class InstancedRenderDispatcher { } public static void loadAllInWorld(ClientWorld world) { - materialManagers.get(world) - .delete(); + materialManagers.replace(world, MaterialManager::delete); InstanceManager tiles = tileInstanceManager.replace(world); world.loadedTileEntityList.forEach(tiles::add); diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/MaterialManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/MaterialManager.java index af338c604..41b422e6c 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/MaterialManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/MaterialManager.java @@ -16,12 +16,14 @@ import com.jozufozu.flywheel.util.WeakHashSet; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.client.renderer.RenderType; +import net.minecraft.inventory.container.PlayerContainer; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Vector3i; +// TODO: 0.2 block atlas should not be a special case public class MaterialManager

{ public static int MAX_ORIGIN_DISTANCE = 100; @@ -103,6 +105,7 @@ public class MaterialManager

{ atlasMaterials.clear(); atlasRenderers.clear(); materials.clear(); + renderers.clear(); } @SuppressWarnings("unchecked") diff --git a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingProgram.java b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingProgram.java index cafe62259..d7e4514ec 100644 --- a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingProgram.java +++ b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingProgram.java @@ -25,12 +25,6 @@ public class CrumblingProgram extends WorldProgram { uTextureScale = getUniformLocation("uTextureScale"); } - @Override - public void bind() { - super.bind(); - setDefaultAtlasSize(); - } - @Override protected void registerSamplers() { super.registerSamplers(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/CrumblingRenderer.java b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java similarity index 78% rename from src/main/java/com/jozufozu/flywheel/backend/instancing/CrumblingRenderer.java rename to src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java index bb8e44ce2..409b5273f 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/CrumblingRenderer.java +++ b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.backend.instancing; +package com.jozufozu.flywheel.core.crumbling; import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; import static org.lwjgl.opengl.GL11.glBindTexture; @@ -11,11 +11,12 @@ import java.util.List; import java.util.SortedSet; import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.instancing.InstanceManager; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.jozufozu.flywheel.core.Contexts; -import com.jozufozu.flywheel.core.crumbling.CrumblingInstanceManager; -import com.jozufozu.flywheel.core.crumbling.CrumblingMaterialManager; -import com.jozufozu.flywheel.core.crumbling.CrumblingProgram; import com.jozufozu.flywheel.event.ReloadRenderersEvent; +import com.jozufozu.flywheel.util.Lazy; +import com.jozufozu.flywheel.util.Pair; import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -29,7 +30,6 @@ import net.minecraft.client.renderer.texture.Texture; import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.client.world.ClientWorld; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.LazyValue; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Matrix4f; import net.minecraftforge.api.distmarker.Dist; @@ -44,8 +44,15 @@ import net.minecraftforge.fml.common.Mod; @Mod.EventBusSubscriber(Dist.CLIENT) public class CrumblingRenderer { - private static final LazyValue> materialManager = new LazyValue<>(() -> new CrumblingMaterialManager(Contexts.CRUMBLING)); - private static final LazyValue> manager = new LazyValue<>(() -> new CrumblingInstanceManager(materialManager.getValue())); + private static final Lazy STATE; + private static final Lazy.KillSwitch INVALIDATOR; + + static { + Pair, Lazy.KillSwitch> state = Lazy.ofKillable(State::new, State::kill); + + STATE = state.getFirst(); + INVALIDATOR = state.getSecond(); + } private static final RenderType crumblingLayer = ModelBakery.BLOCK_DESTRUCTION_RENDER_LAYERS.get(0); @@ -57,12 +64,14 @@ public class CrumblingRenderer { if (activeStages.isEmpty()) return; - InstanceManager renderer = manager.getValue(); + State state = STATE.get(); + + InstanceManager renderer = state.instanceManager; TextureManager textureManager = Minecraft.getInstance().textureManager; ActiveRenderInfo info = Minecraft.getInstance().gameRenderer.getActiveRenderInfo(); - MaterialManager materials = materialManager.getValue(); + MaterialManager materials = state.materialManager; crumblingLayer.startDrawing(); for (Int2ObjectMap.Entry> stage : activeStages.int2ObjectEntrySet()) { @@ -124,7 +133,26 @@ public class CrumblingRenderer { ClientWorld world = event.getWorld(); if (Backend.getInstance() .canUseInstancing() && world != null) { - materialManager.getValue().delete(); + reset(); + } + } + + public static void reset() { + INVALIDATOR.killValue(); + } + + private static class State { + private final MaterialManager materialManager; + private final InstanceManager instanceManager; + + private State() { + materialManager = new CrumblingMaterialManager(Contexts.CRUMBLING); + instanceManager = new CrumblingInstanceManager(materialManager); + } + + private void kill() { + materialManager.delete(); + instanceManager.invalidate(); } } } diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/WorldProgram.java b/src/main/java/com/jozufozu/flywheel/core/shader/WorldProgram.java index 70200ec58..b3a6b9868 100644 --- a/src/main/java/com/jozufozu/flywheel/core/shader/WorldProgram.java +++ b/src/main/java/com/jozufozu/flywheel/core/shader/WorldProgram.java @@ -5,6 +5,7 @@ import static org.lwjgl.opengl.GL20.glUniform3f; import java.util.List; +import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.backend.loading.Program; import com.jozufozu.flywheel.core.shader.extension.IProgramExtension; import com.jozufozu.flywheel.util.AnimationTickHolder; @@ -25,9 +26,9 @@ public class WorldProgram extends ExtensibleGlProgram { uViewProjection = getUniformLocation("uViewProjection"); uCameraPos = getUniformLocation("uCameraPos"); - bind(); + super.bind(); registerSamplers(); - unbind(); + super.unbind(); } protected void registerSamplers() { diff --git a/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java index 7ef6abf64..cddb3a9dc 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java @@ -9,7 +9,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.OptifineHandler; -import com.jozufozu.flywheel.backend.instancing.CrumblingRenderer; +import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.event.BeginFrameEvent; import com.jozufozu.flywheel.event.ReloadRenderersEvent; diff --git a/src/main/java/com/jozufozu/flywheel/util/Lazy.java b/src/main/java/com/jozufozu/flywheel/util/Lazy.java new file mode 100644 index 000000000..6594a313f --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/util/Lazy.java @@ -0,0 +1,57 @@ +package com.jozufozu.flywheel.util; + +import java.util.function.Consumer; +import java.util.function.Supplier; + +import javax.annotation.Nonnull; + +import net.minecraftforge.common.util.NonNullSupplier; + +public class Lazy { + + private final NonNullSupplier supplier; + + private T value; + + public Lazy(NonNullSupplier supplier) { + this.supplier = supplier; + } + + @Nonnull + public T get() { + if (value == null) { + value = supplier.get(); + } + + return value; + } + + /** + * Provides an external facing API safe way of invalidating lazy values. + */ + public static Pair, KillSwitch> ofKillable(NonNullSupplier factory, Consumer destructor) { + Lazy lazy = new Lazy<>(factory); + + KillSwitch killSwitch = new KillSwitch<>(lazy, destructor); + + return Pair.of(lazy, killSwitch); + } + + public static class KillSwitch { + + private final Lazy lazy; + private final Consumer finalizer; + + private KillSwitch(Lazy lazy, Consumer finalizer) { + this.lazy = lazy; + this.finalizer = finalizer; + } + + public void killValue() { + if (lazy.value != null) { + finalizer.accept(lazy.value); + lazy.value = null; + } + } + } +} diff --git a/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java b/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java index 4d4d944e9..a91acb0e8 100644 --- a/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java +++ b/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java @@ -50,7 +50,8 @@ public class WorldAttached { public T replace(IWorld world, Consumer finalizer) { T remove = attached.remove(world); - finalizer.accept(remove); + if (remove != null) + finalizer.accept(remove); return get(world); }