From 141c2b1f98e75eaf9e9fa072de3884d373348aa0 Mon Sep 17 00:00:00 2001 From: mcrcortex <18544518+MCRcortex@users.noreply.github.com> Date: Fri, 31 Oct 2025 11:43:36 +1000 Subject: [PATCH] Add option to choose if to use sodium build threads (default true) --- .../voxy/client/VoxyClientInstance.java | 20 +++++++++++++- .../cortex/voxy/client/config/VoxyConfig.java | 1 + .../client/config/VoxyConfigScreenPages.java | 26 +++++++++++-------- .../mixin/minecraft/MixinLevelRenderer.java | 1 + .../mixin/sodium/MixinChunkJobQueue.java | 3 ++- .../sodium/MixinRenderSectionManager.java | 8 ------ .../sodium/MixinSodiumWorldRenderer.java | 17 ++++++++++++ .../cortex/voxy/commonImpl/VoxyInstance.java | 6 ++++- .../resources/assets/voxy/lang/en_us.json | 3 +++ src/main/resources/client.voxy.mixins.json | 3 ++- 10 files changed, 65 insertions(+), 23 deletions(-) create mode 100644 src/main/java/me/cortex/voxy/client/mixin/sodium/MixinSodiumWorldRenderer.java diff --git a/src/main/java/me/cortex/voxy/client/VoxyClientInstance.java b/src/main/java/me/cortex/voxy/client/VoxyClientInstance.java index c6b0c5a4..66396b4d 100644 --- a/src/main/java/me/cortex/voxy/client/VoxyClientInstance.java +++ b/src/main/java/me/cortex/voxy/client/VoxyClientInstance.java @@ -2,6 +2,7 @@ package me.cortex.voxy.client; import me.cortex.voxy.client.compat.FlashbackCompat; import me.cortex.voxy.client.config.VoxyConfig; +import me.cortex.voxy.client.mixin.sodium.AccessorSodiumWorldRenderer; import me.cortex.voxy.common.Logger; import me.cortex.voxy.common.config.ConfigBuildCtx; import me.cortex.voxy.common.config.Serialization; @@ -14,6 +15,7 @@ import me.cortex.voxy.common.config.storage.rocksdb.RocksDBStorageBackend; import me.cortex.voxy.commonImpl.ImportManager; import me.cortex.voxy.commonImpl.VoxyInstance; import me.cortex.voxy.commonImpl.WorldIdentifier; +import net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer; import net.minecraft.client.Minecraft; import net.minecraft.world.level.storage.LevelResource; import java.nio.file.Files; @@ -27,7 +29,6 @@ public class VoxyClientInstance extends VoxyInstance { private final boolean noIngestOverride; public VoxyClientInstance() { super(); - this.setNumThreads(VoxyConfig.CONFIG.serviceThreads); var path = FlashbackCompat.getReplayStoragePath(); this.noIngestOverride = path != null; if (path == null) { @@ -35,6 +36,23 @@ public class VoxyClientInstance extends VoxyInstance { } this.basePath = path; this.storageConfig = getCreateStorageConfig(path); + this.updateDedicatedThreads(); + } + + @Override + public void updateDedicatedThreads() { + int target = VoxyConfig.CONFIG.serviceThreads; + if (!VoxyConfig.CONFIG.dontUseSodiumBuilderThreads) { + var swr = SodiumWorldRenderer.instanceNullable(); + if (swr != null) { + var rsm = ((AccessorSodiumWorldRenderer) swr).getRenderSectionManager(); + if (rsm != null) { + this.setNumThreads(Math.max(1, target - rsm.getBuilder().getTotalThreadCount())); + return; + } + } + } + this.setNumThreads(target); } @Override diff --git a/src/main/java/me/cortex/voxy/client/config/VoxyConfig.java b/src/main/java/me/cortex/voxy/client/config/VoxyConfig.java index 8adf8f61..c712e915 100644 --- a/src/main/java/me/cortex/voxy/client/config/VoxyConfig.java +++ b/src/main/java/me/cortex/voxy/client/config/VoxyConfig.java @@ -33,6 +33,7 @@ public class VoxyConfig implements OptionStorage { public boolean renderVanillaFog = false; public boolean useEnvironmentalFog = false; public boolean renderStatistics = false; + public boolean dontUseSodiumBuilderThreads = false; private static VoxyConfig loadOrCreate() { if (VoxyCommon.isAvailable()) { diff --git a/src/main/java/me/cortex/voxy/client/config/VoxyConfigScreenPages.java b/src/main/java/me/cortex/voxy/client/config/VoxyConfigScreenPages.java index 7c69d0a0..641e3a26 100644 --- a/src/main/java/me/cortex/voxy/client/config/VoxyConfigScreenPages.java +++ b/src/main/java/me/cortex/voxy/client/config/VoxyConfigScreenPages.java @@ -66,21 +66,25 @@ public abstract class VoxyConfigScreenPages { s.serviceThreads = v; var instance = VoxyCommon.getInstance(); if (instance != null) { - var swr = SodiumWorldRenderer.instanceNullable(); - if (swr != null) { - var rsm = ((AccessorSodiumWorldRenderer)swr).getRenderSectionManager(); - if (rsm!=null) { - instance.setNumThreads(Math.max(1, v-rsm.getBuilder().getTotalThreadCount())); - } else { - instance.setNumThreads(v); - } - } else { - instance.setNumThreads(v); - } + instance.updateDedicatedThreads(); } }, s -> s.serviceThreads) .setImpact(OptionImpact.HIGH) .build() + ).add(OptionImpl.createBuilder(boolean.class, storage) + .setName(Component.translatable("voxy.config.general.useSodiumBuilder")) + .setTooltip(Component.translatable("voxy.config.general.useSodiumBuilder.tooltip")) + .setControl(TickBoxControl::new) + .setImpact(OptionImpact.VARIES) + .setFlags(OptionFlag.REQUIRES_RENDERER_RELOAD) + .setBinding((s,v)->{ + s.dontUseSodiumBuilderThreads = !v; + var instance = VoxyCommon.getInstance(); + if (instance != null) { + instance.updateDedicatedThreads(); + } + }, s->!s.dontUseSodiumBuilderThreads) + .build() ).add(OptionImpl.createBuilder(boolean.class, storage) .setName(Component.translatable("voxy.config.general.ingest")) .setTooltip(Component.translatable("voxy.config.general.ingest.tooltip")) diff --git a/src/main/java/me/cortex/voxy/client/mixin/minecraft/MixinLevelRenderer.java b/src/main/java/me/cortex/voxy/client/mixin/minecraft/MixinLevelRenderer.java index 5fa0f066..a3ba9761 100644 --- a/src/main/java/me/cortex/voxy/client/mixin/minecraft/MixinLevelRenderer.java +++ b/src/main/java/me/cortex/voxy/client/mixin/minecraft/MixinLevelRenderer.java @@ -87,5 +87,6 @@ public abstract class MixinLevelRenderer implements IGetVoxyRenderSystem { throw e; } } + instance.updateDedicatedThreads(); } } diff --git a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinChunkJobQueue.java b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinChunkJobQueue.java index 6c4c2bab..782cdd15 100644 --- a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinChunkJobQueue.java +++ b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinChunkJobQueue.java @@ -1,6 +1,7 @@ package me.cortex.voxy.client.mixin.sodium; import me.cortex.voxy.client.compat.SemaphoreBlockImpersonator; +import me.cortex.voxy.client.config.VoxyConfig; import me.cortex.voxy.common.thread.MultiThreadPrioritySemaphore; import me.cortex.voxy.commonImpl.VoxyCommon; import org.spongepowered.asm.mixin.Mixin; @@ -19,7 +20,7 @@ public class MixinChunkJobQueue { @Redirect(method = "", at = @At(value = "NEW", target = "(I)Ljava/util/concurrent/Semaphore;")) private Semaphore voxy$injectUnifiedPool(int permits) { var instance = VoxyCommon.getInstance(); - if (instance != null) { + if (instance != null && !VoxyConfig.CONFIG.dontUseSodiumBuilderThreads) { this.voxy$semaphoreBlock = instance.getThreadPool().groupSemaphore.createBlock(); return new SemaphoreBlockImpersonator(this.voxy$semaphoreBlock); } diff --git a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinRenderSectionManager.java b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinRenderSectionManager.java index 0c0b2641..7f7fee2d 100644 --- a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinRenderSectionManager.java +++ b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinRenderSectionManager.java @@ -46,14 +46,6 @@ public class MixinRenderSectionManager { } } this.bottomSectionY = this.level.getMinY()>>4; - - { - //TODO: put in a better position - var instance = VoxyCommon.getInstance(); - if (instance != null) { - instance.setNumThreads(Math.max(1, VoxyConfig.CONFIG.serviceThreads - this.builder.getTotalThreadCount())); - } - } } @Inject(method = "onChunkRemoved", at = @At("HEAD")) diff --git a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinSodiumWorldRenderer.java b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinSodiumWorldRenderer.java new file mode 100644 index 00000000..82b218a5 --- /dev/null +++ b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinSodiumWorldRenderer.java @@ -0,0 +1,17 @@ +package me.cortex.voxy.client.mixin.sodium; + +import me.cortex.voxy.commonImpl.VoxyCommon; +import me.cortex.voxy.commonImpl.VoxyInstance; +import net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; + +@Mixin(SodiumWorldRenderer.class) +public class MixinSodiumWorldRenderer { + @Inject(method = "initRenderer", at = @At("TAIL")) + private void voxy$injectThreadUpdate() { + var vi = VoxyCommon.getInstance(); + if (vi != null) vi.updateDedicatedThreads(); + } +} diff --git a/src/main/java/me/cortex/voxy/commonImpl/VoxyInstance.java b/src/main/java/me/cortex/voxy/commonImpl/VoxyInstance.java index 15ef74f1..3da76839 100644 --- a/src/main/java/me/cortex/voxy/commonImpl/VoxyInstance.java +++ b/src/main/java/me/cortex/voxy/commonImpl/VoxyInstance.java @@ -57,13 +57,17 @@ public abstract class VoxyInstance { this.worldCleaner.start(); } - public void setNumThreads(int threads) { + protected void setNumThreads(int threads) { if (threads<0) throw new IllegalArgumentException("Num threads <0"); if (this.threadPool.setNumThreads(threads)) { Logger.info("Dedicated voxy thread pool size: " + threads); } } + public void updateDedicatedThreads() { + this.setNumThreads(3); + } + protected ImportManager createImportManager() { return new ImportManager(); } diff --git a/src/main/resources/assets/voxy/lang/en_us.json b/src/main/resources/assets/voxy/lang/en_us.json index d688d558..9530bf64 100644 --- a/src/main/resources/assets/voxy/lang/en_us.json +++ b/src/main/resources/assets/voxy/lang/en_us.json @@ -7,6 +7,9 @@ "voxy.config.general.serviceThreads": "Service threads", "voxy.config.general.serviceThreads.tooltip": "Number of threads the ServiceThreadPool can use", + "voxy.config.general.useSodiumBuilder": "Use sodium threads", + "voxy.config.general.useSodiumBuilder.tooltip": "Uses sodium builder threads as part of voxys thread pool, can reduce stuttering and lag when moving quickly at high render distance", + "voxy.config.general.ingest": "Chunk Ingest", "voxy.config.general.ingest.tooltip": "Enables or disables voxies ability to convert new chunks into LoDs", diff --git a/src/main/resources/client.voxy.mixins.json b/src/main/resources/client.voxy.mixins.json index b47f8353..c66ee66e 100644 --- a/src/main/resources/client.voxy.mixins.json +++ b/src/main/resources/client.voxy.mixins.json @@ -33,7 +33,8 @@ "sodium.MixinChunkJobQueue", "sodium.MixinDefaultChunkRenderer", "sodium.MixinRenderSectionManager", - "sodium.MixinSodiumOptionsGUI" + "sodium.MixinSodiumOptionsGUI", + "sodium.MixinSodiumWorldRenderer" ], "injectors": { "defaultRequire": 1