From da6ab3807e5197691e4205f8934da537b72dac82 Mon Sep 17 00:00:00 2001 From: PoPo Date: Thu, 17 Sep 2026 21:03:23 +0200 Subject: [PATCH] Port Voxy to Minecraft 26.3 --- README.md | 35 +++++++++++++- build.gradle | 4 +- docs/vulkan-port.md | 46 +++++++++++++++++++ gradle.properties | 27 +++++------ scripts/smoke.gradle | 17 +++++++ .../me/cortex/voxy/client/VoxyClient.java | 6 ++- .../voxy/client/core/RenderProperties.java | 4 +- .../voxy/client/core/VoxyRenderSystem.java | 4 +- .../model/bakery/BakedBlockEntityModel.java | 2 +- .../model/bakery/ReuseVertexConsumer.java | 9 +++- .../bakery/SoftwareModelTextureBakery.java | 10 ++-- .../core/rendering/util/LightMapHelper.java | 2 +- .../iris/MixinIrisRenderingPipeline.java | 2 +- .../client/mixin/iris/MixinLevelRenderer.java | 4 +- .../mixin/minecraft/MixinRenderSystem.java | 2 +- .../mixin/minecraft/util/MixinGlDebug.java | 2 +- .../mixin/nvidium/MixinRenderPipeline.java | 4 +- .../sodium/MixinDefaultChunkRenderer.java | 16 ++++--- .../voxy/client/taskbar/WindowsTaskbar.java | 11 ++++- .../voxy/commonImpl/OptionalMixinPlugin.java | 29 ++++++++++++ src/main/resources/client.voxy.mixins.json | 1 + src/main/resources/common.voxy.mixins.json | 1 + src/main/resources/fabric.mod.json | 5 +- src/main/resources/voxy.accesswidener | 7 +-- src/smokeTest/java/smoke/PortSmoke.java | 30 ++++++++++++ src/smokeTest/resources/fabric.mod.json | 1 + 26 files changed, 228 insertions(+), 53 deletions(-) create mode 100644 docs/vulkan-port.md create mode 100644 scripts/smoke.gradle create mode 100644 src/main/java/me/cortex/voxy/commonImpl/OptionalMixinPlugin.java create mode 100644 src/smokeTest/java/smoke/PortSmoke.java create mode 100644 src/smokeTest/resources/fabric.mod.json diff --git a/README.md b/README.md index 9b2edc41f..c9f5c597b 100644 --- a/README.md +++ b/README.md @@ -1 +1,34 @@ -Voxy is an LoD rendering mod for minecraft \ No newline at end of file +Voxy is an LoD rendering mod for minecraft + +## Minecraft 26.3 port + +Requires Java 25, Fabric Loader 0.19.5+, Fabric API 0.160.7+26.3 and +Sodium mc26.3-0.9.2-fabric. This port uses **OpenGL**. Vulkan LoD rendering +is not implemented; Voxy disables its renderer when another backend is selected. + +Build with a Java 25 JDK selected in `JAVA_HOME`: + +```powershell +.\gradlew.bat build +``` + +The mod jar is written to `build/libs`. Optional development dependencies are +pinned in `gradle.properties`. Vivecraft, Flashback and Nvidium remain compile-only +integration targets from earlier Minecraft releases; their 26.3 compatibility is +not claimed. Iris 1.11.6+26.3 can be enabled in the development client with +`-Pruntime.iris_version=1.11.6+26.3-fabric`. + +### In-world smoke test + +```powershell +.\gradlew.bat -I scripts/smoke.gradle runClient +.\gradlew.bat -I scripts/smoke.gradle runClient -Pruntime.iris_version=1.11.6+26.3-fabric +``` + +Each invocation opens a development client and creates a new disposable world +under `run/saves/voxy-port-smoke-*`. It checks that Voxy has a renderer after +400 in-world client ticks, prints `VOXY_PORT_SMOKE_OK`, and closes the client. +The smoke-test mod is excluded from the normal build. This checks startup, +world loading and renderer lifetime, not visual correctness or shaderpack compatibility. + +See [the Vulkan port assessment](docs/vulkan-port.md) for the remaining rendering work. diff --git a/build.gradle b/build.gradle index d32f17179..c19a236ee 100644 --- a/build.gradle +++ b/build.gradle @@ -366,7 +366,7 @@ jar { } } -project.ext.lwjglVersion = "3.4.1" +project.ext.lwjglVersion = "3.4.3" project.ext.lwjglNatives = "natives-windows" repositories { @@ -429,4 +429,4 @@ if (!isInGHA) { exclude group: 'net.fabricmc', module: 'fabric-loader' } } -}*/ \ No newline at end of file +}*/ diff --git a/docs/vulkan-port.md b/docs/vulkan-port.md new file mode 100644 index 000000000..b95e0639b --- /dev/null +++ b/docs/vulkan-port.md @@ -0,0 +1,46 @@ +# Vulkan port assessment — Minecraft 26.3 + +Status: **not implemented**. The current 26.3 port renders LoDs with OpenGL. +The backend check in `VoxyClient.initVoxyClient` prevents OpenGL initialization +on Vulkan. Disabling Voxy there is not Vulkan rendering support. + +## Findings from the 26.3 game sources + +Minecraft's graphics classes now live under `com.mojang.renderpearl`. +The public `api.pipeline.ShaderType` exposes vertex and fragment stages only. +`api.commands.CommandEncoder` has no compute-dispatch API. Using this API alone +cannot preserve Voxy's GPU-driven occlusion traversal and indirect draw generation. + +The native Vulkan backend has usable starting points: `VulkanDevice.vkDevice()`, +`vma()`, `graphicsQueue()` and `computeQueue()`. Integrating directly requires +access to the frontend's backend plus careful coordination with Minecraft's +command recording, image layouts, submissions and resource lifetime. It is not +safe to submit independent commands against Minecraft textures without that coordination. + +There are 43 production Java files importing LWJGL OpenGL. Key dependencies are: + +| Area | Existing implementation | Vulkan work | +| --- | --- | --- | +| Buffers, uploads, readbacks | `core/gl`, `UploadStream`, `DownloadStream` | Vulkan/VMA allocations, mapped staging rings and fence-based retirement | +| Shader compilation | `core/gl/shader` | SPIR-V compilation, descriptor layouts and graphics/compute pipelines | +| Visibility and LoD traversal | `HierarchicalOcclusionTraverser`, `NodeCleaner`, `AsyncNodeManager` | Compute pipelines, storage buffers, indirect dispatch and explicit barriers | +| Geometry drawing | `MDICSectionRenderer` | Indexed indirect-count draws, descriptor binding and feature checks | +| Model atlas and lighting | `SoftwareModelTextureBakery`, `LightMapHelper` | GPU image readback and sampling without OpenGL texture IDs | +| Depth and compositing | `VoxyRenderSystem`, rendering pipelines, SSAO | Shared depth conventions, render attachments, layout transitions and compute passes | +| Optional shaders | Iris integration mixins | Separate compatibility work; OpenGL Iris hooks cannot be reused as-is | + +## Implementation sequence + +1. Introduce an explicit backend boundary for GPU resources and frame execution, + retaining the working OpenGL implementation as a regression reference. +2. Add a Vulkan device bridge and a minimal offscreen triangle test sharing + Minecraft's device and submission lifecycle. Check with Vulkan validation layers. +3. Port buffer allocation, uploads/readbacks and shader compilation; validate a + compute dispatch with known input/output before porting the traversal algorithms. +4. Port the MDIC path and its dependencies (visibility, indirect draw generation, + model atlas, lighting, depth pyramid and composition). +5. Test actual LoD output, world/dimension changes, resizing, resource reloads, + shutdown, and GPU-memory lifetime. Only then enable Vulkan as a supported backend. + +No Vulkan support claim should be made on the basis of a successful Java build +or a game launch where Voxy has disabled itself. diff --git a/gradle.properties b/gradle.properties index 3a1b999f9..16c70878f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,31 +7,32 @@ org.gradle.daemon = false # Fabric Properties # check these on https://modmuss50.me/fabric.html -minecraft_version=26.2 -loader_version=0.19.3 -loom_version=1.16-SNAPSHOT +minecraft_version=26.3 +loader_version=0.19.5 +loom_version=1.17.21 # Fabric API -fabric_api_version=0.152.2+26.2 -sodium_version_modrinth=mc26.2-0.9.2-fabric -#sodium_version=0.9.0-beta.3+mc26.2r1 -sodium_extra_allows=0.9.1 +fabric_api_version=0.160.7+26.3 +sodium_version_modrinth=mc26.3-0.9.2-fabric +# Only allow the Sodium version used to build this port. +sodium_extra_allows= #Following modifiers are accepted: compileOnly, runtime -modmenu_version=20.0.0 -lithium_version=mc26.2-0.25.1-fabric +modmenu_version=21.0.0-beta.1 +lithium_version=mc26.3-0.26.1-fabric -compileOnly.iris_version=1.11.2+26.2-fabric +compileOnly.iris_version=1.11.6+26.3-fabric -chunky_version=DCgX52a5 +chunky_version=4Eotm6ov +# Optional integration compile targets; no 26.3 releases were available when porting. vivecraft_version=26.2-1.3.12-fabric flashback_version=VaqZB1DF nvidium_version=0.4.3-beta13-26.1 # Mod Properties -mod_version = 0.2.20-beta +mod_version = 0.2.20-beta+mc26.3 maven_group = me.cortex -archives_base_name = voxy \ No newline at end of file +archives_base_name = voxy diff --git a/scripts/smoke.gradle b/scripts/smoke.gradle new file mode 100644 index 000000000..bf079ab71 --- /dev/null +++ b/scripts/smoke.gradle @@ -0,0 +1,17 @@ +allprojects { + afterEvaluate { + def smokeCompile = tasks.register('compilePortSmoke', JavaCompile) { + source = fileTree('src/smokeTest/java') + classpath = sourceSets.main.compileClasspath + sourceSets.main.output + destinationDirectory = layout.buildDirectory.dir('smoke-classes') + options.release = 25 + dependsOn tasks.named('classes') + } + def smokeResources = tasks.register('copyPortSmoke', Copy) { + from 'src/smokeTest/resources' + into layout.buildDirectory.dir('smoke-classes') + } + dependencies.add('runtimeOnly', files(layout.buildDirectory.dir('smoke-classes'))) + tasks.named('runClient') { dependsOn smokeCompile, smokeResources } + } +} diff --git a/src/main/java/me/cortex/voxy/client/VoxyClient.java b/src/main/java/me/cortex/voxy/client/VoxyClient.java index c0029a7d1..56ff998f9 100644 --- a/src/main/java/me/cortex/voxy/client/VoxyClient.java +++ b/src/main/java/me/cortex/voxy/client/VoxyClient.java @@ -21,6 +21,10 @@ public class VoxyClient implements ClientModInitializer { private static final HashSet FREX = new HashSet<>(); private static FileLock EXCLUSIVE_LOCK; public static void initVoxyClient() { + if (!"OpenGL".equalsIgnoreCase(com.mojang.blaze3d.systems.RenderSystem.getDevice().getDeviceInfo().backendName())) { + Logger.error("Voxy requires the OpenGL renderer; Voxy is disabled on this graphics backend."); + return; + } Capabilities.init();//Ensure clinit is called if (Capabilities.INSTANCE.hasBrokenDepthSampler) { @@ -92,4 +96,4 @@ public static int getOcclusionDebugState() { public static boolean disableSodiumChunkRender() { return false;// getOcclusionDebugState() != 0; } -} \ No newline at end of file +} diff --git a/src/main/java/me/cortex/voxy/client/core/RenderProperties.java b/src/main/java/me/cortex/voxy/client/core/RenderProperties.java index 85a93cef2..b5247a1a3 100644 --- a/src/main/java/me/cortex/voxy/client/core/RenderProperties.java +++ b/src/main/java/me/cortex/voxy/client/core/RenderProperties.java @@ -1,7 +1,7 @@ package me.cortex.voxy.client.core; -import com.mojang.blaze3d.pipeline.DepthStencilState; -import com.mojang.blaze3d.platform.CompareOp; +import com.mojang.renderpearl.api.pipeline.DepthStencilState; +import com.mojang.renderpearl.api.pipeline.CompareOp; import com.mojang.blaze3d.systems.RenderSystem; import me.cortex.voxy.client.core.gl.shader.Shader; import me.cortex.voxy.client.core.util.IrisUtil; diff --git a/src/main/java/me/cortex/voxy/client/core/VoxyRenderSystem.java b/src/main/java/me/cortex/voxy/client/core/VoxyRenderSystem.java index aede085f7..009939312 100644 --- a/src/main/java/me/cortex/voxy/client/core/VoxyRenderSystem.java +++ b/src/main/java/me/cortex/voxy/client/core/VoxyRenderSystem.java @@ -1,7 +1,7 @@ package me.cortex.voxy.client.core; -import com.mojang.blaze3d.opengl.GlConst; -import com.mojang.blaze3d.opengl.GlStateManager; +import com.mojang.renderpearl.backend.opengl.GlConst; +import com.mojang.renderpearl.backend.opengl.GlStateManager; import me.cortex.voxy.client.TimingStatistics; import me.cortex.voxy.client.VoxyClient; import me.cortex.voxy.client.config.VoxyConfig; diff --git a/src/main/java/me/cortex/voxy/client/core/model/bakery/BakedBlockEntityModel.java b/src/main/java/me/cortex/voxy/client/core/model/bakery/BakedBlockEntityModel.java index ab439e15e..41b39a504 100644 --- a/src/main/java/me/cortex/voxy/client/core/model/bakery/BakedBlockEntityModel.java +++ b/src/main/java/me/cortex/voxy/client/core/model/bakery/BakedBlockEntityModel.java @@ -34,7 +34,7 @@ public void render(Matrix4f matrix, int texId) { if (textureId == null) { Logger.error("ERROR: Empty texture id for layer: " + layer); } else { - texId = ((com.mojang.blaze3d.opengl.GlTexture)Minecraft.getInstance().getTextureManager().getTexture(textureId).getTexture()).glId(); + texId = ((com.mojang.renderpearl.backend.opengl.GlTexture)Minecraft.getInstance().getTextureManager().getTexture(textureId).getTexture()).glId(); } } if (texId == 0) continue; diff --git a/src/main/java/me/cortex/voxy/client/core/model/bakery/ReuseVertexConsumer.java b/src/main/java/me/cortex/voxy/client/core/model/bakery/ReuseVertexConsumer.java index 73002be2a..e1199b067 100644 --- a/src/main/java/me/cortex/voxy/client/core/model/bakery/ReuseVertexConsumer.java +++ b/src/main/java/me/cortex/voxy/client/core/model/bakery/ReuseVertexConsumer.java @@ -82,6 +82,12 @@ public ReuseVertexConsumer setUv2(int u, int v) { return this; } + @Override + public ReuseVertexConsumer setUv3(float u, float v) { + // Glint coordinates are not used by the block LoD texture baker. + return this; + } + @Override public ReuseVertexConsumer setNormal(float x, float y, float z) { return this; @@ -104,7 +110,8 @@ public ReuseVertexConsumer quad(BakedQuad quad, boolean forceSolid) { } public ReuseVertexConsumer quad(BakedQuad quad, int metadata) { - this.anyShaded |= quad.materialInfo().shade(); + // 26.3 represents unshaded faces with an upward shade direction override. + this.anyShaded |= quad.materialInfo().shadeDirectionOverride() != net.minecraft.core.Direction.UP; this.anyDarkendTex |= quad.materialInfo().sprite().contents().mipmapStrategy == MipmapStrategy.DARK_CUTOUT; this.ensureCanPut(); for (int i = 0; i < 4; i++) { diff --git a/src/main/java/me/cortex/voxy/client/core/model/bakery/SoftwareModelTextureBakery.java b/src/main/java/me/cortex/voxy/client/core/model/bakery/SoftwareModelTextureBakery.java index 68677078f..ebe1cdbb3 100644 --- a/src/main/java/me/cortex/voxy/client/core/model/bakery/SoftwareModelTextureBakery.java +++ b/src/main/java/me/cortex/voxy/client/core/model/bakery/SoftwareModelTextureBakery.java @@ -1,7 +1,7 @@ package me.cortex.voxy.client.core.model.bakery; -import com.mojang.blaze3d.GpuFormat; -import com.mojang.blaze3d.opengl.GlTexture; +import com.mojang.renderpearl.api.GpuFormat; +import com.mojang.renderpearl.backend.opengl.GlTexture; import com.mojang.blaze3d.vertex.PoseStack; import me.cortex.voxy.client.core.model.ModelFactory; import me.cortex.voxy.common.util.UnsafeUtil; @@ -293,9 +293,9 @@ public int renderToOutput(BlockState state, long outputBuffer, boolean rasterAsU private static void addView(int i, float pitch, float yaw, float rotation, int flip) { var stack = new PoseStack(); stack.translate(0.5f,0.5f,0.5f); - stack.mulPose(makeQuatFromAxisExact(new Vector3f(0,0,1), rotation)); - stack.mulPose(makeQuatFromAxisExact(new Vector3f(1,0,0), pitch)); - stack.mulPose(makeQuatFromAxisExact(new Vector3f(0,1,0), yaw)); + stack.rotate(makeQuatFromAxisExact(new Vector3f(0,0,1), rotation)); + stack.rotate(makeQuatFromAxisExact(new Vector3f(1,0,0), pitch)); + stack.rotate(makeQuatFromAxisExact(new Vector3f(0,1,0), yaw)); stack.mulPose(new Matrix4f().scale(1-2*(flip&1), 1-(flip&2), 1-((flip>>1)&2))); stack.translate(-0.5f,-0.5f,-0.5f); var mat = new Matrix4f(stack.last().pose()); diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/util/LightMapHelper.java b/src/main/java/me/cortex/voxy/client/core/rendering/util/LightMapHelper.java index 60d08f002..e73fb5f69 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/util/LightMapHelper.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/util/LightMapHelper.java @@ -27,6 +27,6 @@ public static void bind(int lightingIndex) { } public static int getLightmapTextureId() { - return ((com.mojang.blaze3d.opengl.GlTexture)(Minecraft.getInstance().gameRenderer.levelLightmap().texture())).glId(); + return ((com.mojang.renderpearl.backend.opengl.GlTexture)(Minecraft.getInstance().gameRenderer.levelLightmap().texture())).glId(); } } \ No newline at end of file diff --git a/src/main/java/me/cortex/voxy/client/mixin/iris/MixinIrisRenderingPipeline.java b/src/main/java/me/cortex/voxy/client/mixin/iris/MixinIrisRenderingPipeline.java index 7d80e4a9a..4cf953bf8 100644 --- a/src/main/java/me/cortex/voxy/client/mixin/iris/MixinIrisRenderingPipeline.java +++ b/src/main/java/me/cortex/voxy/client/mixin/iris/MixinIrisRenderingPipeline.java @@ -40,7 +40,7 @@ public class MixinIrisRenderingPipeline implements IGetVoxyPatchData, IGetIrisVo } } - @Inject(method = "beginLevelRendering", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/opengl/GlStateManager;_activeTexture(I)V", shift = At.Shift.BEFORE), remap = false) + @Inject(method = "beginLevelRendering", at = @At(value = "INVOKE", target = "Lcom/mojang/renderpearl/backend/opengl/GlStateManager;_activeTexture(I)V", shift = At.Shift.BEFORE), remap = false) private void voxy$injectViewportSetup(CallbackInfo ci) { if (IrisUtil.CAPTURED_VIEWPORT_PARAMETERS != null) { var renderer = IVoxyRenderSystemHolder.getNullable(); diff --git a/src/main/java/me/cortex/voxy/client/mixin/iris/MixinLevelRenderer.java b/src/main/java/me/cortex/voxy/client/mixin/iris/MixinLevelRenderer.java index 4efd3efa8..112f51083 100644 --- a/src/main/java/me/cortex/voxy/client/mixin/iris/MixinLevelRenderer.java +++ b/src/main/java/me/cortex/voxy/client/mixin/iris/MixinLevelRenderer.java @@ -1,6 +1,6 @@ package me.cortex.voxy.client.mixin.iris; -import com.mojang.blaze3d.buffers.GpuBufferSlice; +import com.mojang.renderpearl.api.buffers.GpuBufferSlice; import com.mojang.blaze3d.resource.GraphicsResourceAllocator; import me.cortex.voxy.client.core.IVoxyRenderSystemHolder; import me.cortex.voxy.client.core.util.IrisUtil; @@ -30,7 +30,7 @@ public class MixinLevelRenderer { private GameRenderer gameRenderer; @Inject(method = "render", at = @At("HEAD"), order = 100) - private void voxy$injectIrisCompat(GraphicsResourceAllocator resourceAllocator, DeltaTracker deltaTracker, boolean renderOutline, CameraRenderState cameraState, Matrix4fc modelViewMatrix, GpuBufferSlice terrainFog, Vector4f fogColor, boolean shouldRenderSky, CallbackInfo ci) { + private void voxy$injectIrisCompat(GraphicsResourceAllocator resourceAllocator, boolean renderOutline, CameraRenderState cameraState, GpuBufferSlice terrainFog, Vector4f fogColor, boolean shouldRenderSky, boolean consistentDepthRequired, CallbackInfo ci) { if (IrisUtil.irisShaderPackEnabled()) { var renderer = IVoxyRenderSystemHolder.getNullableHolder(); if (renderer != null) { diff --git a/src/main/java/me/cortex/voxy/client/mixin/minecraft/MixinRenderSystem.java b/src/main/java/me/cortex/voxy/client/mixin/minecraft/MixinRenderSystem.java index 744703418..be7abf4f5 100644 --- a/src/main/java/me/cortex/voxy/client/mixin/minecraft/MixinRenderSystem.java +++ b/src/main/java/me/cortex/voxy/client/mixin/minecraft/MixinRenderSystem.java @@ -1,7 +1,7 @@ package me.cortex.voxy.client.mixin.minecraft; -import com.mojang.blaze3d.systems.GpuDevice; +import com.mojang.renderpearl.api.device.GpuDevice; import com.mojang.blaze3d.systems.RenderSystem; import me.cortex.voxy.client.VoxyClient; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/me/cortex/voxy/client/mixin/minecraft/util/MixinGlDebug.java b/src/main/java/me/cortex/voxy/client/mixin/minecraft/util/MixinGlDebug.java index 156960f0a..3ab5f0bec 100644 --- a/src/main/java/me/cortex/voxy/client/mixin/minecraft/util/MixinGlDebug.java +++ b/src/main/java/me/cortex/voxy/client/mixin/minecraft/util/MixinGlDebug.java @@ -2,7 +2,7 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import com.mojang.blaze3d.opengl.GlDebug; +import com.mojang.renderpearl.backend.opengl.GlDebug; import me.cortex.voxy.client.core.gl.Capabilities; import org.slf4j.Logger; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/me/cortex/voxy/client/mixin/nvidium/MixinRenderPipeline.java b/src/main/java/me/cortex/voxy/client/mixin/nvidium/MixinRenderPipeline.java index 36f124b46..95e7c01bb 100644 --- a/src/main/java/me/cortex/voxy/client/mixin/nvidium/MixinRenderPipeline.java +++ b/src/main/java/me/cortex/voxy/client/mixin/nvidium/MixinRenderPipeline.java @@ -1,7 +1,7 @@ package me.cortex.voxy.client.mixin.nvidium; -import com.mojang.blaze3d.opengl.GlTextureView; -import com.mojang.blaze3d.textures.GpuSampler; +import com.mojang.renderpearl.backend.opengl.GlTextureView; +import com.mojang.renderpearl.api.textures.GpuSampler; import me.cortex.nvidium.RenderPipeline; import me.cortex.voxy.client.core.IVoxyRenderSystemHolder; import net.caffeinemc.mods.sodium.client.render.chunk.ChunkRenderMatrices; diff --git a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinDefaultChunkRenderer.java b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinDefaultChunkRenderer.java index 19056d94f..0ad69fe0b 100644 --- a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinDefaultChunkRenderer.java +++ b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinDefaultChunkRenderer.java @@ -1,9 +1,11 @@ package me.cortex.voxy.client.mixin.sodium; -import com.mojang.blaze3d.buffers.GpuBuffer; -import com.mojang.blaze3d.buffers.GpuBufferSlice; -import com.mojang.blaze3d.opengl.GlTextureView; -import com.mojang.blaze3d.textures.GpuSampler; +import com.mojang.renderpearl.api.buffers.GpuBuffer; +import com.mojang.renderpearl.api.commands.RenderPass; +import net.minecraft.client.renderer.oit.OitStage; +import com.mojang.renderpearl.api.buffers.GpuBufferSlice; +import com.mojang.renderpearl.backend.opengl.GlTextureView; +import com.mojang.renderpearl.api.textures.GpuSampler; import me.cortex.voxy.client.VoxyClient; import me.cortex.voxy.client.core.IVoxyRenderSystemHolder; import me.cortex.voxy.client.core.rendering.Viewport; @@ -31,9 +33,9 @@ public MixinDefaultChunkRenderer(ChunkVertexType vertexType) { } @Inject(method = "render", at = @At(value = "HEAD"), cancellable = true) - private void voxy$cancelThingie(ChunkRenderMatrices matrices, ChunkRenderListIterable renderLists, TerrainRenderPass renderPass, CameraTransform camera, FogParameters parameters, boolean indexedRenderingEnabled, GpuSampler terrainSampler, GpuBufferSlice uniformData, GpuBuffer sectionTimeInfo, CallbackInfo ci) { + private void voxy$cancelThingie(ChunkRenderMatrices matrices, ChunkRenderListIterable renderLists, TerrainRenderPass renderPass, CameraTransform camera, FogParameters parameters, boolean indexedRenderingEnabled, RenderPass pass, GpuSampler terrainSampler, GpuBufferSlice uniformData, GpuBuffer sectionTimeInfo, OitStage oitStage, CallbackInfo ci) { if (VoxyClient.disableSodiumChunkRender()) { - super.begin(renderPass, parameters, terrainSampler); + super.begin(renderPass, parameters, terrainSampler, oitStage); this.doRender(matrices, renderPass, camera, parameters); super.end(renderPass); ci.cancel(); @@ -41,7 +43,7 @@ public MixinDefaultChunkRenderer(ChunkVertexType vertexType) { } @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/ShaderChunkRenderer;end(Lnet/caffeinemc/mods/sodium/client/render/chunk/terrain/TerrainRenderPass;)V", shift = At.Shift.BEFORE)) - private void voxy$injectRender(ChunkRenderMatrices matrices, ChunkRenderListIterable renderLists, TerrainRenderPass renderPass, CameraTransform camera, FogParameters parameters, boolean indexedRenderingEnabled, GpuSampler terrainSampler, GpuBufferSlice uniformData, GpuBuffer sectionTimeInfo, CallbackInfo ci) { + private void voxy$injectRender(ChunkRenderMatrices matrices, ChunkRenderListIterable renderLists, TerrainRenderPass renderPass, CameraTransform camera, FogParameters parameters, boolean indexedRenderingEnabled, RenderPass pass, GpuSampler terrainSampler, GpuBufferSlice uniformData, GpuBuffer sectionTimeInfo, OitStage oitStage, CallbackInfo ci) { this.doRender(matrices, renderPass, camera, parameters); } diff --git a/src/main/java/me/cortex/voxy/client/taskbar/WindowsTaskbar.java b/src/main/java/me/cortex/voxy/client/taskbar/WindowsTaskbar.java index 9c4e49171..74768a8f1 100644 --- a/src/main/java/me/cortex/voxy/client/taskbar/WindowsTaskbar.java +++ b/src/main/java/me/cortex/voxy/client/taskbar/WindowsTaskbar.java @@ -4,11 +4,18 @@ import com.sun.jna.platform.win32.COM.COMInvoker; import com.sun.jna.platform.win32.*; import com.sun.jna.ptr.PointerByReference; -import org.lwjgl.glfw.GLFWNativeWin32; +import static org.lwjgl.sdl.SDLProperties.SDL_GetPointerProperty; +import static org.lwjgl.sdl.SDLVideo.SDL_GetWindowProperties; +import static org.lwjgl.sdl.SDLVideo.SDL_PROP_WINDOW_WIN32_HWND_POINTER; public class WindowsTaskbar extends COMInvoker implements Taskbar.ITaskbar { private final WinDef.HWND hwnd; WindowsTaskbar(long windowId) { + long nativeWindow = SDL_GetPointerProperty(SDL_GetWindowProperties(windowId), + SDL_PROP_WINDOW_WIN32_HWND_POINTER, 0); + if (nativeWindow == 0) { + throw new IllegalStateException("SDL window has no Win32 handle"); + } var itaskbar3res = new PointerByReference(); if (W32Errors.FAILED(Ole32.INSTANCE.CoCreateInstance(new Guid.GUID("56FDF344-FD6D-11d0-958A-006097C9A090"), @@ -20,7 +27,7 @@ public class WindowsTaskbar extends COMInvoker implements Taskbar.ITaskbar { } this.setPointer(itaskbar3res.getValue()); - this.hwnd = new WinDef.HWND(new Pointer(GLFWNativeWin32.glfwGetWin32Window(windowId))); + this.hwnd = new WinDef.HWND(new Pointer(nativeWindow)); this.invokeNative(3); // HrInit } diff --git a/src/main/java/me/cortex/voxy/commonImpl/OptionalMixinPlugin.java b/src/main/java/me/cortex/voxy/commonImpl/OptionalMixinPlugin.java new file mode 100644 index 000000000..65306d930 --- /dev/null +++ b/src/main/java/me/cortex/voxy/commonImpl/OptionalMixinPlugin.java @@ -0,0 +1,29 @@ +package me.cortex.voxy.commonImpl; + +import net.fabricmc.loader.api.FabricLoader; +import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import java.util.List; +import java.util.Set; + +/** Only load compatibility mixins when their optional mod is present. */ +public final class OptionalMixinPlugin implements IMixinConfigPlugin { + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + for (String mod : List.of("iris", "flashback", "nvidium", "chunky")) { + if (mixinClassName.contains(".mixin." + mod + ".")) { + return FabricLoader.getInstance().isModLoaded(mod); + } + } + return true; + } + + @Override public void onLoad(String mixinPackage) {} + @Override public String getRefMapperConfig() { return null; } + @Override public void acceptTargets(Set myTargets, Set otherTargets) {} + @Override public List getMixins() { return null; } + @Override public void preApply(String target, ClassNode node, String mixin, IMixinInfo info) {} + @Override public void postApply(String target, ClassNode node, String mixin, IMixinInfo info) {} +} diff --git a/src/main/resources/client.voxy.mixins.json b/src/main/resources/client.voxy.mixins.json index 6f7bb54a7..211730fbc 100644 --- a/src/main/resources/client.voxy.mixins.json +++ b/src/main/resources/client.voxy.mixins.json @@ -1,5 +1,6 @@ { "required": true, + "plugin": "me.cortex.voxy.commonImpl.OptionalMixinPlugin", "package": "me.cortex.voxy.client.mixin", "compatibilityLevel": "JAVA_17", "client": [ diff --git a/src/main/resources/common.voxy.mixins.json b/src/main/resources/common.voxy.mixins.json index f1ab5b819..b6f18d40b 100644 --- a/src/main/resources/common.voxy.mixins.json +++ b/src/main/resources/common.voxy.mixins.json @@ -1,5 +1,6 @@ { "required": true, + "plugin": "me.cortex.voxy.commonImpl.OptionalMixinPlugin", "package": "me.cortex.voxy.commonImpl.mixin", "compatibilityLevel": "JAVA_17", "injectors": { diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 942cce402..749627091 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -39,8 +39,9 @@ ], "depends": { "minecraft": "${allowed_mc_version}", - "fabricloader": ">=0.14.22", - "fabric-api": ">=0.91.1", + "java": ">=25", + "fabricloader": ">=0.19.5", + "fabric-api": ">=0.160.7", "sodium": "${allowed_sodium_versions}" }, "breaks": { diff --git a/src/main/resources/voxy.accesswidener b/src/main/resources/voxy.accesswidener index bb001c74a..385d65a8d 100644 --- a/src/main/resources/voxy.accesswidener +++ b/src/main/resources/voxy.accesswidener @@ -1,13 +1,8 @@ accessWidener v1 official accessible class net/minecraft/client/multiplayer/ClientChunkCache$Storage -accessible class com/mojang/blaze3d/opengl/GlDebug$LogEntry +accessible class com/mojang/renderpearl/backend/opengl/GlDebug$LogEntry -accessible class com/mojang/blaze3d/opengl/GlRenderPass -accessible method com/mojang/blaze3d/opengl/GlCommandEncoder trySetup (Lcom/mojang/blaze3d/opengl/GlRenderPass;Ljava/util/Collection;)Z -accessible method com/mojang/blaze3d/opengl/GlCommandEncoder applyPipelineState (Lcom/mojang/blaze3d/pipeline/RenderPipeline;)V - -accessible field com/mojang/blaze3d/opengl/GlBuffer handle I accessible field net/minecraft/client/renderer/texture/TextureAtlas maxMipLevel I accessible field net/minecraft/client/gui/components/BossHealthOverlay events Ljava/util/Map; accessible field net/minecraft/client/multiplayer/MultiPlayerGameMode connection Lnet/minecraft/client/multiplayer/ClientPacketListener; diff --git a/src/smokeTest/java/smoke/PortSmoke.java b/src/smokeTest/java/smoke/PortSmoke.java new file mode 100644 index 000000000..593823296 --- /dev/null +++ b/src/smokeTest/java/smoke/PortSmoke.java @@ -0,0 +1,30 @@ +package smoke; + +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.minecraft.client.gui.screens.TitleScreen; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.level.GameType; +import net.minecraft.world.level.levelgen.WorldOptions; +import net.minecraft.world.level.levelgen.presets.WorldPresets; +import me.cortex.voxy.client.core.IVoxyRenderSystemHolder; + +public class PortSmoke implements ClientModInitializer { + private boolean started; + private int ticks; + @Override public void onInitializeClient() { + ClientTickEvents.END_CLIENT_TICK.register(client -> { + if (!started && client.gui.screen() instanceof TitleScreen screen) { + started = true; + client.createWorldOpenFlows().createFreshLevel("voxy-port-smoke-" + System.currentTimeMillis(), + MinecraftServer.DEMO_SETTINGS.withGameType(GameType.CREATIVE), WorldOptions.DEMO_OPTIONS, + WorldPresets::createNormalWorldDimensions, screen); + } + if (client.level != null && client.player != null && ++ticks == 400) { + if (IVoxyRenderSystemHolder.getNullable() == null) throw new AssertionError("Voxy renderer missing"); + System.out.println("VOXY_PORT_SMOKE_OK: world rendered for 400 client ticks"); + client.stop(); + } + }); + } +} diff --git a/src/smokeTest/resources/fabric.mod.json b/src/smokeTest/resources/fabric.mod.json new file mode 100644 index 000000000..5115a2a8a --- /dev/null +++ b/src/smokeTest/resources/fabric.mod.json @@ -0,0 +1 @@ +{"schemaVersion":1,"id":"voxy_port_smoke","version":"1.0.0","environment":"client","entrypoints":{"client":["smoke.PortSmoke"]}}