diff --git a/changelog.txt b/changelog.txt index 1a62e6f1a..5efc1aa0b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,8 @@ +0.5.0a: +Fixes + - Address crash experienced by some users while rendering any tile. + - Fix crash caused by loading a world with flywheel backend off. + 0.5.0: New - Added parallel batching backend, effectively a CPU instancer. diff --git a/gradle.properties b/gradle.properties index 91ce648e8..fcf0688d4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs = -Xmx3G org.gradle.daemon = false # mod version info -mod_version = 0.5.0 +mod_version = 0.5.0a mc_update_version = 1.18 minecraft_version = 1.18.1 loader_version = 0.12.12 diff --git a/src/main/java/com/jozufozu/flywheel/backend/Backend.java b/src/main/java/com/jozufozu/flywheel/backend/Backend.java index 1d5f931eb..bffbddc46 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Backend.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Backend.java @@ -27,7 +27,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; public class Backend { - public static final Logger log = LogManager.getLogger(Backend.class); + public static final Logger LOGGER = LogManager.getLogger(Backend.class); protected static final Backend INSTANCE = new Backend(); public static Backend getInstance() { @@ -39,8 +39,6 @@ public class Backend { public GLCapabilities capabilities; public GlCompat compat; - private boolean enabled; - public final Loader loader; private final List> contexts = new ArrayList<>(); private final Map> materialRegistry = new HashMap<>(); @@ -93,7 +91,7 @@ public class Backend { } materialRegistry.put(name, spec); - log.debug("registered material '" + name + "' with instance size " + spec.getLayout().getStride()); + LOGGER.debug("registered material '" + name + "' with instance size " + spec.getLayout().getStride()); return spec; } @@ -104,20 +102,12 @@ public class Backend { public void refresh() { OptifineHandler.refresh(); - boolean usingShaders = OptifineHandler.usingShaders(); capabilities = GL.createCapabilities(); compat = new GlCompat(capabilities); - engine = FlwConfig.get() - .getEngine(); - - enabled = switch (engine) { - case OFF -> false; - case BATCHING -> true; - case INSTANCING -> !usingShaders && compat.instancedArraysSupported(); - }; + engine = chooseEngine(compat); } public Collection> allMaterials() { @@ -133,7 +123,7 @@ public class Backend { } public static boolean isOn() { - return getInstance().enabled; + return getInstance().engine != FlwEngine.OFF; } public static boolean canUseInstancing(@Nullable Level world) { @@ -174,4 +164,18 @@ public class Backend { public static void init() { } + + private static FlwEngine chooseEngine(GlCompat compat) { + FlwEngine preferredChoice = FlwConfig.get() + .getEngine(); + + boolean usingShaders = OptifineHandler.usingShaders(); + boolean canUseEngine = switch (preferredChoice) { + case OFF -> true; + case BATCHING -> !usingShaders; + case INSTANCING -> !usingShaders && compat.instancedArraysSupported(); + }; + + return canUseEngine ? preferredChoice : FlwEngine.OFF; + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/Loader.java b/src/main/java/com/jozufozu/flywheel/backend/Loader.java index 58150d518..0f7fd877e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Loader.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Loader.java @@ -82,10 +82,10 @@ public class Loader { throw new ShaderLoadingException("Could not load all shaders, see log for details"); } - Backend.log.info("Loaded all shader programs."); + Backend.LOGGER.info("Loaded all shader programs."); ClientLevel world = Minecraft.getInstance().level; - if (Backend.isFlywheelWorld(world)) { + if (Backend.canUseInstancing(world)) { // TODO: looks like it might be good to have another event here InstancedRenderDispatcher.resetInstanceWorld(world); CrumblingRenderer.reset(); @@ -115,7 +115,7 @@ public class Loader { backend.register(spec); } catch (Exception e) { - Backend.log.error(e); + Backend.LOGGER.error(e); } } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/OptifineHandler.java b/src/main/java/com/jozufozu/flywheel/backend/OptifineHandler.java index 1fd8fbd2f..f003208fe 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/OptifineHandler.java +++ b/src/main/java/com/jozufozu/flywheel/backend/OptifineHandler.java @@ -44,9 +44,9 @@ public class OptifineHandler { optifine = Package.getPackage(OPTIFINE_ROOT_PACKAGE); if (optifine == null) { - Backend.log.info("Optifine not detected."); + Backend.LOGGER.info("Optifine not detected."); } else { - Backend.log.info("Optifine detected."); + Backend.LOGGER.info("Optifine detected."); refresh(); } @@ -79,7 +79,7 @@ public class OptifineHandler { return false; }); } catch (IOException e) { - Backend.log.info("No shader config found."); + Backend.LOGGER.info("No shader config found."); } return shadersOff; } diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/PersistentGlBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/PersistentGlBuffer.java index 79f6148ef..fb783dc4f 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/PersistentGlBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/PersistentGlBuffer.java @@ -12,7 +12,6 @@ import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.gl.GlFence; import com.jozufozu.flywheel.backend.gl.error.GlError; import com.jozufozu.flywheel.backend.gl.error.GlException; -import com.jozufozu.flywheel.util.StringUtil; public class PersistentGlBuffer extends GlBuffer implements Mappable { @@ -49,13 +48,6 @@ public class PersistentGlBuffer extends GlBuffer implements Mappable { Backend.getInstance().compat.bufferStorage.bufferStorage(type, size, flags); - GlError error = GlError.poll(); - if (error != null) { - // If this error is being thrown but everything seems fine, - // GlError.poll() might be returning an error from something earlier. - throw new GlException(error, StringUtil.args("bufferStorage", type, size, flags)); - } - ByteBuffer byteBuffer = GL30.glMapBufferRange(type.glEnum, 0, size, flags); if (byteBuffer == null) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/error/GlError.java b/src/main/java/com/jozufozu/flywheel/backend/gl/error/GlError.java index 41b9ddf46..a0cdbded8 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/error/GlError.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/error/GlError.java @@ -5,8 +5,6 @@ import java.util.function.Supplier; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL30; -import com.jozufozu.flywheel.Flywheel; - import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -41,10 +39,10 @@ public enum GlError { } public static void pollAndThrow(Supplier context) { - // TODO: build flag? to enable or disable this function - GlError err = GlError.poll(); - if (err != null) { - Flywheel.LOGGER.error("{}: {}", err.name(), context.get()); - } +// This was a bad idea. +// GlError err = GlError.poll(); +// if (err != null) { +// Flywheel.LOGGER.error("{}: {}", err.name(), context.get()); +// } } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java index 8fbac95cd..432575f5e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java @@ -49,7 +49,7 @@ public abstract class GlProgram extends GlObject { int index = glGetUniformLocation(this.handle(), uniform); if (index < 0) { - Backend.log.debug("No active uniform '{}' exists in program '{}'. Could be unused.", uniform, this.name); + Backend.LOGGER.debug("No active uniform '{}' exists in program '{}'. Could be unused.", uniform, this.name); } return index; diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java index c386294ba..9aab8e5f0 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java @@ -24,8 +24,8 @@ public class GlShader extends GlObject { String log = GL20.glGetShaderInfoLog(handle); if (!log.isEmpty()) { - Backend.log.error("Shader compilation log for " + name + ": " + log); - Backend.log.error(source); + Backend.LOGGER.error("Shader compilation log for " + name + ": " + log); + Backend.LOGGER.error(source); } //Backend.log.debug(shader.printSource()); 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 abd5d7e95..7e101ed91 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java @@ -22,8 +22,11 @@ public class InstancedRenderDispatcher { * @param te The tile whose instance you want to update. */ public static void enqueueUpdate(BlockEntity te) { - if (te.hasLevel() && te.getLevel() instanceof ClientLevel) - getTiles(te.getLevel()).queueUpdate(te); + if (Backend.isOn() && te.hasLevel() && te.getLevel() instanceof ClientLevel) { + instanceWorlds.get(te.getLevel()) + .getTileEntityInstanceManager() + .queueUpdate(te); + } } /** @@ -31,17 +34,29 @@ public class InstancedRenderDispatcher { * @param entity The entity whose instance you want to update. */ public static void enqueueUpdate(Entity entity) { - getEntities(entity.level).queueUpdate(entity); + if (Backend.isOn()) { + instanceWorlds.get(entity.level) + .getEntityInstanceManager() + .queueUpdate(entity); + } } public static InstanceManager getTiles(LevelAccessor world) { - return instanceWorlds.get(world) - .getTileEntityInstanceManager(); + if (Backend.isOn()) { + return instanceWorlds.get(world) + .getTileEntityInstanceManager(); + } else { + throw new NullPointerException("Backend is off, cannot retrieve instance world."); + } } public static InstanceManager getEntities(LevelAccessor world) { - return instanceWorlds.get(world) - .getEntityInstanceManager(); + if (Backend.isOn()) { + return instanceWorlds.get(world) + .getEntityInstanceManager(); + } else { + throw new NullPointerException("Backend is off, cannot retrieve instance world."); + } } public static void tick(Minecraft mc) { @@ -52,11 +67,14 @@ public class InstancedRenderDispatcher { ClientLevel world = mc.level; AnimationTickHolder.tick(); - instanceWorlds.get(world).tick(); + if (Backend.isOn()) { + instanceWorlds.get(world) + .tick(); + } } public static void onBeginFrame(BeginFrameEvent event) { - if (Backend.isGameActive()) { + if (Backend.isGameActive() && Backend.isOn()) { instanceWorlds.get(event.getWorld()) .beginFrame(event); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/ProtoProgram.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/ProtoProgram.java index caa331d79..db4f9353e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/ProtoProgram.java +++ b/src/main/java/com/jozufozu/flywheel/backend/pipeline/ProtoProgram.java @@ -50,7 +50,7 @@ public class ProtoProgram { String log = glGetProgramInfoLog(this.program); if (!log.isEmpty()) { - Backend.log.debug("Program link log for " + parent.name + ": " + log); + Backend.LOGGER.debug("Program link log for " + parent.name + ": " + log); } int result = glGetProgrami(this.program, GL_LINK_STATUS); diff --git a/src/main/java/com/jozufozu/flywheel/backend/source/FileResolution.java b/src/main/java/com/jozufozu/flywheel/backend/source/FileResolution.java index ba4e5f343..9799f00ca 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/source/FileResolution.java +++ b/src/main/java/com/jozufozu/flywheel/backend/source/FileResolution.java @@ -73,7 +73,7 @@ public class FileResolution { builder.pointAtFile(span.getSourceFile()) .pointAt(span, 2); } - Backend.log.error(builder.build()); + Backend.LOGGER.error(builder.build()); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/source/error/ErrorReporter.java b/src/main/java/com/jozufozu/flywheel/backend/source/error/ErrorReporter.java index 97232a6c4..20e70d2eb 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/source/error/ErrorReporter.java +++ b/src/main/java/com/jozufozu/flywheel/backend/source/error/ErrorReporter.java @@ -18,7 +18,7 @@ public class ErrorReporter { .pointAt(span, 2) .build(); - Backend.log.error(error); + Backend.LOGGER.error(error); } public static void generateFileError(SourceFile file, String message) { @@ -27,7 +27,7 @@ public class ErrorReporter { .pointAtFile(file) .build(); - Backend.log.error(error); + Backend.LOGGER.error(error); } public static void generateMissingStruct(SourceFile file, Span vertexName, CharSequence msg) { @@ -45,7 +45,7 @@ public class ErrorReporter { .pointAt(vertexName, 2) .hintIncludeFor(span.orElse(null), hint); - Backend.log.error(error.build()); + Backend.LOGGER.error(error.build()); } public static void generateMissingFunction(SourceFile file, CharSequence functionName, CharSequence msg) { @@ -62,6 +62,6 @@ public class ErrorReporter { .pointAtFile(file) .hintIncludeFor(span.orElse(null), hint); - Backend.log.error(error.build()); + Backend.LOGGER.error(error.build()); } } diff --git a/src/main/java/com/jozufozu/flywheel/core/WorldContext.java b/src/main/java/com/jozufozu/flywheel/core/WorldContext.java index 5306d605c..92320a0f9 100644 --- a/src/main/java/com/jozufozu/flywheel/core/WorldContext.java +++ b/src/main/java/com/jozufozu/flywheel/core/WorldContext.java @@ -34,7 +34,7 @@ public class WorldContext

implements ShaderContext

{ @Override public void load() { - Backend.log.info("Loading context '{}'", name); + Backend.LOGGER.info("Loading context '{}'", name); specStream.get() .map(backend::getSpec) @@ -46,10 +46,10 @@ public class WorldContext

implements ShaderContext

{ try { programs.put(spec.name, pipeline.compile(spec)); - Backend.log.debug("Loaded program {}", spec.name); + Backend.LOGGER.debug("Loaded program {}", spec.name); } catch (Exception e) { - Backend.log.error("Error loading program {}", spec.name); - Backend.log.error("", e); + Backend.LOGGER.error("Error loading program {}", spec.name); + Backend.LOGGER.error("", e); backend.loader.notifyError(); } } diff --git a/src/main/java/com/jozufozu/flywheel/event/EntityWorldHandler.java b/src/main/java/com/jozufozu/flywheel/event/EntityWorldHandler.java index a8c4707e4..6ae8c00b8 100644 --- a/src/main/java/com/jozufozu/flywheel/event/EntityWorldHandler.java +++ b/src/main/java/com/jozufozu/flywheel/event/EntityWorldHandler.java @@ -1,5 +1,6 @@ package com.jozufozu.flywheel.event; +import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import net.minecraft.client.multiplayer.ClientLevel; @@ -8,12 +9,12 @@ import net.minecraft.world.entity.Entity; public class EntityWorldHandler { public static void onEntityJoinWorld(Entity entity, ClientLevel level) { - InstancedRenderDispatcher.getEntities(level) + if (Backend.isOn()) InstancedRenderDispatcher.getEntities(level) .queueAdd(entity); } public static void onEntityLeaveWorld(Entity entity, ClientLevel level) { - InstancedRenderDispatcher.getEntities(level) + if (Backend.isOn()) InstancedRenderDispatcher.getEntities(level) .remove(entity); } } diff --git a/src/main/java/com/jozufozu/flywheel/fabric/mixin/SystemReportMixin.java b/src/main/java/com/jozufozu/flywheel/fabric/mixin/SystemReportMixin.java new file mode 100644 index 000000000..2d2d22e29 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/fabric/mixin/SystemReportMixin.java @@ -0,0 +1,19 @@ +package com.jozufozu.flywheel.fabric.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.jozufozu.flywheel.backend.Backend; + +import net.minecraft.SystemReport; + +@Mixin(value = SystemReport.class, priority = 1100) +public class SystemReportMixin { + @Inject(method = "()V", at = @At("TAIL")) + private void onTailInit(CallbackInfo ci) { + SystemReport self = (SystemReport) (Object) this; + self.setDetail("Flywheel Backend", () -> Backend.getInstance().getBackendDescriptor()); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/mixin/ChunkRebuildHooksMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/ChunkRebuildHooksMixin.java index d1c3bb30f..c01dbc402 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/ChunkRebuildHooksMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/ChunkRebuildHooksMixin.java @@ -20,7 +20,7 @@ public class ChunkRebuildHooksMixin { @Inject(method = "handleBlockEntity", at = @At("HEAD"), cancellable = true) private void addAndFilterBEs(ChunkRenderDispatcher.CompiledChunk compiledChunk, Set set, E be, CallbackInfo ci) { - if (Backend.isOn() && Backend.isFlywheelWorld(be.getLevel())) { + if (Backend.canUseInstancing(be.getLevel())) { InstancedRenderRegistry registry = InstancedRenderRegistry.getInstance(); if (registry.canInstance(be.getType())) diff --git a/src/main/java/com/jozufozu/flywheel/mixin/InstanceAddMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/InstanceAddMixin.java index 63cde6441..046772e07 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/InstanceAddMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/InstanceAddMixin.java @@ -7,6 +7,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import net.minecraft.world.level.Level; @@ -23,7 +24,9 @@ public class InstanceAddMixin { @Inject(method = "setBlockEntity", at = @At(value = "INVOKE_ASSIGN", target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")) private void tileAdded(BlockEntity be, CallbackInfo ci) { - if (level.isClientSide) InstancedRenderDispatcher.getTiles(this.level) - .add(be); + if (level.isClientSide && Backend.isOn()) { + InstancedRenderDispatcher.getTiles(this.level) + .add(be); + } } } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/InstanceRemoveMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/InstanceRemoveMixin.java index e0282a5c8..9a6862ddf 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/InstanceRemoveMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/InstanceRemoveMixin.java @@ -8,6 +8,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import net.minecraft.client.multiplayer.ClientLevel; @@ -23,8 +24,10 @@ public class InstanceRemoveMixin { @Inject(at = @At("TAIL"), method = "setRemoved") private void removeInstance(CallbackInfo ci) { - if (level instanceof ClientLevel) InstancedRenderDispatcher.getTiles(this.level) - .remove((BlockEntity) (Object) this); + if (level instanceof ClientLevel && Backend.isOn()) { + InstancedRenderDispatcher.getTiles(this.level) + .remove((BlockEntity) (Object) this); + } } // /** diff --git a/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java index dca282ca7..bddedd5cc 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java @@ -83,7 +83,9 @@ public class RenderHooksMixin { */ @Inject(at = @At("TAIL"), method = "setBlockDirty(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/state/BlockState;)V") private void checkUpdate(BlockPos pos, BlockState lastState, BlockState newState, CallbackInfo ci) { - InstancedRenderDispatcher.getTiles(level) - .update(level.getBlockEntity(pos)); + if (Backend.isOn()) { + InstancedRenderDispatcher.getTiles(level) + .update(level.getBlockEntity(pos)); + } } } diff --git a/src/main/resources/flywheel.fabric.mixins.json b/src/main/resources/flywheel.fabric.mixins.json index 2d165e3e8..198e1bdeb 100644 --- a/src/main/resources/flywheel.fabric.mixins.json +++ b/src/main/resources/flywheel.fabric.mixins.json @@ -8,6 +8,7 @@ "DebugScreenOverlayMixin", "Matrix4fMixin", "MinecraftMixin", + "SystemReportMixin", "TextureAtlasMixin", "VertexFormatAccessor" ],