diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/ChunkBoundRenderer.java b/src/main/java/me/cortex/voxy/client/core/rendering/ChunkBoundRenderer.java index d1bd7ea0..31ce07d6 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/ChunkBoundRenderer.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/ChunkBoundRenderer.java @@ -1,5 +1,8 @@ package me.cortex.voxy.client.core.rendering; +import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2LongLinkedOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2LongOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; import me.cortex.voxy.client.core.gl.GlBuffer; import me.cortex.voxy.client.core.gl.GlFramebuffer; @@ -43,6 +46,8 @@ public class ChunkBoundRenderer { private GlTexture depthBuffer = new GlTexture().store(GL_DEPTH_COMPONENT24, 1, 128, 128); private final GlFramebuffer frameBuffer = new GlFramebuffer().bind(GL_DEPTH_ATTACHMENT, this.depthBuffer).verify(); + private final Int2LongOpenHashMap updates = new Int2LongOpenHashMap(); + public ChunkBoundRenderer() { this.chunk2idx.defaultReturnValue(-1); } @@ -52,24 +57,20 @@ public class ChunkBoundRenderer { throw new IllegalStateException("At capacity"); } if (this.chunk2idx.containsKey(pos)) { - Logger.warn("Chunk already in map: " + new ChunkPos(pos)); + //Logger.warn("Chunk already in map: " + new ChunkPos(pos)); return; } int idx = this.chunk2idx.size(); this.chunk2idx.put(pos, idx); this.idx2chunk[idx] = pos; - long ptr = UploadStream.INSTANCE.upload(this.chunkPosBuffer, 8L*idx, 8); - //Need to do it in 2 parts because ivec2 is 2 parts - MemoryUtil.memPutInt(ptr, (int)(pos&0xFFFFFFFFL)); ptr += 4; - MemoryUtil.memPutInt(ptr, (int)((pos>>>32)&0xFFFFFFFFL)); - UploadStream.INSTANCE.commit(); + this.updates.put(idx, pos); } public void removeChunk(long pos) { int idx = this.chunk2idx.remove(pos); if (idx == -1) { - Logger.warn("Chunk not in map: " + new ChunkPos(pos)); + //Logger.warn("Chunk not in map: " + new ChunkPos(pos)); return; } if (idx == this.chunk2idx.size()) { @@ -88,11 +89,7 @@ public class ChunkBoundRenderer { this.idx2chunk[idx] = ePos; //Put the end pos into the new idx - long ptr = UploadStream.INSTANCE.upload(this.chunkPosBuffer, 8L*idx, 8); - //Need to do it in 2 parts because ivec2 is 2 parts - MemoryUtil.memPutInt(ptr, (int)(ePos&0xFFFFFFFFL)); ptr += 4; - MemoryUtil.memPutInt(ptr, (int)((ePos>>>32)&0xFFFFFFFFL)); - UploadStream.INSTANCE.commit(); + this.updates.put(idx, ePos); } //Bind and render, changing as little gl state as possible so that the caller may configure how it wants to render @@ -151,6 +148,23 @@ public class ChunkBoundRenderer { glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); } + + //Only apply after + if (!this.updates.isEmpty()) { + var iter = this.updates.int2LongEntrySet().fastIterator(); + while (iter.hasNext()) { + var entry = iter.next(); + int idx = entry.getIntKey(); + long pos = entry.getLongValue(); + + long ptr2 = UploadStream.INSTANCE.upload(this.chunkPosBuffer, 8L*idx, 8); + //Need to do it in 2 parts because ivec2 is 2 parts + MemoryUtil.memPutInt(ptr2, (int)(pos&0xFFFFFFFFL)); ptr2 += 4; + MemoryUtil.memPutInt(ptr2, (int)((pos>>>32)&0xFFFFFFFFL)); + UploadStream.INSTANCE.commit(); + } + this.updates.clear(); + } } public void reset() { 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 303228a2..ce5aba69 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 @@ -1,12 +1,18 @@ package me.cortex.voxy.client.mixin.sodium; import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import me.cortex.voxy.client.VoxyClientInstance; import me.cortex.voxy.client.config.VoxyConfig; import me.cortex.voxy.client.core.IGetVoxyRenderSystem; +import me.cortex.voxy.client.core.VoxyRenderSystem; import me.cortex.voxy.commonImpl.VoxyCommon; import net.caffeinemc.mods.sodium.client.gl.device.CommandList; +import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection; import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionManager; +import net.caffeinemc.mods.sodium.client.render.chunk.data.BuiltSectionInfo; import net.minecraft.client.world.ClientWorld; import net.minecraft.util.math.ChunkPos; import org.spongepowered.asm.mixin.Final; @@ -14,6 +20,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(value = RenderSectionManager.class, remap = false) @@ -30,6 +37,7 @@ public class MixinRenderSectionManager { } } + /* @Inject(method = "onChunkAdded", at = @At("HEAD")) private void voxy$trackChunkAdd(int x, int z, CallbackInfo ci) { if (this.level.worldRenderer != null) { @@ -38,7 +46,7 @@ public class MixinRenderSectionManager { system.chunkBoundRenderer.addChunk(ChunkPos.toLong(x, z)); } } - } + }*/ @Inject(method = "onChunkRemoved", at = @At("HEAD")) private void voxy$trackChunkRemove(int x, int z, CallbackInfo ci) { @@ -66,6 +74,21 @@ public class MixinRenderSectionManager { } } + @Redirect(method = "updateSectionInfo", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/RenderSection;setInfo(Lnet/caffeinemc/mods/sodium/client/render/chunk/data/BuiltSectionInfo;)Z")) + private boolean voxy$updateOnUpload(RenderSection instance, BuiltSectionInfo info) { + boolean retVal = instance.setInfo(info); + if (!retVal) { + return false; + } + if (info == null || info == BuiltSectionInfo.EMPTY) { + return true; + } + VoxyRenderSystem system = ((IGetVoxyRenderSystem)(this.level.worldRenderer)).getVoxyRenderSystem(); + if (system != null) { + system.chunkBoundRenderer.addChunk(ChunkPos.toLong(instance.getChunkX(), instance.getChunkZ())); + } + return true; + } @ModifyReturnValue(method = "getSearchDistance", at = @At("RETURN")) private float voxy$increaseSearchDistanceFix(float searchDistance) {