From 243dfc149132cdc518970372068b87003639c9dc Mon Sep 17 00:00:00 2001 From: Elijah Stephenson Date: Mon, 25 May 2026 15:32:36 -0500 Subject: [PATCH] Updated to 26.1.2 Should also work on 26.1 and 26.1.1. Tested with DH-3.0.3 and VulkanMod 0.6.6 --- .DS_Store | Bin 0 -> 6148 bytes .gitlab-ci.yml | 2 +- Readme.md | 16 +-- buildSrc/.DS_Store | Bin 0 -> 6148 bytes .../core/render/renderer/LodRenderer.class | Bin 0 -> 12332 bytes docs/curseforge_description.md | 4 +- gradle.properties | 7 +- gradle/.DS_Store | Bin 0 -> 6148 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 12 ++- .../{1.21.11.properties => 26.1.2.properties} | 23 ++-- vulkan/.DS_Store | Bin 0 -> 6148 bytes vulkan/build.gradle | 82 +++++++++----- .../dhvulkan/DhVulkanMixinPlugin.java | 32 +++--- .../dhvulkan/DhVulkanModEntrypoint.java | 53 ++++++++-- .../dhvulkan/api/ApiDhIntegration.java | 4 +- .../dhvulkan/api/VkRenderApiDefinition.java | 18 ++++ .../dhvulkan/api/VkVertexBufferWrapper.java | 4 +- .../com/braffolk/dhvulkan/compat/Compat.java | 100 +++++++++++++++--- .../dhvulkan/config/DhVulkanConfig.java | 8 +- .../dhvulkan/core/DhConfigHelper.java | 6 +- .../dhvulkan/core/DhFrameProfiler.java | 2 +- .../dhvulkan/core/DhVulkanFramebuffer.java | 6 +- .../dhvulkan/core/VulkanCloudRenderer.java | 12 ++- .../dhvulkan/core/VulkanRenderContext.java | 17 ++- .../dhvulkan/core/VulkanRenderEngine.java | 22 ++-- .../core/pipeline/DhCompositePipeline.java | 18 ++-- .../core/pipeline/DhDepthReaderPipeline.java | 12 +-- .../dhvulkan/core/pipeline/DhFogPipeline.java | 12 +-- .../core/pipeline/DhSsaoPipeline.java | 12 +-- .../dhvulkan/dh24/Dh24Integration.java | 4 +- .../dhvulkan/mixin/dh24/MixinGLProxy.java | 2 +- .../dhvulkan/mixin/dh24/MixinLodRenderer.java | 2 +- .../mixin/dh3/MixinDependencySetup.java | 28 ++--- .../dhvulkan/mixin/dh3/MixinGLProxy.java | 63 +++++++++++ .../dh3/MixinLevelRendererRenderBridge.java | 86 +++++++++++++++ .../dh3/MixinLodBufferContainerRenderDef.java | 33 ++++++ .../mixin/shared/MixinLightMapWrapper.java | 18 ++-- .../dhvulkan/render/DhVulkanRenderBridge.java | 90 ++++++++++++++++ .../dh-vulkanmod.mixins.json | 2 +- .../fabric.mod.json | 2 +- .../resources-mc26/dh-vulkanmod.mixins.json | 17 +++ .../src/main/resources-mc26/fabric.mod.json | 33 ++++++ 43 files changed, 675 insertions(+), 191 deletions(-) create mode 100644 .DS_Store create mode 100644 buildSrc/.DS_Store create mode 100644 com/seibel/distanthorizons/core/render/renderer/LodRenderer.class create mode 100644 gradle/.DS_Store rename versionProperties/{1.21.11.properties => 26.1.2.properties} (57%) create mode 100644 vulkan/.DS_Store create mode 100644 vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh3/MixinGLProxy.java create mode 100644 vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh3/MixinLevelRendererRenderBridge.java create mode 100644 vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh3/MixinLodBufferContainerRenderDef.java create mode 100644 vulkan/src/main/java/com/braffolk/dhvulkan/render/DhVulkanRenderBridge.java rename vulkan/src/main/{resources => resources-legacy}/dh-vulkanmod.mixins.json (99%) rename vulkan/src/main/{resources => resources-legacy}/fabric.mod.json (99%) create mode 100644 vulkan/src/main/resources-mc26/dh-vulkanmod.mixins.json create mode 100644 vulkan/src/main/resources-mc26/fabric.mod.json diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..8c0648fabb8faffa12fa3697f9fbca22043b7bf1 GIT binary patch literal 6148 zcmeHK%}(1u5S~p!vJtA3LtFK@64yusf{?0StQ20LuF3(b)W#9G7%#FDa)=`N2rtB= z@H~9`6G)VDg{Yd5X20F}@p`|tc0EKS29sous6#{&YOvNu^A9n8qia(0mL^cxXCz5^ zp2b>cYq4zDOa{!}ZBa}UN-3k2{gW?d3aOy;<;`u<1xyho$Qms>8uSBA)`iXBUUi72* zS2~&wJ0HL6d>p0usIUoXGD67NNt!2mI?$6mDQ#}(9I`Fj!_Mc~Y_H!{hy8h1&A#sU zy6T{RIG?xWr=8tzKZaM?b*}H+RtbF5Rz7%Kz&$!EE4mGfJk$9F?2DX5EF&|(3@`(m z$bdhqLa6l|z?K!WSRH&n$d}BJAvVzOvyY0*Bl(1I)lG19dm-nEU_u_4(^b literal 0 HcmV?d00001 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3425234..51256d1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -35,7 +35,7 @@ build: parallel: matrix: - MC_VER: [ - "1.21.11", "1.21.10", "1.21.9", "1.21.8", "1.21.6", "1.21.5", "1.21.4", "1.21.3", "1.21.1", + "26.1.2", "1.21.10", "1.21.9", "1.21.8", "1.21.6", "1.21.5", "1.21.4", "1.21.3", "1.21.1", "1.20.6", "1.20.4", "1.20.2", "1.20.1", "1.19.4", "1.19.2", "1.18.2", diff --git a/Readme.md b/Readme.md index 1cd9be1..6c7e312 100644 --- a/Readme.md +++ b/Readme.md @@ -4,7 +4,7 @@ A Fabric extension mod that adds native **Vulkan rendering** to [Distant Horizon LODs are rendered using VulkanMod's Vulkan pipeline instead of OpenGL, enabling Distant Horizons to work on systems and configurations running VulkanMod. -> **This is not a standalone mod.** You must have both Distant Horizons and VulkanMod installed. Versions v2.4.6+vm.3 and earlier were standalone forks of DH; Newer versions are a separate extension mod that runs alongside unmodified DH. Tested for Minecraft versions 1.20.6 and 1.21.11. +> **This is not a standalone mod.** You must have both Distant Horizons and VulkanMod installed. Versions v2.4.6+vm.3 and earlier were standalone forks of DH; Newer versions are a separate extension mod that runs alongside unmodified DH. Tested for Minecraft versions 1.20.6 and 26.1–26.1.2. ![Distant Horizons running on VulkanMod](docs/dh-vulkanmod.jpg) *Distant Horizons LODs rendered via VulkanMod's Vulkan backend* @@ -32,30 +32,32 @@ See [docs/vulkan_implementation_roadmap.md](docs/vulkan_implementation_roadmap.m ## Requirements -- **Minecraft:** 1.20.6 or 1.21.11 +- **Minecraft:** 1.20.6 or 26.1 / 26.1.1 / 26.1.2 - **Mod loader:** Fabric -- **VulkanMod** must be installed (0.4.2 for MC 1.20.6, 0.6.1 for MC 1.21.11) -- **Distant Horizons** 2.4.0+ or 3.0.0+ must be installed +- **VulkanMod** must be installed (0.4.2 for MC 1.20.6, 0.6.6+ for MC 26.1.x) +- **Distant Horizons** 2.4.0+ (1.20.6) or 3.0.0+ (26.1.x) must be installed > This is not the official Distant Horizons mod. For the original, see the [GitLab](https://gitlab.com/distant-horizons-team/distant-horizons) or [CurseForge](https://www.curseforge.com/minecraft/mc-mods/distant-horizons) pages. ## Building ```bash -# MC 1.21.11 -./gradlew :vulkan:build -PmcVer="1.21.11" +# MC 26.1.2 (also supports 26.1 and 26.1.1 in the same jar) +./gradlew :vulkan:build -PmcVer="26.1.2" # MC 1.20.6 ./gradlew :vulkan:build -PmcVer="1.20.6" ``` +Place matching **Distant Horizons** and **VulkanMod** jars in `jars/` before building (see Modrinth: DH 3.0.3-b for 26.1.2, VulkanMod 0.6.6 for 26.1.2). + The compiled jar will be in `vulkan/build/libs/`. ## Source Code Setup ### Prerequisites -* JDK 21 or newer — https://www.oracle.com/java/technologies/downloads/ +* JDK 21+ for MC 1.20.6 builds; **JDK 25+** for MC 26.1.x (Gradle auto-downloads via toolchains) * Git — https://git-scm.com/ ### IntelliJ IDEA diff --git a/buildSrc/.DS_Store b/buildSrc/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..74e6c6d5d2180f79466cdf141ee0b6c4c3ff017b GIT binary patch literal 6148 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 CAtvDf literal 0 HcmV?d00001 diff --git a/docs/curseforge_description.md b/docs/curseforge_description.md index 9b4371c..d87c733 100644 --- a/docs/curseforge_description.md +++ b/docs/curseforge_description.md @@ -22,8 +22,8 @@ An extension mod that makes [Distant Horizons](https://www.curseforge.com/minecr **Requirements:** - Fabric -- MC 1.20.6 or 1.21.11 -- VulkanMod must be installed. 0.6+ for 1.21.11 and 0.4.2 for 1.20.6 +- MC 1.20.6 or 26.1 / 26.1.1 / 26.1.2 +- VulkanMod must be installed. 0.6.6+ for 26.1.x and 0.4.2 for 1.20.6 - Distant Horizons 2.4.0+ or 3.0.0+ must be installed > This is not a standalone mod. Both Distant Horizons and VulkanMod are required. diff --git a/gradle.properties b/gradle.properties index 6a36c41..affe50c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,12 +2,13 @@ org.gradle.jvmargs=-Xmx4096M org.gradle.parallel=true org.gradle.caching=true -org.gradle.java.home=/Library/Java/JavaVirtualMachines/zulu-21.jdk/Contents/Home +# MC 26.1+ needs Java 25+ for Gradle; MC 1.20.6 builds work with Java 21+ +# org.gradle.java.home=/Library/Java/JavaVirtualMachines/jdk-25.jdk/Contents/Home # Mod Info mod_name=DistantHorizons-VulkanMod mod_version=2.4.0-3.0.0+vm.2 -api_version=5.1.0 +api_version=6.1.1 maven_group=com.seibel.distanthorizons mod_readable_name=Distant Horizons for VulkanMod mod_description=VulkanMod port of Distant Horizons. This mod generates and renders simplified terrain beyond the normal view distance at a low performance cost. Allowing you to see much farther without turning your game into a slideshow. @@ -52,7 +53,7 @@ versionStr= # This defines what MC version Intellij will use for the preprocessor # and what version is used automatically by build and run commands -mcVer=1.21.11 +mcVer=26.1.2 # Defines the maximum amount of memory Minecraft is allowed when run in a development environment #minecraftMemoryJavaArg="-Xmx4G" diff --git a/gradle/.DS_Store b/gradle/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..7fbcbb679b3f7a058a566f6f7801216e96bb632b GIT binary patch literal 6148 zcmeHKJ8r`;3?wdt&GyY__LLC?!g0nEXjFg-Pys4H1*pJ{703eHyxjO)9!CYJ!2egkz7GX%SQDo}|8!vR767pr@)|#X7izWvu1~)eml-Do-SGgIZ^>CaIU~} zELT?l-{4pJ|8o*oRDcRRlmfcw-n$l0%Gx@6oYmR_|A1T032uhDQ!scr26{Qh!piZh cCq-VdIreMf6zFusoet#BfayY`0{2$n7dHVFrvLx| literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index cea7a79..dbc3ce4 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle b/settings.gradle index 2353b5d..6b8b652 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,12 +8,22 @@ pluginManagement { gradlePluginPortal() mavenLocal() } + plugins { + id "dev.architectury.loom" version "1.13-SNAPSHOT" + id "net.fabricmc.fabric-loom" version "1.16-SNAPSHOT" + id "systems.manifold.manifold-gradle-plugin" version "0.0.2-alpha" + id "org.gradle.toolchains.foojay-resolver-convention" version "1.0.0" + } +} + +plugins { + id "org.gradle.toolchains.foojay-resolver-convention" } /** Loads version properties for the selected Minecraft version. */ def loadProperties() { - def defaultMcVersion = "1.21.11" + def defaultMcVersion = "26.1.2" def mcVersion = "" def mcVers = fileTree("versionProperties").files.name for (int i = 0; i < mcVers.size(); i++) { diff --git a/versionProperties/1.21.11.properties b/versionProperties/26.1.2.properties similarity index 57% rename from versionProperties/1.21.11.properties rename to versionProperties/26.1.2.properties index 23ae464..f4b720a 100644 --- a/versionProperties/1.21.11.properties +++ b/versionProperties/26.1.2.properties @@ -1,10 +1,12 @@ -# 1.21.11 version (VulkanMod port - Fabric only) -java_version=21 -minecraft_version=1.21.11 -parchment_version=1.21:2024.07.28 -compatible_minecraft_versions=["1.21.11"] -accessWidenerVersion=1_21_11 +# 26.1.2 version (VulkanMod port - Fabric only) +# Single jar supports 26.1, 26.1.1, and 26.1.2+ (matches DH / VulkanMod releases) +java_version=25 +minecraft_version=26.1.2 +parchment_version= +compatible_minecraft_versions=["26.1","26.1.1","26.1.2"] +accessWidenerVersion=26_1_2 builds_for=fabric +unobfuscated=true # Netty netty_version=4.1.97.Final @@ -13,8 +15,8 @@ netty_version=4.1.97.Final lwjgl_version=3.3.3 # Fabric loader -fabric_loader_version=0.17.3 -fabric_api_version=0.139.4+1.21.11 +fabric_loader_version=0.18.4 +fabric_api_version=0.149.1+26.1.2 modmenu_version=17.0.0-alpha.1 starlight_version_fabric= phosphor_version_fabric= @@ -29,9 +31,6 @@ fabric_api_version=0.139.4+1.21.11 fabric_recommend_list={} # Fabric mod run - all disabled for VulkanMod port - # 0 = Don't enable and don't run - # 1 = Can be referenced in code but doesn't run - # 2 = Can be referenced in code and runs in client enable_mod_menu=2 enable_starlight=0 enable_phosphor=0 @@ -42,5 +41,5 @@ fabric_api_version=0.139.4+1.21.11 enable_immersive_portals=0 enable_canvas=0 -# Empty stubs for root build.gradle processResources (references these even for Fabric-only builds) +# Empty stubs for root build.gradle processResources neoforge_version_range= diff --git a/vulkan/.DS_Store b/vulkan/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..16d875f048b003f89438f610b00ecfc05d69253a GIT binary patch literal 6148 zcmeH~J&pn~427Thk&tL8DbsL(y+MTF1YBUnPJ=WO#fm;h=h<(?J6KYLuU74ZjM<6h0 J5P^Rs@C1L66M6su literal 0 HcmV?d00001 diff --git a/vulkan/build.gradle b/vulkan/build.gradle index 8846a02..80bbf02 100644 --- a/vulkan/build.gradle +++ b/vulkan/build.gradle @@ -1,19 +1,36 @@ plugins { - id "dev.architectury.loom" version "1.13-SNAPSHOT" + id "net.fabricmc.fabric-loom" version "1.16-SNAPSHOT" id "systems.manifold.manifold-gradle-plugin" version "0.0.2-alpha" } -version = rootProject.mod_version -archivesBaseName = "DistantHorizons-VulkanMod-fabric" +def mcVer = rootProject.minecraft_version +def isUnobfuscatedMc = mcVer.startsWith("26.") -jar { - archiveFileName = "${archivesBaseName}-${version}-mc${rootProject.minecraft_version}.jar" +sourceSets { + main { + resources { + if (isUnobfuscatedMc) { + srcDir "src/main/resources-mc26" + } else { + srcDir "src/main/resources-legacy" + } + } + if (isUnobfuscatedMc) { + java { + exclude "**/dh24/**" + exclude "**/mixin/dh24/**" + } + } + } } -remapJar { - inputFile = jar.archiveFile - archiveFileName = "DistantHorizons-VulkanMod-fabric-${version}-mc${rootProject.minecraft_version}.jar" - dependsOn jar +version = rootProject.mod_version +base { + archivesName = "DistantHorizons-VulkanMod-fabric" +} + +jar { + archiveFileName.set("${base.archivesName.get()}-${version}-mc${rootProject.minecraft_version}.jar") } processResources { @@ -22,17 +39,16 @@ processResources { inputs.property "minecraft_version", rootProject.minecraft_version inputs.property "vulkanmod_min_version", vmMinVersion filesMatching("fabric.mod.json") { - expand "version": project.version, "minecraft_version": rootProject.minecraft_version, "vulkanmod_min_version": vmMinVersion + expand "version": project.version, + "minecraft_version": rootProject.minecraft_version, + "vulkanmod_min_version": vmMinVersion } } -// Manifold preprocessor version manifold { manifoldVersion = "2025.1.31" } -// Resolve DH and VulkanMod jars dynamically based on MC version -def mcVer = rootProject.minecraft_version def dhJar = fileTree("${rootDir}/jars").matching { include "DistantHorizons-*-${mcVer}-*.jar" }.files def vmJar = fileTree("${rootDir}/jars").matching { include "VulkanMod_${mcVer}-*.jar" }.files @@ -41,24 +57,34 @@ if (vmJar.isEmpty()) throw new GradleException("No VulkanMod jar found for MC ${ dependencies { minecraft "com.mojang:minecraft:${mcVer}" - mappings loom.layered() { - officialMojangMappings() - parchment("org.parchmentmc.data:parchment-${rootProject.parchment_version}@zip") - } - // Fabric loader + API - modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" - modImplementation "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}" - - // Distant Horizons — compile against all matched jars (DH 2.4 + DH 3.0) - dhJar.each { modCompileOnly files(it) } - // VulkanMod — compile against the jar - modCompileOnly files(vmJar.first()) + if (isUnobfuscatedMc) { + implementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" + implementation "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}" + dhJar.each { compileOnly files(it) } + compileOnly files(vmJar.first()) + } else { + mappings loom.layered() { + officialMojangMappings() + parchment("org.parchmentmc.data:parchment-${rootProject.parchment_version}@zip") + } + modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" + modImplementation "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}" + dhJar.each { modCompileOnly files(it) } + modCompileOnly files(vmJar.first()) + } - // LWJGL vulkan types (VkCommandBuffer, MemoryStack) surfaced by VulkanMod's API compileOnly "org.lwjgl:lwjgl:${rootProject.lwjgl_version}" compileOnly "org.lwjgl:lwjgl-vulkan:${rootProject.lwjgl_version}" - - // Manifold preprocessor annotationProcessor("systems.manifold:manifold-preprocessor:2025.1.31") } + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(rootProject.java_version as int) + } +} + +tasks.withType(JavaCompile).configureEach { + options.release = rootProject.java_version as int +} diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/DhVulkanMixinPlugin.java b/vulkan/src/main/java/com/braffolk/dhvulkan/DhVulkanMixinPlugin.java index 9480008..123e30e 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/DhVulkanMixinPlugin.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/DhVulkanMixinPlugin.java @@ -1,5 +1,7 @@ package com.braffolk.dhvulkan; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.objectweb.asm.tree.ClassNode; import org.spongepowered.asm.mixin.Mixins; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; @@ -24,6 +26,8 @@ */ public class DhVulkanMixinPlugin implements IMixinConfigPlugin { + private static final Logger LOGGER = LogManager.getLogger("DH-VulkanMod"); + private static final String DH_CONFIG_NAME = "DistantHorizons.fabric.mixins.json"; private static final String DH_MIXIN_TO_REMOVE = "client.MixinTextureUtil"; // DH 3.0's MixinSharedConstants sets IS_RUNNING_IN_IDE = true, which enables @@ -34,7 +38,7 @@ public class DhVulkanMixinPlugin implements IMixinConfigPlugin { @Override public void onLoad(String mixinPackage) { - System.out.println("[DH-VulkanMod] Mixin plugin loaded, resolving DH/VulkanMod mixin conflicts..."); + LOGGER.debug("Resolving DH/VulkanMod mixin conflicts..."); boolean removed = false; try { @@ -45,12 +49,12 @@ public void onLoad(String mixinPackage) { continue; } - System.out.println("[DH-VulkanMod] Found DH config: " + configName); + LOGGER.debug("Found DH config: {}", configName); // Config.getConfig() returns the internal MixinConfig Object mixinConfig = getFieldValue(config, "config"); if (mixinConfig == null) { - System.err.println("[DH-VulkanMod] Could not access internal MixinConfig"); + LOGGER.warn("Could not access internal MixinConfig"); continue; } @@ -71,28 +75,16 @@ public void onLoad(String mixinPackage) { if (clientMixins != null) { if (clientMixins.remove(DH_MIXIN_TO_REMOVE)) { removed = true; - System.out.println("[DH-VulkanMod] ✓ Removed " + DH_MIXIN_TO_REMOVE - + " from DH config — TextureUtil conflict resolved"); + LOGGER.debug("Removed {} from DH config (TextureUtil conflict)", DH_MIXIN_TO_REMOVE); } if (clientMixins.remove(DH_MIXIN_SHARED_CONSTANTS)) { removed = true; - System.out.println("[DH-VulkanMod] ✓ Removed " + DH_MIXIN_SHARED_CONSTANTS - + " from DH config — prevents VulkanMod validation crash"); + LOGGER.debug("Removed {} from DH config (validation crash)", DH_MIXIN_SHARED_CONSTANTS); } } - if (!removed) { - System.out.println("[DH-VulkanMod] No conflicting DH mixins found in config" - + " (may not exist in this DH version — no conflict)"); - } } } catch (Exception e) { - System.err.println("[DH-VulkanMod] WARNING: Failed to strip DH's MixinTextureUtil: " + e); - e.printStackTrace(); - } - - if (!removed) { - System.err.println("[DH-VulkanMod] Could not remove conflicting DH mixins from DH config."); - System.err.println("[DH-VulkanMod] If a mixin crash occurs, add JVM arg: -Dmixin.checks=false"); + LOGGER.warn("Failed to strip conflicting DH mixins from DH config", e); } } @@ -157,10 +149,10 @@ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { "com.seibel.distanthorizons.core.wrapperInterfaces.render.AbstractDhRenderApiDefinition" ); isDh3Present = true; - System.out.println("[DH-VulkanMod] DH 3.0 detected. Using API integration + dh3 mixins."); + LOGGER.debug("DH 3.0 detected; using API integration + dh3 mixins."); } catch (ClassNotFoundException e) { isDh3Present = false; - System.out.println("[DH-VulkanMod] DH 2.4 detected. Using mixin integration + dh24 mixins."); + LOGGER.debug("DH 2.4 detected; using mixin integration + dh24 mixins."); } } diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/DhVulkanModEntrypoint.java b/vulkan/src/main/java/com/braffolk/dhvulkan/DhVulkanModEntrypoint.java index 31bf307..613e32a 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/DhVulkanModEntrypoint.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/DhVulkanModEntrypoint.java @@ -5,11 +5,17 @@ import com.braffolk.dhvulkan.config.DhVulkanConfig; import com.braffolk.dhvulkan.core.VulkanBackend; import com.braffolk.dhvulkan.core.VulkanRenderEngine; -import com.braffolk.dhvulkan.dh24.Dh24Integration; import com.braffolk.dhvulkan.compat.Compat; +#if MC_VER < MC_26_1_2 +import com.braffolk.dhvulkan.dh24.Dh24Integration; +#endif import com.mojang.brigadier.arguments.IntegerArgumentType; import net.fabricmc.api.ClientModInitializer; +#if MC_VER >= MC_26_1_2 +import net.fabricmc.fabric.api.client.command.v2.ClientCommands; +#else import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +#endif import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.minecraft.network.chat.Component; import org.apache.logging.log4j.LogManager; @@ -32,14 +38,18 @@ public class DhVulkanModEntrypoint implements ClientModInitializer { @Override public void onInitializeClient() { - LOGGER.info("[DH-VulkanMod] Extension mod initializing..."); + LOGGER.debug("[DH-VulkanMod] Extension mod initializing..."); DhVulkanConfig config = DhVulkanConfig.get(); - LOGGER.info("[DH-VulkanMod] Config loaded. vulkanRenderMode={}", config.vulkanRenderMode); + LOGGER.debug("[DH-VulkanMod] Config loaded. vulkanRenderMode={}", config.vulkanRenderMode); // Register /dh-debug <0-6> client command ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { + #if MC_VER >= MC_26_1_2 + dispatcher.register(ClientCommands.literal("dh-debug") + #else dispatcher.register(ClientCommandManager.literal("dh-debug") + #endif .executes(ctx -> { int mode = DhVulkanConfig.get().vulkanRenderMode; String name = mode >= 0 && mode < MODE_NAMES.length ? MODE_NAMES[mode] : "Unknown"; @@ -47,7 +57,11 @@ public void onInitializeClient() { "\u00a7b[DH-Vulkan]\u00a7r Render mode: " + mode + " (" + name + ")")); return 1; }) + #if MC_VER >= MC_26_1_2 + .then(ClientCommands.argument("mode", IntegerArgumentType.integer(0, 6)) + #else .then(ClientCommandManager.argument("mode", IntegerArgumentType.integer(0, 6)) + #endif .executes(ctx -> { int mode = IntegerArgumentType.getInteger(ctx, "mode"); DhVulkanConfig.get().vulkanRenderMode = mode; @@ -64,31 +78,46 @@ public void onInitializeClient() { return; } - LOGGER.info("[DH-VulkanMod] VulkanMod detected. Vulkan rendering backend will be used."); + LOGGER.info("[DH-VulkanMod] Loaded (VulkanMod + Distant Horizons)."); // Create the shared Vulkan backend VulkanBackend backend = new VulkanRenderEngine(); // Detect DH version and initialize the appropriate integration DhVersionDetector.DhVersion dhVersion = DhVersionDetector.detect(); - LOGGER.info("[DH-VulkanMod] Detected DH version: {}", dhVersion); + LOGGER.debug("[DH-VulkanMod] Detected DH version: {}", dhVersion); switch (dhVersion) { case DH_3_0: - com.braffolk.dhvulkan.api.ApiDhIntegration apiIntegration = new com.braffolk.dhvulkan.api.ApiDhIntegration(); - apiIntegration.initialize(backend); - activeIntegration = apiIntegration; + com.braffolk.dhvulkan.api.ApiDhIntegration existing = + com.braffolk.dhvulkan.api.ApiDhIntegration.getInstance(); + if (existing != null) { + activeIntegration = existing; + LOGGER.debug("[DH-VulkanMod] Reusing API integration (initialized during DH DependencySetup)."); + } else { + com.braffolk.dhvulkan.api.ApiDhIntegration apiIntegration = + new com.braffolk.dhvulkan.api.ApiDhIntegration(); + apiIntegration.initialize(backend); + activeIntegration = apiIntegration; + } break; + #if MC_VER < MC_26_1_2 case DH_2_4: default: activeIntegration = new Dh24Integration(); activeIntegration.initialize(backend); break; + #else + default: + LOGGER.error("[DH-VulkanMod] DH 3.0 is required for Minecraft 26.1+"); + break; + #endif } - LOGGER.info("[DH-VulkanMod] Using integration: {}", activeIntegration.getName()); + LOGGER.debug("[DH-VulkanMod] Using integration: {}", activeIntegration.getName()); } + #if MC_VER < MC_26_1_2 /** * Called from MixinLodRenderer before the first render pass to wire the * delegate. Only applies to DH 2.4 path. @@ -98,12 +127,18 @@ public static void wireIfNeeded() { ((Dh24Integration) activeIntegration).wireIfNeeded(); } } + #endif /** Get the active integration (for mixins that need it) */ public static DhIntegration getActiveIntegration() { return activeIntegration; } + /** Called from MixinDependencySetup when DH setup runs before this entrypoint. */ + public static void setActiveIntegration(DhIntegration integration) { + activeIntegration = integration; + } + /** * Called from MixinLevelRenderer at renderLevel @RETURN to read MC's depth * buffer while the swapchain depth is in a known-good Vulkan image layout. diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/api/ApiDhIntegration.java b/vulkan/src/main/java/com/braffolk/dhvulkan/api/ApiDhIntegration.java index 9436e7a..f464672 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/api/ApiDhIntegration.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/api/ApiDhIntegration.java @@ -23,7 +23,7 @@ public void initialize(VulkanBackend backend) { this.backend = backend; this.renderApi = new VkRenderApiDefinition(backend); instance = this; - LOGGER.info("[DH-VulkanMod] DH 3.0 API integration created (renderer binding deferred to DH setup)."); + LOGGER.debug("[DH-VulkanMod] DH 3.0 API integration created (renderer binding deferred to DH setup)."); } @Override @@ -40,7 +40,7 @@ public String getName() { public void bindRenderApi() { if (renderApi != null) { renderApi.bindRenderers(); - LOGGER.info("[DH-VulkanMod] Vulkan renderers bound into DH's SingletonInjector."); + LOGGER.info("[DH-VulkanMod] Vulkan LOD renderer active for Distant Horizons 3.0."); } } diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/api/VkRenderApiDefinition.java b/vulkan/src/main/java/com/braffolk/dhvulkan/api/VkRenderApiDefinition.java index be83959..f0c4933 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/api/VkRenderApiDefinition.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/api/VkRenderApiDefinition.java @@ -15,6 +15,8 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.ILodContainerUniformBufferWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IVertexBufferWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.*; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; /** * Vulkan implementation of DH 3.0's render API definition. @@ -53,6 +55,11 @@ public VkRenderApiDefinition(VulkanBackend backend) { @Override public String getApiName() { return "VulkanMod"; } + @Override + public boolean useSingleIbo() { + return true; + } + // Singletons @Override public IDhMetaRenderer getMetaRenderer() { return metaRenderer; } @Override public IDhTerrainRenderer getTerrainRenderer() { return terrainRenderer; } @@ -93,10 +100,12 @@ static RenderUniforms toUniforms(RenderParams params, RenderUniforms target) { * This is the main lifecycle manager connecting DH's render loop to our Vulkan engine. */ static class VkMetaRenderer implements IDhMetaRenderer { + private static final Logger LOGGER = LogManager.getLogger("DH-VulkanMod"); private final VulkanBackend backend; private final RenderUniforms cachedUniforms = new RenderUniforms(); private boolean frameActive = false; private boolean initialized = false; + private static boolean loggedFirstPass = false; VkMetaRenderer(VulkanBackend backend) { this.backend = backend; @@ -104,6 +113,10 @@ static class VkMetaRenderer implements IDhMetaRenderer { @Override public void runRenderPassSetup(RenderParams renderParams) { + if (!loggedFirstPass) { + loggedFirstPass = true; + LOGGER.debug("[DH-VulkanMod] DH 3.0 render pass started (Vulkan meta renderer)."); + } // Deferred init: VulkanMod's VkDevice is only ready at render time if (!initialized) { backend.init(); @@ -297,5 +310,10 @@ public void add(IDhApiRenderableBoxGroup cubeGroup) throws IllegalArgumentExcept public IDhApiRenderableBoxGroup remove(long id) { return null; // Not yet implemented } + + @Override + public void close() { + // No persistent GPU resources for generic renderer yet + } } } diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/api/VkVertexBufferWrapper.java b/vulkan/src/main/java/com/braffolk/dhvulkan/api/VkVertexBufferWrapper.java index f6f85e6..2d3f6f0 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/api/VkVertexBufferWrapper.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/api/VkVertexBufferWrapper.java @@ -34,13 +34,11 @@ public VkVertexBufferWrapper(VulkanBackend backend) { } // [DH 2.4 COMPAT] DH 2.4 calls upload(); DH 3.0 calls uploadVertexBuffer(). - // Remove this method when dropping DH 2.4 support. - @Override public void upload(ByteBuffer buffer, int vertexCount) { uploadVertexBufferImpl(buffer, vertexCount); } - // DH 3.0 interface methods + @Override public void uploadVertexBuffer(ByteBuffer buffer, int vertexCount) { uploadVertexBufferImpl(buffer, vertexCount); } diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/compat/Compat.java b/vulkan/src/main/java/com/braffolk/dhvulkan/compat/Compat.java index 6c7c2d3..cfd3ac6 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/compat/Compat.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/compat/Compat.java @@ -232,25 +232,46 @@ public static void drawIndexed(Object vertexBuffer, Object indexBuffer, int inde // VertexFormatElement // // ========================= // + /** Semantic role of a vertex attribute (replaces removed VertexFormatElement.Usage on MC 26.1+). */ + public enum ElementUsage { + POSITION, + COLOR, + GENERIC, + UV + } + public static VertexFormatElement vertexFormatElement( int id, int index, - VertexFormatElement.Type type, VertexFormatElement.Usage usage, + VertexFormatElement.Type type, ElementUsage usage, int count) { - #if MC_VER >= MC_1_21_1 - return new VertexFormatElement(id, index, type, usage, count); + #if MC_VER >= MC_26_1_2 + // MC 26.1: register() assigns a global BY_ID slot — ids 0–7 are taken by POSITION, COLOR, etc. + // Custom DH/Vulkan formats must use the record constructor (format-local ids are fine). + boolean normalized = usage == ElementUsage.COLOR && type == VertexFormatElement.Type.UBYTE; + return new VertexFormatElement(id, index, type, normalized, count); + #elif MC_VER >= MC_1_21_1 + VertexFormatElement.Usage mapped = mapElementUsage(usage); + return new VertexFormatElement(id, index, type, mapped, count); #else - // MC 1.20: VertexFormatElement(id, Type, Usage, count) - // Non-UV usages MUST have id=0 (MC validates this at construction). - // CRITICAL: Do NOT remap GENERIC→UV! VulkanMod's UV handler doesn't - // support INT type, resulting in VK_FORMAT_UNDEFINED → DEVICE_LOST. - // GENERIC with id=0 is valid and VulkanMod maps INT→VK_FORMAT_R32_SINT. - if (usage == VertexFormatElement.Usage.UV) { - return new VertexFormatElement(id, type, usage, count); + VertexFormatElement.Usage mapped = mapElementUsage(usage); + if (mapped == VertexFormatElement.Usage.UV) { + return new VertexFormatElement(id, type, mapped, count); } - return new VertexFormatElement(0, type, usage, count); + return new VertexFormatElement(0, type, mapped, count); #endif } + #if MC_VER < MC_26_1_2 + private static VertexFormatElement.Usage mapElementUsage(ElementUsage usage) { + return switch (usage) { + case POSITION -> VertexFormatElement.Usage.POSITION; + case COLOR -> VertexFormatElement.Usage.COLOR; + case GENERIC -> VertexFormatElement.Usage.GENERIC; + case UV -> VertexFormatElement.Usage.UV; + }; + } + #endif + // ========================= // // VertexFormat builder // // ========================= // @@ -356,7 +377,11 @@ public static void addUniformWithBuffer( net.vulkanmod.vulkan.shader.layout.Uniform.Info info = net.vulkanmod.vulkan.shader.layout.Uniform.createUniformInfo(type, name, count); info.setBufferSupplier(bufferSupplier); + #if MC_VER >= MC_26_1_2 + builder.addUniform(info); + #else builder.addUniformInfo(info); + #endif #else builder.addUniformInfo(type, name, count); #endif @@ -398,18 +423,56 @@ public static void buildAndSetPushConstants( net.vulkanmod.vulkan.shader.layout.Uniform.Info info = net.vulkanmod.vulkan.shader.layout.Uniform.createUniformInfo(type, name, count); info.setBufferSupplier(bufferSupplier); + #if MC_VER >= MC_26_1_2 + pcBuilder.addUniform(info); + #else pcBuilder.addUniformInfo(info); + #endif try { java.lang.reflect.Field pcField = net.vulkanmod.vulkan.shader.Pipeline.Builder.class.getDeclaredField("pushConstants"); pcField.setAccessible(true); + #if MC_VER >= MC_26_1_2 + int stages = org.lwjgl.vulkan.VK10.VK_SHADER_STAGE_VERTEX_BIT + | org.lwjgl.vulkan.VK10.VK_SHADER_STAGE_FRAGMENT_BIT; + pcField.set(pipelineBuilder, pcBuilder.buildPushConstant(stages)); + #else pcField.set(pipelineBuilder, pcBuilder.buildPushConstant()); + #endif } catch (Exception e) { throw new RuntimeException("[DH-Vulkan] Failed to set push constants on pipeline builder", e); } #endif } + /** + * Attach GLSL sources to a pipeline builder (API differs between VM 0.6.1 and 0.6.6+). + */ + public static void compileShaders( + net.vulkanmod.vulkan.shader.Pipeline.Builder builder, + String name, String vertSource, String fragSource) { + #if MC_VER >= MC_26_1_2 + builder.setShaderSrc(net.vulkanmod.vulkan.shader.SPIRVUtils.ShaderKind.VERTEX_SHADER, vertSource); + builder.setShaderSrc(net.vulkanmod.vulkan.shader.SPIRVUtils.ShaderKind.FRAGMENT_SHADER, fragSource); + #else + builder.compileShaders(name, vertSource, fragSource); + #endif + } + + /** + * Create a combined image sampler descriptor (VulkanMod 0.6.6+ / MC 26.1). + */ + public static net.vulkanmod.vulkan.shader.descriptor.ImageDescriptor imageDescriptor( + int binding, String qualifier, String name, int imageIdx) { + #if MC_VER >= MC_26_1_2 + return new net.vulkanmod.vulkan.shader.descriptor.ImageDescriptor( + binding, qualifier, name, imageIdx, + org.lwjgl.vulkan.VK10.VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); + #else + return new net.vulkanmod.vulkan.shader.descriptor.ImageDescriptor(binding, qualifier, name, imageIdx); + #endif + } + /** * Per-draw state application: * - VM 0.6.1: issues vkCmdPushConstants (12 bytes, zero-copy to cmd buffer) @@ -448,7 +511,16 @@ public static void setUniformSuppliers( public static VulkanImage getLightmapVulkanImage() { try { - #if MC_VER >= MC_1_21_1 + #if MC_VER >= MC_26_1_2 + var lightmapView = net.minecraft.client.Minecraft.getInstance() + .gameRenderer.lightmap(); + if (lightmapView == null) return null; + com.mojang.blaze3d.textures.GpuTexture gpuTex = lightmapView.texture(); + if (!(gpuTex instanceof com.mojang.blaze3d.opengl.GlTexture glTex)) return null; + net.vulkanmod.gl.VkGlTexture vkGlTex = + net.vulkanmod.gl.VkGlTexture.getTexture(glTex.glId()); + return vkGlTex != null ? vkGlTex.getVulkanImage() : null; + #elif MC_VER >= MC_1_21_1 var lightmapView = net.minecraft.client.Minecraft.getInstance() .gameRenderer.lightTexture().getTextureView(); if (lightmapView == null) return null; @@ -543,7 +615,7 @@ public static void prepareMcDepthForSampling(int slot, VulkanImage depthImage) { VK_IMAGE_ASPECT_DEPTH_BIT, 1, depthImage.mipLevels); lastDepthImageId = imageId; - LOGGER.info("[DH-Vulkan] Created depth-only view for D+S format={} aspect={} (view={})", + LOGGER.debug("[DH-Vulkan] Created depth-only view for D+S format={} aspect={} (view={})", depthImage.format, depthImage.aspect, depthOnlyView); } @@ -712,7 +784,7 @@ public static VulkanImage copyMcDepthForSampling(VulkanImage srcDepth) { copyUsage, false, true); mcDepthCopyWidth = srcDepth.width; mcDepthCopyHeight = srcDepth.height; - LOGGER.info("[DH-Vulkan] Created MC depth copy image: {}x{} format={}", + LOGGER.debug("[DH-Vulkan] Created MC depth copy image: {}x{} format={}", srcDepth.width, srcDepth.height, srcDepth.format); } diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/config/DhVulkanConfig.java b/vulkan/src/main/java/com/braffolk/dhvulkan/config/DhVulkanConfig.java index 22b1635..52d16ee 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/config/DhVulkanConfig.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/config/DhVulkanConfig.java @@ -3,6 +3,8 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import net.fabricmc.loader.api.FabricLoader; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import java.io.IOException; import java.nio.file.*; @@ -13,6 +15,8 @@ */ public class DhVulkanConfig { + private static final Logger LOGGER = LogManager.getLogger("DH-VulkanMod"); + private static final Path CONFIG_PATH = FabricLoader.getInstance() .getConfigDir().resolve("dh-vulkanmod.json"); private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); @@ -56,7 +60,7 @@ private static DhVulkanConfig load() { if (config != null) return config; } catch (Exception e) { - System.err.println("[DH-VulkanMod] Failed to load config, using defaults: " + e.getMessage()); + LOGGER.warn("Failed to load config, using defaults: {}", e.getMessage()); } } // Create default config @@ -70,7 +74,7 @@ public void save() { Files.createDirectories(CONFIG_PATH.getParent()); Files.writeString(CONFIG_PATH, GSON.toJson(this)); } catch (IOException e) { - System.err.println("[DH-VulkanMod] Failed to save config: " + e.getMessage()); + LOGGER.warn("Failed to save config: {}", e.getMessage()); } } } diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/core/DhConfigHelper.java b/vulkan/src/main/java/com/braffolk/dhvulkan/core/DhConfigHelper.java index f3080e3..5446052 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/core/DhConfigHelper.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/core/DhConfigHelper.java @@ -80,7 +80,11 @@ public static boolean whiteWorldEnabled() { // =================== // public static boolean ssaoEnabled() { + #if MC_VER >= MC_26_1_2 + return Config.Client.Advanced.Graphics.enableSsao.get(); + #else return Config.Client.Advanced.Graphics.Ssao.enableSsao.get(); + #endif } // =================== // @@ -211,7 +215,7 @@ public static float applyVelocityReduction(float overdraw) { if (!velocityDiagLogged) { velocityDiagLogged = true; - LOGGER.info("[DH-VulkanMod] Velocity overdraw active: speed={}, overdraw={}", + LOGGER.debug("[DH-VulkanMod] Velocity overdraw active: speed={}, overdraw={}", String.format("%.1f", speedAverage), String.format("%.3f", overdraw)); } } diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/core/DhFrameProfiler.java b/vulkan/src/main/java/com/braffolk/dhvulkan/core/DhFrameProfiler.java index f4163b8..e3ad8b0 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/core/DhFrameProfiler.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/core/DhFrameProfiler.java @@ -160,7 +160,7 @@ private void log() { intervalGcCount, intervalGcTimeMs)); - LOGGER.info("[DH-Perf] {}", sb); + LOGGER.debug("[DH-Perf] {}", sb); } private void snapshotGc() { diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/core/DhVulkanFramebuffer.java b/vulkan/src/main/java/com/braffolk/dhvulkan/core/DhVulkanFramebuffer.java index a2a15f0..cba845f 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/core/DhVulkanFramebuffer.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/core/DhVulkanFramebuffer.java @@ -58,7 +58,7 @@ public void init(int width, int height) { // Recreate when VulkanMod resizes the swap chain Renderer.getInstance().addOnResizeCallback(this::onResize); - LOGGER.info("[DH-Vulkan] DhVulkanFramebuffer created ({}x{})", width, height); + LOGGER.debug("[DH-Vulkan] DhVulkanFramebuffer created ({}x{})", width, height); } private void createFramebufferAndPass() { @@ -117,7 +117,7 @@ private void onResize() { return; // No change } - LOGGER.info("[DH-Vulkan] Resizing DhVulkanFramebuffer: {}x{} -> {}x{}", + LOGGER.debug("[DH-Vulkan] Resizing DhVulkanFramebuffer: {}x{} -> {}x{}", this.width, this.height, newWidth, newHeight); // Clean up old render pass and framebuffer @@ -163,6 +163,6 @@ public void cleanup() { this.framebuffer.cleanUp(); this.framebuffer = null; } - LOGGER.info("[DH-Vulkan] DhVulkanFramebuffer cleaned up."); + LOGGER.debug("[DH-Vulkan] DhVulkanFramebuffer cleaned up."); } } diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/core/VulkanCloudRenderer.java b/vulkan/src/main/java/com/braffolk/dhvulkan/core/VulkanCloudRenderer.java index 348a550..673d721 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/core/VulkanCloudRenderer.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/core/VulkanCloudRenderer.java @@ -167,7 +167,11 @@ else if (centerY > 0.0f) else yState = Y_INSIDE_CLOUDS; + #if MC_VER >= MC_26_1_2 + CloudStatus cloudsType = mc.options.getCloudStatus(); + #else CloudStatus cloudsType = mc.options.getCloudsType(); + #endif // Rebuild mesh when camera cell changes if (centerCellX != this.prevCloudX || centerCellZ != this.prevCloudZ @@ -391,7 +395,7 @@ private void loadCloudTexture() { this.cloudGridWidth = width; this.cloudRenderFaces = computeRenderFaces(); this.textureLoaded = true; - LOGGER.info("[DH-VulkanMod] Cloud texture loaded: {}x{}", width, height); + LOGGER.debug("[DH-VulkanMod] Cloud texture loaded: {}x{}", width, height); } catch (Exception e) { LOGGER.error("[DH-VulkanMod] Failed to load cloud texture", e); } @@ -458,7 +462,7 @@ private void resolveReflection() { // Requires VM 0.6+ getCloudsPipeline() Method getCloudsPipelineMethod = pipelineManagerClass.getMethod("getCloudsPipeline"); this.cloudsPipeline = (GraphicsPipeline) getCloudsPipelineMethod.invoke(null); - LOGGER.info("[DH-VulkanMod] Cloud pipeline: using VM 0.6 getCloudsPipeline()"); + LOGGER.debug("[DH-VulkanMod] Cloud pipeline: using VM 0.6 getCloudsPipeline()"); if (this.cloudsPipeline == null) { throw new RuntimeException("Cloud pipeline is null"); @@ -486,9 +490,9 @@ private void resolveReflection() { this.vboCloseHandle = lookup.unreflect( vboClass.getMethod("close")); - LOGGER.info("[DH-VulkanMod] Cloud renderer MethodHandles resolved (VM 0.6)."); + LOGGER.debug("[DH-VulkanMod] Cloud renderer MethodHandles resolved (VM 0.6)."); } catch (Exception e) { - LOGGER.info("[DH-VulkanMod] VM 0.6 cloud API not available, custom cloud renderer disabled. ({})", + LOGGER.debug("[DH-VulkanMod] VM 0.6 cloud API not available, custom cloud renderer disabled. ({})", e.getMessage()); this.reflectionFailed = true; } diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/core/VulkanRenderContext.java b/vulkan/src/main/java/com/braffolk/dhvulkan/core/VulkanRenderContext.java index 6019ca2..80b6ef0 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/core/VulkanRenderContext.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/core/VulkanRenderContext.java @@ -12,7 +12,6 @@ import com.mojang.blaze3d.vertex.VertexFormatElement; import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.util.math.Mat4f; import com.seibel.distanthorizons.core.util.math.Vec3f; import net.vulkanmod.vulkan.Drawer; @@ -104,11 +103,11 @@ public void init() { return; } - LOGGER.info("[DH-Vulkan] Initializing VulkanRenderContext..."); + LOGGER.debug("[DH-Vulkan] Initializing VulkanRenderContext..."); try { this.terrainPipeline = createTerrainPipeline(); this.initialized = true; - LOGGER.info("[DH-Vulkan] VulkanRenderContext initialized."); + LOGGER.debug("[DH-Vulkan] VulkanRenderContext initialized."); } catch (Exception e) { LOGGER.error("[DH-Vulkan] Failed to initialize VulkanRenderContext", e); throw new RuntimeException("DH Vulkan initialization failed", e); @@ -125,11 +124,11 @@ public void init() { private static final VertexFormat DH_TERRAIN_FORMAT; static { VertexFormatElement position = Compat.vertexFormatElement(0, 0, - VertexFormatElement.Type.SHORT, VertexFormatElement.Usage.POSITION, 4); + VertexFormatElement.Type.SHORT, Compat.ElementUsage.POSITION, 4); VertexFormatElement color = Compat.vertexFormatElement(1, 0, - VertexFormatElement.Type.UBYTE, VertexFormatElement.Usage.COLOR, 4); + VertexFormatElement.Type.UBYTE, Compat.ElementUsage.COLOR, 4); VertexFormatElement material = Compat.vertexFormatElement(2, 0, - VertexFormatElement.Type.INT, VertexFormatElement.Usage.GENERIC, 1); + VertexFormatElement.Type.INT, Compat.ElementUsage.GENERIC, 1); DH_TERRAIN_FORMAT = Compat.buildVertexFormat( new String[] { "Position", "Color", "Material" }, @@ -157,7 +156,7 @@ private GraphicsPipeline createTerrainPipeline() { } Pipeline.Builder builder = new Pipeline.Builder(DH_TERRAIN_FORMAT); - builder.compileShaders("dh_terrain", vertSource, fragSource); + Compat.compileShaders(builder, "dh_terrain", vertSource, fragSource); // UBOs and samplers List ubos = new ArrayList<>(); @@ -203,7 +202,7 @@ private GraphicsPipeline createTerrainPipeline() { // Binding 1: LightMap sampler // VulkanMod hardcodes lightmap at texture slot 2 (see // VTextureSelector.setLightTexture()) - imageDescriptors.add(new ImageDescriptor(1, "sampler2D", "uLightMap", 2)); + imageDescriptors.add(Compat.imageDescriptor(1, "sampler2D", "uLightMap", 2)); builder.setUniforms(ubos, imageDescriptors); @@ -367,7 +366,7 @@ public void cleanup() { } this.uniformBuffers.clear(); this.initialized = false; - LOGGER.info("[DH-Vulkan] VulkanRenderContext cleaned up."); + LOGGER.debug("[DH-Vulkan] VulkanRenderContext cleaned up."); } // ================// diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/core/VulkanRenderEngine.java b/vulkan/src/main/java/com/braffolk/dhvulkan/core/VulkanRenderEngine.java index 33f9819..16854c1 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/core/VulkanRenderEngine.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/core/VulkanRenderEngine.java @@ -153,36 +153,28 @@ public void init() { try { disableUnsupportedSettings(); - LOGGER.info("[DH-Vulkan] Init: creating pipeline..."); this.renderContext.init(); - - LOGGER.info("[DH-Vulkan] Init: creating index buffer..."); this.ensureQuadIndexBuffer(262144); - LOGGER.info("[DH-Vulkan] Init: creating framebuffer..."); int width = Compat.getSwapChainWidth(); int height = Compat.getSwapChainHeight(); this.dhFramebuffer = new DhVulkanFramebuffer(); this.dhFramebuffer.init(width, height); - LOGGER.info("[DH-Vulkan] Init: creating composite pipeline..."); this.compositePipeline = new DhCompositePipeline(); this.compositePipeline.init(); - LOGGER.info("[DH-Vulkan] Init: creating SSAO pipeline..."); this.ssaoPipeline = new DhSsaoPipeline(); this.ssaoPipeline.init(width, height); - LOGGER.info("[DH-Vulkan] Init: creating Fog pipeline..."); this.fogPipeline = new DhFogPipeline(); this.fogPipeline.init(width, height); - LOGGER.info("[DH-Vulkan] Init: creating Depth Reader pipeline..."); this.depthReaderPipeline = new DhDepthReaderPipeline(); this.depthReaderPipeline.init(width, height); this.initialized = true; - LOGGER.info("[DH-Vulkan] Init complete. All resources created."); + LOGGER.debug("[DH-Vulkan] Vulkan renderer initialized ({}x{}).", width, height); } catch (Exception e) { LOGGER.error("[DH-Vulkan] Init FAILED", e); this.initFailed = true; @@ -233,7 +225,7 @@ public void beginFrame() { if (this.initFailed) return; Compat.rebindMainTarget(); - return; + // Continue into the normal frame path now that init succeeded. } // Bind MC's lightmap texture @@ -723,7 +715,7 @@ public void cleanup() { // Drained, freed in cache sweep below } - LOGGER.info("[DH-Vulkan] cleanup() called, freeing {} cached Vulkan buffers.", this.vulkanBufferCache.size()); + LOGGER.debug("[DH-Vulkan] cleanup() called, freeing {} cached Vulkan buffers.", this.vulkanBufferCache.size()); for (CachedBuffer cached : this.vulkanBufferCache.values()) { cached.free(); } @@ -759,7 +751,7 @@ public void cleanup() { this.initialized = false; this.initFailed = false; - LOGGER.info("[DH-Vulkan] VulkanRenderEngine cleaned up."); + LOGGER.debug("[DH-Vulkan] VulkanRenderEngine cleaned up."); } /** @@ -771,12 +763,16 @@ private void disableUnsupportedSettings() { Config.Client.Advanced.Debugging.DebugWireframe.showWorldGenQueue.setApiValue(false); Config.Client.Advanced.Debugging.DebugWireframe.showNetworkSyncOnLoadQueue.setApiValue(false); Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionStatus.setApiValue(false); + #if MC_VER < MC_26_1_2 Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionToggling.setApiValue(false); + #endif Config.Client.Advanced.Debugging.DebugWireframe.showQuadTreeRenderStatus.setApiValue(false); Config.Client.Advanced.Debugging.DebugWireframe.showFullDataUpdateStatus.setApiValue(false); + #if MC_VER < MC_26_1_2 Config.Client.Advanced.Graphics.GenericRendering.enableInstancedRendering .setAppearance(EConfigEntryAppearance.ONLY_IN_FILE); + #endif Config.Client.Advanced.Graphics.Fog.enableVanillaFog .setAppearance(EConfigEntryAppearance.ONLY_IN_FILE); Config.Client.Advanced.Debugging.OpenGl.overrideVanillaGLLogger @@ -785,7 +781,9 @@ private void disableUnsupportedSettings() { .setAppearance(EConfigEntryAppearance.ONLY_IN_FILE); Config.Client.Advanced.Debugging.OpenGl.glErrorHandlingMode .setAppearance(EConfigEntryAppearance.ONLY_IN_FILE); + #if MC_VER < MC_26_1_2 Config.Client.Advanced.Debugging.OpenGl.glUploadMode .setAppearance(EConfigEntryAppearance.ONLY_IN_FILE); + #endif } } diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/core/pipeline/DhCompositePipeline.java b/vulkan/src/main/java/com/braffolk/dhvulkan/core/pipeline/DhCompositePipeline.java index 130842c..845c60f 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/core/pipeline/DhCompositePipeline.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/core/pipeline/DhCompositePipeline.java @@ -87,7 +87,7 @@ public class DhCompositePipeline { private static final VertexFormat QUAD_FORMAT; static { VertexFormatElement position = Compat.vertexFormatElement(0, 0, - VertexFormatElement.Type.FLOAT, VertexFormatElement.Usage.POSITION, 2); + VertexFormatElement.Type.FLOAT, Compat.ElementUsage.POSITION, 2); QUAD_FORMAT = Compat.buildVertexFormat( new String[] { "Position" }, new VertexFormatElement[] { position }); @@ -101,7 +101,7 @@ public void init() { createQuadBuffers(); createPipeline(); this.initialized = true; - LOGGER.info("[DH-Vulkan] DhCompositePipeline initialized."); + LOGGER.debug("[DH-Vulkan] DhCompositePipeline initialized."); } /** @@ -138,7 +138,7 @@ private void createPipeline() { String fragSource = readShaderResource("shaders/vulkan/dh_apply.frag"); Pipeline.Builder builder = new Pipeline.Builder(QUAD_FORMAT); - builder.compileShaders("dh_composite", vertSource, fragSource); + Compat.compileShaders(builder, "dh_composite", vertSource, fragSource); // UBO at binding 0: mat4 uInvProj (64 bytes) + int uDebugMode (4 bytes) + int // uUseMcDepth (4 bytes) @@ -202,11 +202,11 @@ private void createPipeline() { // Image descriptors — DH color/depth + SSAO/fog debug + MC depth List imageDescriptors = new ArrayList<>(); - imageDescriptors.add(new ImageDescriptor(1, "sampler2D", "gDhColorTexture", DH_COLOR_TEXTURE_SLOT)); - imageDescriptors.add(new ImageDescriptor(2, "sampler2D", "gDhDepthTexture", DH_DEPTH_TEXTURE_SLOT)); - imageDescriptors.add(new ImageDescriptor(3, "sampler2D", "gSsaoTexture", DEBUG_SSAO_TEXTURE_SLOT)); - imageDescriptors.add(new ImageDescriptor(4, "sampler2D", "gFogTexture", DEBUG_FOG_TEXTURE_SLOT)); - imageDescriptors.add(new ImageDescriptor(5, "sampler2D", "gMcDepthTexture", MC_DEPTH_TEXTURE_SLOT)); + imageDescriptors.add(Compat.imageDescriptor(1, "sampler2D", "gDhColorTexture", DH_COLOR_TEXTURE_SLOT)); + imageDescriptors.add(Compat.imageDescriptor(2, "sampler2D", "gDhDepthTexture", DH_DEPTH_TEXTURE_SLOT)); + imageDescriptors.add(Compat.imageDescriptor(3, "sampler2D", "gSsaoTexture", DEBUG_SSAO_TEXTURE_SLOT)); + imageDescriptors.add(Compat.imageDescriptor(4, "sampler2D", "gFogTexture", DEBUG_FOG_TEXTURE_SLOT)); + imageDescriptors.add(Compat.imageDescriptor(5, "sampler2D", "gMcDepthTexture", MC_DEPTH_TEXTURE_SLOT)); builder.setUniforms(ubos, imageDescriptors); this.compositePipeline = builder.createGraphicsPipeline(); @@ -398,7 +398,7 @@ public void cleanup() { } this.initialized = false; - LOGGER.info("[DH-Vulkan] DhCompositePipeline cleaned up."); + LOGGER.debug("[DH-Vulkan] DhCompositePipeline cleaned up."); } private static String readShaderResource(String path) { diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/core/pipeline/DhDepthReaderPipeline.java b/vulkan/src/main/java/com/braffolk/dhvulkan/core/pipeline/DhDepthReaderPipeline.java index 6de3430..d131b82 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/core/pipeline/DhDepthReaderPipeline.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/core/pipeline/DhDepthReaderPipeline.java @@ -59,7 +59,7 @@ public class DhDepthReaderPipeline { private static final VertexFormat QUAD_FORMAT; static { VertexFormatElement position = Compat.vertexFormatElement(0, 0, - VertexFormatElement.Type.FLOAT, VertexFormatElement.Usage.POSITION, 2); + VertexFormatElement.Type.FLOAT, Compat.ElementUsage.POSITION, 2); QUAD_FORMAT = Compat.buildVertexFormat( new String[] { "Position" }, new VertexFormatElement[] { position }); @@ -87,7 +87,7 @@ public void init(int width, int height) { createPipeline(); Renderer.getInstance().addOnResizeCallback(this::onResize); this.initialized = true; - LOGGER.info("[DH-Vulkan] DhDepthReaderPipeline initialized ({}x{})", width, height); + LOGGER.debug("[DH-Vulkan] DhDepthReaderPipeline initialized ({}x{})", width, height); } private void createQuadBuffers() { @@ -118,7 +118,7 @@ private void createPipeline() { String fragSource = readShaderResource("shaders/vulkan/dh_depth_read.frag"); Pipeline.Builder builder = new Pipeline.Builder(QUAD_FORMAT); - builder.compileShaders("dh_depth_read", vertSource, fragSource); + Compat.compileShaders(builder, "dh_depth_read", vertSource, fragSource); List ubos = new ArrayList<>(); AlignedStruct.Builder uboBuilder = new AlignedStruct.Builder(); @@ -135,7 +135,7 @@ private void createPipeline() { ubos.add(mainUbo); List imageDescriptors = new ArrayList<>(); - imageDescriptors.add(new ImageDescriptor(1, "sampler2D", "gMcDepthTexture", MC_DEPTH_READ_SLOT)); + imageDescriptors.add(Compat.imageDescriptor(1, "sampler2D", "gMcDepthTexture", MC_DEPTH_READ_SLOT)); builder.setUniforms(ubos, imageDescriptors); this.pipeline = builder.createGraphicsPipeline(); @@ -202,7 +202,7 @@ private void onResize() { if (newWidth == this.width && newHeight == this.height) return; - LOGGER.info("[DH-Vulkan] Resizing DhDepthReaderPipeline: {}x{} -> {}x{}", + LOGGER.debug("[DH-Vulkan] Resizing DhDepthReaderPipeline: {}x{} -> {}x{}", this.width, this.height, newWidth, newHeight); // Free old framebuffer and render pass @@ -241,7 +241,7 @@ public void cleanup() { this.dummyBuf = null; } this.initialized = false; - LOGGER.info("[DH-Vulkan] DhDepthReaderPipeline cleaned up."); + LOGGER.debug("[DH-Vulkan] DhDepthReaderPipeline cleaned up."); } private String readShaderResource(String path) { diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/core/pipeline/DhFogPipeline.java b/vulkan/src/main/java/com/braffolk/dhvulkan/core/pipeline/DhFogPipeline.java index f94a690..fa15c68 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/core/pipeline/DhFogPipeline.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/core/pipeline/DhFogPipeline.java @@ -91,7 +91,7 @@ public class DhFogPipeline { private static final VertexFormat QUAD_FORMAT; static { VertexFormatElement position = Compat.vertexFormatElement(0, 0, - VertexFormatElement.Type.FLOAT, VertexFormatElement.Usage.POSITION, 2); + VertexFormatElement.Type.FLOAT, Compat.ElementUsage.POSITION, 2); QUAD_FORMAT = Compat.buildVertexFormat( new String[] { "Position" }, new VertexFormatElement[] { position }); @@ -188,7 +188,7 @@ private void createFogComputePipeline() { String fragSource = readShaderResource("shaders/vulkan/dh_fog.frag"); Pipeline.Builder builder = new Pipeline.Builder(QUAD_FORMAT); - builder.compileShaders("dh_fog_compute", vertSource, fragSource); + Compat.compileShaders(builder, "dh_fog_compute", vertSource, fragSource); List ubos = new ArrayList<>(); AlignedStruct.Builder uboBuilder = new AlignedStruct.Builder(); @@ -236,7 +236,7 @@ private void createFogComputePipeline() { ubos.add(mainUbo); List imageDescriptors = new ArrayList<>(); - imageDescriptors.add(new ImageDescriptor(1, "sampler2D", "uDepthMap", FOG_DEPTH_TEXTURE_SLOT)); + imageDescriptors.add(Compat.imageDescriptor(1, "sampler2D", "uDepthMap", FOG_DEPTH_TEXTURE_SLOT)); builder.setUniforms(ubos, imageDescriptors); this.fogComputePipeline = builder.createGraphicsPipeline(); @@ -252,7 +252,7 @@ private void createFogApplyPipeline() { String fragSource = readShaderResource("shaders/vulkan/dh_fog_apply.frag"); Pipeline.Builder builder = new Pipeline.Builder(QUAD_FORMAT); - builder.compileShaders("dh_fog_apply", vertSource, fragSource); + Compat.compileShaders(builder, "dh_fog_apply", vertSource, fragSource); List ubos = new ArrayList<>(); AlignedStruct.Builder uboBuilder = new AlignedStruct.Builder(); @@ -263,8 +263,8 @@ private void createFogApplyPipeline() { ubos.add(mainUbo); List imageDescriptors = new ArrayList<>(); - imageDescriptors.add(new ImageDescriptor(1, "sampler2D", "uFogTexture", FOG_COLOR_TEXTURE_SLOT)); - imageDescriptors.add(new ImageDescriptor(2, "sampler2D", "uDepthTexture", FOG_APPLY_DEPTH_TEXTURE_SLOT)); + imageDescriptors.add(Compat.imageDescriptor(1, "sampler2D", "uFogTexture", FOG_COLOR_TEXTURE_SLOT)); + imageDescriptors.add(Compat.imageDescriptor(2, "sampler2D", "uDepthTexture", FOG_APPLY_DEPTH_TEXTURE_SLOT)); builder.setUniforms(ubos, imageDescriptors); this.fogApplyPipeline = builder.createGraphicsPipeline(); diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/core/pipeline/DhSsaoPipeline.java b/vulkan/src/main/java/com/braffolk/dhvulkan/core/pipeline/DhSsaoPipeline.java index fc81bd3..fe8ed8a 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/core/pipeline/DhSsaoPipeline.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/core/pipeline/DhSsaoPipeline.java @@ -77,7 +77,7 @@ public class DhSsaoPipeline { private static final VertexFormat QUAD_FORMAT; static { VertexFormatElement position = Compat.vertexFormatElement(0, 0, - VertexFormatElement.Type.FLOAT, VertexFormatElement.Usage.POSITION, 2); + VertexFormatElement.Type.FLOAT, Compat.ElementUsage.POSITION, 2); QUAD_FORMAT = Compat.buildVertexFormat( new String[] { "Position" }, new VertexFormatElement[] { position }); @@ -238,7 +238,7 @@ private void createSsaoComputePipeline() { String fragSource = readShaderResource("shaders/vulkan/dh_ssao.frag"); Pipeline.Builder builder = new Pipeline.Builder(QUAD_FORMAT); - builder.compileShaders("dh_ssao_compute", vertSource, fragSource); + Compat.compileShaders(builder, "dh_ssao_compute", vertSource, fragSource); // UBO at binding 0: SSAO parameters List ubos = new ArrayList<>(); @@ -268,7 +268,7 @@ private void createSsaoComputePipeline() { // Image descriptor: DH depth at binding 1 List imageDescriptors = new ArrayList<>(); - imageDescriptors.add(new ImageDescriptor(1, "sampler2D", "uDepthMap", SSAO_DEPTH_TEXTURE_SLOT)); + imageDescriptors.add(Compat.imageDescriptor(1, "sampler2D", "uDepthMap", SSAO_DEPTH_TEXTURE_SLOT)); builder.setUniforms(ubos, imageDescriptors); this.ssaoComputePipeline = builder.createGraphicsPipeline(); @@ -284,7 +284,7 @@ private void createSsaoApplyPipeline() { String fragSource = readShaderResource("shaders/vulkan/dh_ssao_apply.frag"); Pipeline.Builder builder = new Pipeline.Builder(QUAD_FORMAT); - builder.compileShaders("dh_ssao_apply", vertSource, fragSource); + Compat.compileShaders(builder, "dh_ssao_apply", vertSource, fragSource); // UBO at binding 0: blur parameters List ubos = new ArrayList<>(); @@ -302,8 +302,8 @@ private void createSsaoApplyPipeline() { // Image descriptors: raw SSAO at binding 1, DH depth at binding 2 List imageDescriptors = new ArrayList<>(); - imageDescriptors.add(new ImageDescriptor(1, "sampler2D", "gSSAOMap", SSAO_RAW_TEXTURE_SLOT)); - imageDescriptors.add(new ImageDescriptor(2, "sampler2D", "gDepthMap", SSAO_APPLY_DEPTH_TEXTURE_SLOT)); + imageDescriptors.add(Compat.imageDescriptor(1, "sampler2D", "gSSAOMap", SSAO_RAW_TEXTURE_SLOT)); + imageDescriptors.add(Compat.imageDescriptor(2, "sampler2D", "gDepthMap", SSAO_APPLY_DEPTH_TEXTURE_SLOT)); builder.setUniforms(ubos, imageDescriptors); this.ssaoApplyPipeline = builder.createGraphicsPipeline(); diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/dh24/Dh24Integration.java b/vulkan/src/main/java/com/braffolk/dhvulkan/dh24/Dh24Integration.java index b827ded..07d0b68 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/dh24/Dh24Integration.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/dh24/Dh24Integration.java @@ -22,7 +22,7 @@ public class Dh24Integration implements DhIntegration { public void initialize(VulkanBackend backend) { this.backend = backend; this.delegate = new Dh24RenderDelegate(backend); - LOGGER.info("[DH-VulkanMod] DH 2.4 integration initialized. Delegate ready for wiring."); + LOGGER.debug("[DH-VulkanMod] DH 2.4 integration initialized. Delegate ready for wiring."); } @Override @@ -42,7 +42,7 @@ public void wireIfNeeded() { IVulkanLodRenderer lodRenderer = (IVulkanLodRenderer) LodRenderer.INSTANCE; lodRenderer.dhvulkan$setVulkanDelegate(this.delegate); this.wired = true; - LOGGER.info("[DH-VulkanMod] Dh24RenderDelegate wired into LodRenderer."); + LOGGER.debug("[DH-VulkanMod] Dh24RenderDelegate wired into LodRenderer."); } catch (Exception e) { LOGGER.error("[DH-VulkanMod] Failed to wire delegate", e); } diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh24/MixinGLProxy.java b/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh24/MixinGLProxy.java index 330798c..ee70401 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh24/MixinGLProxy.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh24/MixinGLProxy.java @@ -65,7 +65,7 @@ public class MixinGLProxy { } dhvulkan$dummyCreated = true; - GLProxy.LOGGER.info("[DH-VulkanMod] Created dummy GLProxy (VulkanMod active, no GL context)."); + GLProxy.LOGGER.debug("[DH-VulkanMod] Created dummy GLProxy (VulkanMod active, no GL context)."); } catch (Exception e) { GLProxy.LOGGER.error("[DH-VulkanMod] Failed to create dummy GLProxy", e); } diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh24/MixinLodRenderer.java b/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh24/MixinLodRenderer.java index 219e112..7bb966c 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh24/MixinLodRenderer.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh24/MixinLodRenderer.java @@ -85,7 +85,7 @@ public class MixinLodRenderer implements IVulkanLodRenderer { @Inject(method = "createRenderObjects", at = @At("HEAD"), cancellable = true) private void dhvulkan$skipGLRenderObjectCreation(CallbackInfoReturnable cir) { if (Compat.isVulkanModActive()) { - LodRenderer.LOGGER.info("[DH-VulkanMod] Skipping GL render object creation (VulkanMod active)"); + LodRenderer.LOGGER.debug("[DH-VulkanMod] Skipping GL render object creation (VulkanMod active)"); cir.setReturnValue(true); // signal success to caller } } diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh3/MixinDependencySetup.java b/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh3/MixinDependencySetup.java index d7a0708..1dc6db5 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh3/MixinDependencySetup.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh3/MixinDependencySetup.java @@ -10,27 +10,29 @@ * Intercepts DH 3.0's DependencySetup.setRenderingApiBindings() to replace * the default GL/Blaze3D renderer with our Vulkan renderer. * - * Without this, DH's delayed setup overwrites our early bindRenderers() call. - * By cancelling the original method and binding our VkRenderApiDefinition instead, - * we ensure DH uses our Vulkan rendering pipeline. + * DH 3.0.3 (26.1) uses {@code com.seibel.distanthorizons.common.wrappers.DependencySetup}. + * Older mixin targets ({@code loaderCommon.fabric...}) never applied, so DH kept + * binding GlDhRenderApiDefinition and LODs never rendered on VulkanMod. */ -@Mixin(targets = "loaderCommon.fabric.com.seibel.distanthorizons.common.wrappers.DependencySetup", remap = false) +@Mixin(value = com.seibel.distanthorizons.common.wrappers.DependencySetup.class, remap = false) public class MixinDependencySetup { @Inject(method = "setRenderingApiBindings", at = @At("HEAD"), cancellable = true) private static void dhvulkan$overrideRenderApi(CallbackInfo ci) { if (!Compat.isVulkanModActive()) return; - System.out.println("[DH-VulkanMod] Intercepting DH 3.0 renderer binding — injecting Vulkan render API."); - - // Get the VkRenderApiDefinition from ApiDhIntegration and bind it com.braffolk.dhvulkan.api.ApiDhIntegration integration = - com.braffolk.dhvulkan.api.ApiDhIntegration.getInstance(); - if (integration != null) { - integration.bindRenderApi(); - ci.cancel(); - } else { - System.out.println("[DH-VulkanMod] WARNING: ApiDhIntegration not initialized yet, falling back to default renderer."); + com.braffolk.dhvulkan.api.ApiDhIntegration.getInstance(); + if (integration == null) { + // DH can call this before our ClientModInitializer (DH loads first as a dependency). + com.braffolk.dhvulkan.core.VulkanBackend backend = + new com.braffolk.dhvulkan.core.VulkanRenderEngine(); + integration = new com.braffolk.dhvulkan.api.ApiDhIntegration(); + integration.initialize(backend); + com.braffolk.dhvulkan.DhVulkanModEntrypoint.setActiveIntegration(integration); } + + integration.bindRenderApi(); + ci.cancel(); } } diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh3/MixinGLProxy.java b/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh3/MixinGLProxy.java new file mode 100644 index 0000000..8389a87 --- /dev/null +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh3/MixinGLProxy.java @@ -0,0 +1,63 @@ +package com.braffolk.dhvulkan.mixin.dh3; + +import com.braffolk.dhvulkan.compat.Compat; +import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod; +import com.seibel.distanthorizons.common.render.openGl.glObject.GLProxy; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +/** + * DH 3.0 GLProxy lives in {@code common.render.openGl.glObject}. + * When VulkanMod is active we stub getInstance() so DH's data pipeline does not + * require a real GL context (fixes "GLProxy was created outside the render thread"). + */ +@Mixin(value = GLProxy.class, remap = false) +public class MixinGLProxy { + + @Shadow + private static GLProxy instance; + + @Unique + private static boolean dhvulkan$dummyCreated = false; + + @Inject(method = "getInstance", at = @At("HEAD"), cancellable = true) + private static void dhvulkan$stubGetInstance(CallbackInfoReturnable cir) { + if (!Compat.isVulkanModActive()) return; + + if (!dhvulkan$dummyCreated) { + try { + sun.misc.Unsafe unsafe = dhvulkan$getUnsafe(); + instance = (GLProxy) unsafe.allocateInstance(GLProxy.class); + + java.lang.reflect.Field uploadField = GLProxy.class.getDeclaredField("preferredUploadMethod"); + uploadField.setAccessible(true); + uploadField.set(instance, EDhApiGpuUploadMethod.DATA); + + dhvulkan$dummyCreated = true; + GLProxy.LOGGER.debug("[DH-VulkanMod] Created dummy GLProxy for DH 3.0 (VulkanMod active)."); + } catch (Exception e) { + GLProxy.LOGGER.error("[DH-VulkanMod] Failed to create dummy GLProxy", e); + } + } + + cir.setReturnValue(instance); + } + + @Inject(method = "runningOnRenderThread", at = @At("HEAD"), cancellable = true) + private static void dhvulkan$alwaysOnRenderThread(CallbackInfoReturnable cir) { + if (Compat.isVulkanModActive()) { + cir.setReturnValue(true); + } + } + + @Unique + private static sun.misc.Unsafe dhvulkan$getUnsafe() throws Exception { + java.lang.reflect.Field f = sun.misc.Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + return (sun.misc.Unsafe) f.get(null); + } +} diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh3/MixinLevelRendererRenderBridge.java b/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh3/MixinLevelRendererRenderBridge.java new file mode 100644 index 0000000..35f55bc --- /dev/null +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh3/MixinLevelRendererRenderBridge.java @@ -0,0 +1,86 @@ +package com.braffolk.dhvulkan.mixin.dh3; + +import com.braffolk.dhvulkan.render.DhVulkanRenderBridge; +import com.mojang.blaze3d.buffers.GpuBufferSlice; +import com.mojang.blaze3d.resource.ResourceHandle; +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.chunk.ChunkSectionLayerGroup; +import net.minecraft.client.renderer.chunk.ChunkSectionsToRender; +import net.minecraft.client.renderer.state.level.LevelRenderState; +import net.minecraft.util.profiling.ProfilerFiller; +import org.joml.Matrix4fc; +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; + +/** + * VulkanMod {@code @Redirect}s {@code ChunkSectionsToRender.renderGroup} to + * {@code LevelRenderer.renderSectionLayer}. DH hooks {@code renderGroup} directly. + * + * We inject at the original {@code renderGroup} call sites inside + * {@code lambda$addMainPass$0} (before each invoke), which still exist when VulkanMod + * redirects the call. + */ +@Mixin(LevelRenderer.class) +public class MixinLevelRendererRenderBridge { + + private static final String RENDER_GROUP = + "Lnet/minecraft/client/renderer/chunk/ChunkSectionsToRender;renderGroup" + + "(Lnet/minecraft/client/renderer/chunk/ChunkSectionLayerGroup;" + + "Lcom/mojang/blaze3d/textures/GpuSampler;)V"; + + private static final String LAMBDA_ADD_MAIN_PASS = + "lambda$addMainPass$0(Lcom/mojang/blaze3d/buffers/GpuBufferSlice;" + + "Lnet/minecraft/client/renderer/state/level/LevelRenderState;" + + "Lnet/minecraft/util/profiling/ProfilerFiller;" + + "Lnet/minecraft/client/renderer/chunk/ChunkSectionsToRender;" + + "Lcom/mojang/blaze3d/resource/ResourceHandle;" + + "Lcom/mojang/blaze3d/resource/ResourceHandle;" + + "Lcom/mojang/blaze3d/resource/ResourceHandle;" + + "Lcom/mojang/blaze3d/resource/ResourceHandle;" + + "Lcom/mojang/blaze3d/resource/ResourceHandle;" + + "ZLorg/joml/Matrix4fc;)V"; + + @Inject( + method = LAMBDA_ADD_MAIN_PASS, + at = @At(value = "INVOKE", target = RENDER_GROUP, ordinal = 0), + require = 1 + ) + private void dhvulkan$beforeOpaqueTerrain( + GpuBufferSlice gpuBufferSlice, + LevelRenderState levelRenderState, + ProfilerFiller profiler, + ChunkSectionsToRender chunkSections, + ResourceHandle entityOutlineTarget, + ResourceHandle entityTarget, + ResourceHandle translucentTarget, + ResourceHandle weatherTarget, + ResourceHandle outlineTarget, + boolean renderBlockOutline, + Matrix4fc matrix4fc, + CallbackInfo ci) { + DhVulkanRenderBridge.onTerrainLayerGroup(ChunkSectionLayerGroup.OPAQUE, matrix4fc); + } + + @Inject( + method = LAMBDA_ADD_MAIN_PASS, + at = @At(value = "INVOKE", target = RENDER_GROUP, ordinal = 1), + require = 0 + ) + private void dhvulkan$beforeTranslucentTerrain( + GpuBufferSlice gpuBufferSlice, + LevelRenderState levelRenderState, + ProfilerFiller profiler, + ChunkSectionsToRender chunkSections, + ResourceHandle entityOutlineTarget, + ResourceHandle entityTarget, + ResourceHandle translucentTarget, + ResourceHandle weatherTarget, + ResourceHandle outlineTarget, + boolean renderBlockOutline, + Matrix4fc matrix4fc, + CallbackInfo ci) { + DhVulkanRenderBridge.onTerrainLayerGroup(ChunkSectionLayerGroup.TRANSLUCENT, matrix4fc); + } +} diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh3/MixinLodBufferContainerRenderDef.java b/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh3/MixinLodBufferContainerRenderDef.java new file mode 100644 index 0000000..8059d29 --- /dev/null +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/dh3/MixinLodBufferContainerRenderDef.java @@ -0,0 +1,33 @@ +package com.braffolk.dhvulkan.mixin.dh3; + +import com.braffolk.dhvulkan.compat.Compat; +import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodBufferContainer; +import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; +import com.seibel.distanthorizons.core.wrapperInterfaces.render.AbstractDhRenderApiDefinition; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +/** + * {@link LodBufferContainer} caches {@code RENDER_DEF} in its static initializer from + * whatever was in {@link SingletonInjector} at class-load time. After we bind Vulkan, + * that cached value can be stale. Redirect {@code useSingleIbo()} to read live injector state. + */ +@Mixin(value = LodBufferContainer.class, remap = false) +public class MixinLodBufferContainerRenderDef { + + @Redirect( + method = "createIndexBuffers", + at = @At( + value = "INVOKE", + target = "Lcom/seibel/distanthorizons/core/wrapperInterfaces/render/AbstractDhRenderApiDefinition;useSingleIbo()Z" + ), + require = 0 + ) + private static boolean dhvulkan$useSingleIboFromInjector(AbstractDhRenderApiDefinition cachedDef) { + if (!Compat.isVulkanModActive()) { + return cachedDef.useSingleIbo(); + } + return SingletonInjector.INSTANCE.get(AbstractDhRenderApiDefinition.class).useSingleIbo(); + } +} diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/shared/MixinLightMapWrapper.java b/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/shared/MixinLightMapWrapper.java index cd0721f..579d44c 100644 --- a/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/shared/MixinLightMapWrapper.java +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/mixin/shared/MixinLightMapWrapper.java @@ -2,22 +2,20 @@ import com.braffolk.dhvulkan.compat.Compat; import com.mojang.blaze3d.platform.NativeImage; +import com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper; 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; /** - * Mixin into DH's LightMapWrapper to skip all GL calls when VulkanMod is - * active. Applies to both DH 2.4 and DH 3.0. + * Mixin into DH's LightMapWrapper to skip GL / legacy upload paths when VulkanMod is active. * - * uploadLightmap() and createLightmap() exist in both versions and make GL - * calls (glIsTexture, glTexImage2D, glBindTexture) that are fatal in Vulkan. - * - * bind()/unbind() only exist in DH 2.4 (they call glBindTexture/glActiveTexture) - * — marked require = 0 so the mixin doesn't fail when targeting DH 3.0. + * DH 3.0.3 (26.1): class is {@code com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper}. + * {@code uploadLightmap()} throws on 26.1+ (MC uses {@code setLightmapGpuTexture} instead). + * Our engine binds MC's lightmap via {@link Compat#getLightmapVulkanImage()}. */ -@Mixin(targets = "loaderCommon.fabric.com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper", remap = false) +@Mixin(value = LightMapWrapper.class, remap = false) public class MixinLightMapWrapper { @Inject(method = "uploadLightmap", at = @At("HEAD"), cancellable = true) @@ -27,14 +25,14 @@ public class MixinLightMapWrapper { } } - @Inject(method = "createLightmap", at = @At("HEAD"), cancellable = true) + /** DH 2.4 only — absent in DH 3.0.3 */ + @Inject(method = "createLightmap", at = @At("HEAD"), cancellable = true, require = 0) private void dhvulkan$skipCreateLightmap(NativeImage nativeImage, CallbackInfo ci) { if (Compat.isVulkanModActive()) { ci.cancel(); } } - // bind/unbind only exist in DH 2.4 — require = 0 makes these optional @Inject(method = "bind", at = @At("HEAD"), cancellable = true, require = 0) private void dhvulkan$skipBind(CallbackInfo ci) { if (Compat.isVulkanModActive()) { diff --git a/vulkan/src/main/java/com/braffolk/dhvulkan/render/DhVulkanRenderBridge.java b/vulkan/src/main/java/com/braffolk/dhvulkan/render/DhVulkanRenderBridge.java new file mode 100644 index 0000000..738e3f2 --- /dev/null +++ b/vulkan/src/main/java/com/braffolk/dhvulkan/render/DhVulkanRenderBridge.java @@ -0,0 +1,90 @@ +package com.braffolk.dhvulkan.render; + +import com.braffolk.dhvulkan.compat.Compat; +import com.seibel.distanthorizons.common.wrappers.McObjectConverter; +import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper; +import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper; +import com.seibel.distanthorizons.core.api.internal.ClientApi; +import com.seibel.distanthorizons.core.api.internal.rendering.DhRenderState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.chunk.ChunkSectionLayerGroup; +import net.vulkanmod.vulkan.VRenderSystem; +import org.joml.Matrix4fc; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +/** + * VulkanMod redirects {@code ChunkSectionsToRender.renderGroup} to + * {@code LevelRenderer.renderSectionLayer}, so DH's own chunk-section mixin never runs. + * This mirrors DH's {@code MixinChunkSectionsToRender.renderDeferredLayerHead}. + */ +public final class DhVulkanRenderBridge { + + private static final Logger LOGGER = LogManager.getLogger("DH-VulkanMod"); + private static boolean loggedMatrixFallback; + private static boolean loggedFirstRender; + private static boolean loggedSkipRender; + + private DhVulkanRenderBridge() {} + + public static void onTerrainLayerGroup(ChunkSectionLayerGroup group) { + onTerrainLayerGroup(group, null); + } + + public static void onTerrainLayerGroup(ChunkSectionLayerGroup group, Matrix4fc levelModelView) { + if (!Compat.isVulkanModActive()) { + return; + } + + DhRenderState state = ClientApi.RENDER_STATE; + state.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent( + state.clientLevelWrapper, + Minecraft.getInstance().level); + + ensureRenderMatrices(state, levelModelView); + + try { + state.canRenderOrThrow(); + } catch (RuntimeException e) { + if (!loggedSkipRender) { + loggedSkipRender = true; + LOGGER.debug("[DH-VulkanMod] Skipping LOD render ({}): {}", group, e.getMessage()); + } + return; + } + + if (group == ChunkSectionLayerGroup.TRANSLUCENT) { + ClientApi.INSTANCE.renderDeferredLodsForShaders(); + } else if (group == ChunkSectionLayerGroup.OPAQUE) { + if (!loggedFirstRender) { + loggedFirstRender = true; + LOGGER.debug("[DH-VulkanMod] LOD render hooked at VulkanMod terrain layer ({}).", group); + } + ClientApi.INSTANCE.renderLods(); + } + } + + /** + * DH normally receives matrices from {@code MixinLevelRenderer} / {@code MixinGameRenderer}. + * Under VulkanMod those injects may not run before terrain; fall back to VRenderSystem. + */ + private static void ensureRenderMatrices(DhRenderState state, Matrix4fc levelModelView) { + if (state.mcProjectionMatrix == null) { + state.mcProjectionMatrix = McObjectConverter.Convert(VRenderSystem.projection); + if (!loggedMatrixFallback) { + loggedMatrixFallback = true; + LOGGER.debug("[DH-VulkanMod] Using VRenderSystem.projection for DH render state."); + } + } + if (state.mcModelViewMatrix == null) { + if (levelModelView != null) { + state.mcModelViewMatrix = McObjectConverter.Convert(levelModelView); + } else { + state.mcModelViewMatrix = McObjectConverter.Convert(VRenderSystem.modelView); + } + } + if (state.partialTickTime < 0f) { + state.partialTickTime = MinecraftRenderWrapper.INSTANCE.getPartialTickTime(); + } + } +} diff --git a/vulkan/src/main/resources/dh-vulkanmod.mixins.json b/vulkan/src/main/resources-legacy/dh-vulkanmod.mixins.json similarity index 99% rename from vulkan/src/main/resources/dh-vulkanmod.mixins.json rename to vulkan/src/main/resources-legacy/dh-vulkanmod.mixins.json index 0affd52..95435c5 100644 --- a/vulkan/src/main/resources/dh-vulkanmod.mixins.json +++ b/vulkan/src/main/resources-legacy/dh-vulkanmod.mixins.json @@ -17,4 +17,4 @@ "injectors": { "defaultRequire": 1 } -} \ No newline at end of file +} diff --git a/vulkan/src/main/resources/fabric.mod.json b/vulkan/src/main/resources-legacy/fabric.mod.json similarity index 99% rename from vulkan/src/main/resources/fabric.mod.json rename to vulkan/src/main/resources-legacy/fabric.mod.json index 91c43b2..d2ab3b9 100644 --- a/vulkan/src/main/resources/fabric.mod.json +++ b/vulkan/src/main/resources-legacy/fabric.mod.json @@ -30,4 +30,4 @@ "distanthorizons": ">=2.4.0-", "vulkanmod": "${vulkanmod_min_version}" } -} \ No newline at end of file +} diff --git a/vulkan/src/main/resources-mc26/dh-vulkanmod.mixins.json b/vulkan/src/main/resources-mc26/dh-vulkanmod.mixins.json new file mode 100644 index 0000000..448c3ed --- /dev/null +++ b/vulkan/src/main/resources-mc26/dh-vulkanmod.mixins.json @@ -0,0 +1,17 @@ +{ + "required": true, + "package": "com.braffolk.dhvulkan.mixin", + "compatibilityLevel": "JAVA_21", + "plugin": "com.braffolk.dhvulkan.DhVulkanMixinPlugin", + "client": [ + "dh3.MixinDependencySetup", + "dh3.MixinGLProxy", + "dh3.MixinLevelRendererRenderBridge", + "dh3.MixinLodBufferContainerRenderDef", + "shared.MixinLevelRenderer", + "shared.MixinLightMapWrapper" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/vulkan/src/main/resources-mc26/fabric.mod.json b/vulkan/src/main/resources-mc26/fabric.mod.json new file mode 100644 index 0000000..79851bc --- /dev/null +++ b/vulkan/src/main/resources-mc26/fabric.mod.json @@ -0,0 +1,33 @@ +{ + "schemaVersion": 1, + "id": "dh-vulkanmod", + "version": "${version}", + "name": "Distant Horizons — VulkanMod Extension", + "description": "Adds native Vulkan rendering to Distant Horizons via VulkanMod. Replaces DH's OpenGL pipeline with a Vulkan backend for SSAO, fog, depth compositing, and LOD rendering.", + "authors": [ + "Braffolk" + ], + "contact": { + "homepage": "https://www.curseforge.com/minecraft/mc-mods/distant-horizons-vulkanmod", + "sources": "https://github.com/Braffolk/distant-horizons-vulkanmod", + "issues": "https://github.com/Braffolk/distant-horizons-vulkanmod/issues", + "discord": "https://discord.gg/xAB8G4cENx" + }, + "license": "LGPL-3.0", + "icon": "assets/dh-vulkanmod/icon.png", + "environment": "client", + "entrypoints": { + "client": [ + "com.braffolk.dhvulkan.DhVulkanModEntrypoint" + ] + }, + "mixins": [ + "dh-vulkanmod.mixins.json" + ], + "depends": { + "fabricloader": ">=0.18.0", + "minecraft": ["26.1", "26.1.1", "26.1.2"], + "distanthorizons": ">=3.0.0-", + "vulkanmod": "${vulkanmod_min_version}" + } +}