diff --git a/.github/workflows/build_all.yml b/.github/workflows/build_all.yml new file mode 100644 index 000000000..a55571b9d --- /dev/null +++ b/.github/workflows/build_all.yml @@ -0,0 +1,78 @@ +name: Build All Minecraft Versions + +on: + workflow_dispatch: # 手动触发 + inputs: + version: + description: 'VulkanMod 版本号(如 0.6.2)' + required: true + default: '0.6.2' + +permissions: + contents: write + +jobs: + build-all: + runs-on: ubuntu-latest + strategy: + matrix: + mc_version: + - 1.18.2 + - 1.19.2 + - 1.19.4 + - 1.20.x + - 1.21 + fail-fast: false # 一个失败不影响其他版本 + + steps: + - name: 检出 ${{ matrix.mc_version }} 分支 + uses: actions/checkout@v4 + with: + ref: ${{ matrix.mc_version }} + + - name: 设置 JDK 21 + uses: actions/setup-java@v4 + with: + java-version: 21 + distribution: temurin + + - name: 修改版本号为 ${{ github.event.inputs.version }} + run: | + # 修改 gradle.properties 中的版本号 + sed -i 's/^mod_version=.*/mod_version=${{ github.event.inputs.version }}/' gradle.properties 2>/dev/null || \ + sed -i 's/^version=.*/version=${{ github.event.inputs.version }}/' gradle.properties 2>/dev/null || \ + echo "未找到版本号字段,请检查 gradle.properties" + cat gradle.properties | grep -E "mod_version|version" || echo "警告:未找到版本号定义" + + - name: 赋予 gradlew 执行权限 + run: chmod +x gradlew + + - name: 构建 Mod JAR + run: ./gradlew build + + - name: 查找生成的 JAR + id: find_jar + run: | + JAR_PATH=$(find build/libs -name "*.jar" ! -name "*-sources.jar" ! -name "*-dev.jar" | head -n 1) + if [ -z "$JAR_PATH" ]; then + # 如果没有排除 sources/dev,就取第一个 jar + JAR_PATH=$(find build/libs -name "*.jar" | head -n 1) + fi + echo "jar_path=$JAR_PATH" >> $GITHUB_OUTPUT + echo "找到 JAR: $JAR_PATH" + + - name: 上传到 GitHub Release(每个 MC 版本单独 Release) + uses: softprops/action-gh-release@v1 + with: + tag_name: v${{ github.event.inputs.version }}-${{ matrix.mc_version }} + name: VulkanMod ${{ github.event.inputs.version }} (MC ${{ matrix.mc_version }}) + body: | + 🚀 VulkanMod ${{ github.event.inputs.version }} for Minecraft ${{ matrix.mc_version }} + + - 基于分支: ${{ matrix.mc_version }} + - 自动构建时间: ${{ github.server_time }} + files: ${{ steps.find_jar.outputs.jar_path }} + draft: false + prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/build_release.yml b/.github/workflows/build_release.yml new file mode 100644 index 000000000..195b8544c --- /dev/null +++ b/.github/workflows/build_release.yml @@ -0,0 +1,38 @@ +name: Build Specific MC Version + +on: + workflow_dispatch: + inputs: + branch: + description: '分支名(如 1.21.4)' + required: true + default: '1.21.4' + mc_version: + description: 'Minecraft 版本(用于 Release 名称)' + required: true + default: '1.21.4' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.inputs.branch }} + + - name: 设置 JDK 21 + uses: actions/setup-java@v4 + with: + java-version: 21 + distribution: temurin + + - name: 构建 + run: | + chmod +x gradlew + ./gradlew build + + - name: 上传 JAR + uses: actions/upload-artifact@v4 + with: + name: VulkanMod-${{ github.event.inputs.mc_version }} + path: build/libs/*.jar \ No newline at end of file diff --git a/.github/workflows/buildvk11.yml b/.github/workflows/buildvk11.yml new file mode 100644 index 000000000..6b0dbbc9e --- /dev/null +++ b/.github/workflows/buildvk11.yml @@ -0,0 +1,33 @@ +name: Build Mod for Multiple Versions + +on: + push: + branches: [ main ] # 或指定 0.6.2 对应的分支 + workflow_dispatch: # 支持手动触发 + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + mc_version: [1.20.1, 1.21, 1.21.1] # 修改为你需要的版本列表 + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + - name: Build with Gradle + run: | + # 尝试通过命令行参数覆盖 Minecraft 版本 + # 具体参数需要根据 build.gradle 的逻辑来定,通常需修改 gradle.properties + sed -i "s/minecraft_version=.*/minecraft_version=${{ matrix.mc_version }}/" gradle.properties + chmod +x gradlew + ./gradlew build + - name: Upload JAR + uses: actions/upload-artifact@v4 + with: + name: VulkanMod-${{ matrix.mc_version }} + path: build/libs/*.jar \ No newline at end of file diff --git a/README.md b/README.md index 917d9bdb6..332745eee 100644 --- a/README.md +++ b/README.md @@ -1,77 +1,3 @@ -# VulkanMod - -This is a fabric mod that introduces a brand new **Vulkan** based voxel rendering engine to **Minecraft java** in order to both replace the default OpenGL renderer and bring performance improvements. - -### Why? -- Highly experimental project that overhauls and modernizes the internal renderer for Minecraft.
-- Updates the renderer from OpenGL 3.2 to Vulkan 1.2.
-- Provides a potential reference for a future-proof Vulkan codebase for Minecraft Java.
-- Utilizes the VulkanAPI to allow for capabilities not always possible with OpenGL.
-- Including reduced CPU Overhead and use of newer, modern hardware capabilities.
- -### Demonstration Video: - -[![Demostration Video](http://img.youtube.com/vi/sbr7UxcAmOE/0.jpg)](https://youtu.be/sbr7UxcAmOE) - -## FAQ -- Remember to check the [Wiki](https://github.com/xCollateral/VulkanMod/wiki) we wrote before asking for support! - -## Installation - -### Download Links: - -- [![CurseForge](https://cf.way2muchnoise.eu/full_635429_downloads.svg?badge_style=flat)](https://www.curseforge.com/minecraft/mc-mods/vulkanmod) - -- [![Modrinth Downloads](https://img.shields.io/modrinth/dt/JYQhtZtO?logo=modrinth&label=Modrinth%20Downloads)](https://modrinth.com/mod/vulkanmod/versions) - -- [![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/xCollateral/VulkanMod/total?style=flat-square&logo=github&label=Github%20Downloads)](https://github.com/xCollateral/VulkanMod/releases) - -### Install guide: ->1) Install the [fabric modloader](https://fabricmc.net). ->1) Download and put the `Vulkanmod.jar` file into `.minecraft/mods` ->1) Enjoy ! - -## Useful links - - - - - - - - - -
Discord server Ko-Fi
- - Discord - - - - Static Badge - -
- - -## Features - -### Optimizations: ->- [x] Multiple chunk culling algorithms ->- [x] Reduced CPU overhead ->- [x] Improved GPU performance ->- [x] Indirect Draw mode (reduces CPU overhead) ->- [x] Chunk rendering optimizations - -### New changes: ->- [x] Native Wayland support ->- [x] GPU selector ->- [x] Windowed fullscreen mode ->- [x] Revamped graphic settings menu ->- [x] Resizable render frame queue ->- [ ] Shader support ->- [ ] Removed Herobrine - - -## Notes -- This mod is still in development, please report issues in the [issue tab](https://github.com/xCollateral/VulkanMod/issues) with logs attached! -- This mode isn't just "minecraft on vulkan" (e.g: [zink](https://docs.mesa3d.org/drivers/zink.html) ), it is a full rewrite of the minecraft renderer. +# VulkanMod +这是一个专门用于给vulkan1.1做适配的版本 diff --git a/build.gradle b/build.gradle index 2f68c914c..5bcdbd291 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.6.11' + id 'fabric-loom' version '1.12-SNAPSHOT' id 'maven-publish' } @@ -20,10 +20,9 @@ dependencies { mappings loom.officialMojangMappings() modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - // Fabric API. This is technically optional, but you probably want it anyway. + // Fabric API. modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - // Needed in order to load mod namespace ext.includeModule = { name -> var module = fabricApi.module(name, project.fabric_version) modImplementation(module) @@ -32,8 +31,13 @@ dependencies { includeModule("fabric-api-base") includeModule("fabric-resource-loader-v0") - includeModule("fabric-rendering-fluids-v1") + includeModule("fabric-resource-loader-v1") includeModule("fabric-rendering-v1") + includeModule("fabric-renderer-api-v1") + includeModule("fabric-rendering-fluids-v1") + includeModule("fabric-block-view-api-v2") + includeModule("fabric-lifecycle-events-v1") + includeModule("fabric-transitive-access-wideners-v1") } project.ext.lwjglVersion = "3.3.3" diff --git a/gradle.properties b/gradle.properties index 83d8ea876..5674cebd2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,14 +4,14 @@ org.gradle.parallel=true # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.21 -yarn_mappings=1.21+build.1 -loader_version=0.16.5 +minecraft_version = 1.21.10 +yarn_mappings = 1.21.10+build.2 +loader_version = 0.17.3 # Fabric API -fabric_version=0.102.0+1.21 +fabric_version = 0.138.0+1.21.10 # Mod Properties -mod_version = 0.4.8_dev +mod_version = 0.6.2 maven_group = net.vulkanmod -archives_base_name = VulkanMod_1.21 +archives_base_name = VulkanMod_1.21.10 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e6441136f..a4b76b953 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b82aa23a4..d4081da47 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.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 index 1aa94a426..f3b75f3b0 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/gradlew.bat b/gradlew.bat index 25da30dbd..9d21a2183 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## diff --git a/src/main/java/net/vulkanmod/Initializer.java b/src/main/java/net/vulkanmod/Initializer.java index e99a46eb1..b9309e373 100644 --- a/src/main/java/net/vulkanmod/Initializer.java +++ b/src/main/java/net/vulkanmod/Initializer.java @@ -1,10 +1,13 @@ package net.vulkanmod; import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.renderer.v1.Renderer; import net.fabricmc.loader.api.FabricLoader; import net.vulkanmod.config.Config; import net.vulkanmod.config.Platform; +import net.vulkanmod.config.UpdateChecker; import net.vulkanmod.config.video.VideoModeManager; +import net.vulkanmod.render.chunk.build.frapi.VulkanModRenderer; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -35,6 +38,10 @@ public void onInitializeClient() { .resolve("vulkanmod_settings.json"); CONFIG = loadConfig(configPath); + + Renderer.register(VulkanModRenderer.INSTANCE); + + UpdateChecker.checkForUpdates(); } private static Config loadConfig(Path path) { diff --git a/src/main/java/net/vulkanmod/config/Config.java b/src/main/java/net/vulkanmod/config/Config.java index b265f6d58..e2bebdb7f 100644 --- a/src/main/java/net/vulkanmod/config/Config.java +++ b/src/main/java/net/vulkanmod/config/Config.java @@ -13,19 +13,22 @@ import java.util.Collections; public class Config { - - public int frameQueueSize = 2; public VideoModeSet.VideoMode videoMode = VideoModeManager.getFirstAvailable().getVideoMode(); - public boolean windowedFullscreen = false; + public int windowMode = 0; public int advCulling = 2; - public boolean indirectDraw = false; + public boolean indirectDraw = true; public boolean uniqueOpaqueLayer = true; public boolean entityCulling = true; public int device = -1; public int ambientOcclusion = 1; + public int frameQueueSize = 2; + public int builderThreads = 0; + + public boolean backFaceCulling = true; + public boolean textureAnimations = true; public void write() { diff --git a/src/main/java/net/vulkanmod/config/Platform.java b/src/main/java/net/vulkanmod/config/Platform.java index 6d63eb68a..9e5514642 100644 --- a/src/main/java/net/vulkanmod/config/Platform.java +++ b/src/main/java/net/vulkanmod/config/Platform.java @@ -2,6 +2,7 @@ import org.apache.commons.lang3.SystemUtils; import org.lwjgl.glfw.GLFW; +import org.lwjgl.system.Configuration; import static net.vulkanmod.Initializer.LOGGER; import static org.lwjgl.glfw.GLFW.*; diff --git a/src/main/java/net/vulkanmod/config/UpdateChecker.java b/src/main/java/net/vulkanmod/config/UpdateChecker.java new file mode 100644 index 000000000..cb054a84a --- /dev/null +++ b/src/main/java/net/vulkanmod/config/UpdateChecker.java @@ -0,0 +1,58 @@ +package net.vulkanmod.config; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import net.fabricmc.loader.api.Version; +import net.fabricmc.loader.api.VersionParsingException; +import net.fabricmc.loader.impl.util.version.VersionParser; +import net.minecraft.SharedConstants; +import net.vulkanmod.Initializer; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.concurrent.CompletableFuture; + +public abstract class UpdateChecker { + private static boolean updateAvailable = false; + + public static void checkForUpdates() { + CompletableFuture.supplyAsync(() -> { + try { + String req = "https://api.modrinth.com/v2/project/vulkanmod/version?include_changelog=false"; + String mcVersion = SharedConstants.getCurrentVersion().name(); + req += "&game_versions=%s".formatted(mcVersion); + + URL url = new URL(req); + HttpURLConnection http = (HttpURLConnection)url.openConnection(); + var inputStream = http.getInputStream(); + + JsonObject data = JsonParser.parseString("{ versions: " + new String(inputStream.readAllBytes()) + "}").getAsJsonObject(); + JsonArray versions = data.getAsJsonArray("versions"); + http.disconnect(); + + String version = String.valueOf(versions.get(0).getAsJsonObject().get("version_number")).replace("\"", ""); + + var currentVersion = VersionParser.parseSemantic(Initializer.getVersion()); + updateAvailable = currentVersion.compareTo(Version.parse(version)) < 0; + + if (updateAvailable) { + Initializer.LOGGER.info("Update available!"); + } + } + catch (IOException e) { + Initializer.LOGGER.info("Error occurred, skipping update check."); + } + catch (VersionParsingException e) { + Initializer.LOGGER.info("Unable to parse version, skipping update check."); + } + + return null; + }); + } + + public static boolean isUpdateAvailable() { + return updateAvailable; + } +} diff --git a/src/main/java/net/vulkanmod/config/gui/GuiElement.java b/src/main/java/net/vulkanmod/config/gui/GuiElement.java index ee4305de1..04b85d2a1 100644 --- a/src/main/java/net/vulkanmod/config/gui/GuiElement.java +++ b/src/main/java/net/vulkanmod/config/gui/GuiElement.java @@ -7,6 +7,7 @@ import net.minecraft.client.gui.narration.NarrationElementOutput; import net.minecraft.client.gui.navigation.FocusNavigationEvent; import net.minecraft.client.gui.navigation.ScreenRectangle; +import net.minecraft.client.input.MouseButtonEvent; import org.jetbrains.annotations.Nullable; public abstract class GuiElement implements GuiEventListener, NarratableEntry { @@ -82,46 +83,6 @@ public float getHoverMultiplier(float time) { } } - @Override - public void mouseMoved(double d, double e) { - GuiEventListener.super.mouseMoved(d, e); - } - - @Override - public boolean mouseClicked(double d, double e, int i) { - return GuiEventListener.super.mouseClicked(d, e, i); - } - - @Override - public boolean mouseReleased(double d, double e, int i) { - return GuiEventListener.super.mouseReleased(d, e, i); - } - - @Override - public boolean mouseDragged(double d, double e, int i, double f, double g) { - return GuiEventListener.super.mouseDragged(d, e, i, f, g); - } - - @Override - public boolean mouseScrolled(double d, double e, double f, double g) { - return GuiEventListener.super.mouseScrolled(d, e, f, g); - } - - @Override - public boolean keyPressed(int i, int j, int k) { - return GuiEventListener.super.keyPressed(i, j, k); - } - - @Override - public boolean keyReleased(int i, int j, int k) { - return GuiEventListener.super.keyReleased(i, j, k); - } - - @Override - public boolean charTyped(char c, int i) { - return GuiEventListener.super.charTyped(c, i); - } - @Nullable @Override public ComponentPath nextFocusPath(FocusNavigationEvent focusNavigationEvent) { diff --git a/src/main/java/net/vulkanmod/config/gui/GuiRenderer.java b/src/main/java/net/vulkanmod/config/gui/GuiRenderer.java deleted file mode 100644 index 7dce13097..000000000 --- a/src/main/java/net/vulkanmod/config/gui/GuiRenderer.java +++ /dev/null @@ -1,159 +0,0 @@ -package net.vulkanmod.config.gui; - -import com.mojang.blaze3d.platform.Window; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.*; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.network.chat.Component; -import net.minecraft.util.FastColor; -import net.minecraft.util.FormattedCharSequence; -import org.joml.Matrix4f; - -import java.util.List; - -public abstract class GuiRenderer { - - public static Minecraft minecraft; - public static Font font; - public static GuiGraphics guiGraphics; - public static PoseStack pose; - - public static BufferBuilder bufferBuilder; - public static boolean batching = false; - - public static void setPoseStack(PoseStack poseStack) { - pose = poseStack; - } - - public static void disableScissor() { - RenderSystem.disableScissor(); - } - - public static void enableScissor(int x, int y, int width, int height) { - Window window = Minecraft.getInstance().getWindow(); - int wHeight = window.getHeight(); - double scale = window.getGuiScale(); - int xScaled = (int) (x * scale); - int yScaled = (int) (wHeight - (y + height) * scale); - int widthScaled = (int) (width * scale); - int heightScaled = (int) (height * scale); - RenderSystem.enableScissor(xScaled, yScaled, Math.max(0, widthScaled), Math.max(0, heightScaled)); - } - - public static void fillBox(float x0, float y0, float width, float height, int color) { - fill(x0, y0, x0 + width, y0 + height, 0, color); - } - - public static void fill(float x0, float y0, float x1, float y1, int color) { - fill(x0, y0, x1, y1, 0, color); - } - - public static void fill(float x0, float y0, float x1, float y1, float z, int color) { - Matrix4f matrix4f = pose.last().pose(); - - float a = (float) FastColor.ARGB32.alpha(color) / 255.0F; - float r = (float) FastColor.ARGB32.red(color) / 255.0F; - float g = (float) FastColor.ARGB32.green(color) / 255.0F; - float b = (float) FastColor.ARGB32.blue(color) / 255.0F; - - RenderSystem.setShader(GameRenderer::getPositionColorShader); - - if (!batching) - bufferBuilder = Tesselator.getInstance().begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); - - bufferBuilder.addVertex(matrix4f, x0, y0, z).setColor(r, g, b, a); - bufferBuilder.addVertex(matrix4f, x0, y1, z).setColor(r, g, b, a); - bufferBuilder.addVertex(matrix4f, x1, y1, z).setColor(r, g, b, a); - bufferBuilder.addVertex(matrix4f, x1, y0, z).setColor(r, g, b, a); - - if (!batching) - BufferUploader.drawWithShader(bufferBuilder.buildOrThrow()); - } - - public static void fillGradient(float x0, float y0, float x1, float y1, int color1, int color2) { - fillGradient(x0, y0, x1, y1, 0, color1, color2); - } - - public static void fillGradient(float x0, float y0, float x1, float y1, float z, int color1, int color2) { - float a1 = (float) FastColor.ARGB32.alpha(color1) / 255.0F; - float r1 = (float) FastColor.ARGB32.red(color1) / 255.0F; - float g1 = (float) FastColor.ARGB32.green(color1) / 255.0F; - float b1 = (float) FastColor.ARGB32.blue(color1) / 255.0F; - float a2 = (float) FastColor.ARGB32.alpha(color2) / 255.0F; - float r2 = (float) FastColor.ARGB32.red(color2) / 255.0F; - float g2 = (float) FastColor.ARGB32.green(color2) / 255.0F; - float b2 = (float) FastColor.ARGB32.blue(color2) / 255.0F; - - Matrix4f matrix4f = pose.last().pose(); - - RenderSystem.setShader(GameRenderer::getPositionColorShader); - - if (!batching) - bufferBuilder = Tesselator.getInstance().begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); - - bufferBuilder.addVertex(matrix4f, x0, y0, z).setColor(r1, g1, b1, a1); - bufferBuilder.addVertex(matrix4f, x0, y1, z).setColor(r2, g2, b2, a2); - bufferBuilder.addVertex(matrix4f, x1, y1, z).setColor(r2, g2, b2, a2); - bufferBuilder.addVertex(matrix4f, x1, y0, z).setColor(r1, g1, b1, a1); - - if (!batching) - BufferUploader.drawWithShader(bufferBuilder.buildOrThrow()); - } - - public static void renderBoxBorder(float x0, float y0, float width, float height, float borderWidth, int color) { - renderBorder(x0, y0, x0 + width, y0 + height, borderWidth, color); - } - - public static void renderBorder(float x0, float y0, float x1, float y1, float width, int color) { - GuiRenderer.fill(x0, y0, x1, y0 + width, color); - GuiRenderer.fill(x0, y1 - width, x1, y1, color); - - GuiRenderer.fill(x0, y0 + width, x0 + width, y1 - width, color); - GuiRenderer.fill(x1 - width, y0 + width, x1, y1 - width, color); - } - - public static void drawString(Font font, Component component, int x, int y, int color) { - drawString(font, component.getVisualOrderText(), x, y, color); - } - - public static void drawString(Font font, FormattedCharSequence formattedCharSequence, int x, int y, int color) { - guiGraphics.drawString(font, formattedCharSequence, x, y, color); - } - - public static void drawString(Font font, Component component, int x, int y, int color, boolean shadow) { - drawString(font, component.getVisualOrderText(), x, y, color, shadow); - } - - public static void drawString(Font font, FormattedCharSequence formattedCharSequence, int x, int y, int color, boolean shadow) { - guiGraphics.drawString(font, formattedCharSequence, x, y, color, shadow); - } - - public static void drawCenteredString(Font font, Component component, int x, int y, int color) { - FormattedCharSequence formattedCharSequence = component.getVisualOrderText(); - guiGraphics.drawString(font, formattedCharSequence, x - font.width(formattedCharSequence) / 2, y, color); - } - - public static int getMaxTextWidth(Font font, List list) { - int maxWidth = 0; - for (var text : list) { - int width = font.width(text); - if (width > maxWidth) { - maxWidth = width; - } - } - return maxWidth; - } - - public static void beginBatch(VertexFormat.Mode mode, VertexFormat format) { - bufferBuilder = Tesselator.getInstance().begin(mode, format); - batching = true; - } - - public static void endBatch() { - BufferUploader.drawWithShader(bufferBuilder.buildOrThrow()); - batching = false; - } -} diff --git a/src/main/java/net/vulkanmod/config/gui/VOptionList.java b/src/main/java/net/vulkanmod/config/gui/VOptionList.java index f114dee64..c96ddce62 100644 --- a/src/main/java/net/vulkanmod/config/gui/VOptionList.java +++ b/src/main/java/net/vulkanmod/config/gui/VOptionList.java @@ -1,10 +1,11 @@ package net.vulkanmod.config.gui; -import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.opengl.GlStateManager; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.client.gui.components.events.GuiEventListener; -import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.input.MouseButtonEvent; import net.minecraft.util.Mth; +import net.vulkanmod.config.gui.render.GuiRenderer; import net.vulkanmod.config.gui.widget.OptionWidget; import net.vulkanmod.config.gui.widget.VAbstractWidget; import net.vulkanmod.config.option.Option; @@ -51,24 +52,15 @@ public void addAll(OptionBlock[] blocks) { int margin = this.itemMargin; - this.addEntry(new Entry(option.createOptionWidget(x0, 0, width, height), margin)); + final OptionWidget optionWidget = option.getWidget(); + optionWidget.setDimensions(x0, 0, width, height); + this.addEntry(new Entry(optionWidget, margin)); } this.addEntry(new Entry(null, 12)); } } - public void addAll(Option[] options) { - for (Option option : options) { - int x0 = this.x; - int width = this.itemWidth; - int height = this.itemHeight; - - this.addEntry(new Entry(option.createOptionWidget(x0, 0, width, height), this.itemMargin)); -// this.addEntry(new Entry(options[i].createOptionWidget(width / 2 - 155, 0, 200, 20))); - } - } - private void addEntry(Entry entry) { this.children.add(entry); @@ -104,27 +96,29 @@ void setFocused(Entry focussed) { this.focused = focussed; } - public boolean mouseClicked(double mouseX, double mouseY, int button) { - this.updateScrollingState(mouseX, button); - if (this.isMouseOver(mouseX, mouseY)) { - Entry entry = this.getEntryAtPos(mouseX, mouseY); - if (entry != null && entry.mouseClicked(mouseX, mouseY, button)) { + @Override + public boolean mouseClicked(MouseButtonEvent event, boolean bl) { + this.updateScrollingState(event.x(), event.button()); + if (this.isMouseOver(event.x(), event.y())) { + Entry entry = this.getEntryAtPos(event.x(), event.y()); + if (entry != null && entry.mouseClicked(event, bl)) { setFocused(entry); entry.setFocused(true); return true; } - return button == 0; + return event.button() == 0; } return false; } - public boolean mouseReleased(double mouseX, double mouseY, int button) { - if (this.isValidClickButton(button)) { - Entry entry = this.getEntryAtPos(mouseX, mouseY); + @Override + public boolean mouseReleased(MouseButtonEvent event) { + if (this.isValidClickButton(event.button())) { + Entry entry = this.getEntryAtPos(event.x(), event.y()); if (entry != null) { - if (entry.mouseReleased(mouseX, mouseY, button)) { + if (entry.mouseReleased(event)) { entry.setFocused(false); setFocused(null); return true; @@ -134,13 +128,14 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) { return false; } - public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - if (button != 0) { + @Override + public boolean mouseDragged(MouseButtonEvent event, double deltaX, double deltaY) { + if (event.button() != 0) { return false; } if (this.getFocused() != null) { - return this.getFocused().mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + return this.getFocused().mouseDragged(event, deltaX, deltaY); } if (!this.scrolling) { @@ -148,9 +143,9 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, double del } double maxScroll = this.getMaxScroll(); - if (mouseY < this.y) { + if (event.y() < this.y) { this.setScrollAmount(0.0); - } else if (mouseY > this.getBottom()) { + } else if (event.y() > this.getBottom()) { this.setScrollAmount(maxScroll); } else if (maxScroll > 0.0) { double barHeight = (double) this.height * this.height / this.getTotalLength(); @@ -203,8 +198,7 @@ public void updateState(double mX, double mY) { } public void renderWidget(int mouseX, int mouseY) { - RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); - GuiRenderer.enableScissor(x, y, width, height); + GuiRenderer.enableScissor(x, y, x + width, y + height); this.renderList(mouseX, mouseY); GuiRenderer.disableScissor(); @@ -212,8 +206,7 @@ public void renderWidget(int mouseX, int mouseY) { // Scroll bar int maxScroll = this.getMaxScroll(); if (maxScroll > 0) { - RenderSystem.enableBlend(); - RenderSystem.setShader(GameRenderer::getPositionColorShader); + GlStateManager._enableBlend(); int height = this.getHeight(); int totalLength = this.getTotalLength(); @@ -310,16 +303,19 @@ public int getTotalHeight() { return margin; } - public boolean mouseClicked(double mouseX, double mouseY, int button) { - return widget.mouseClicked(mouseX, mouseY, button); + @Override + public boolean mouseClicked(MouseButtonEvent event, boolean bl) { + return widget.mouseClicked(event, bl); } - public boolean mouseReleased(double mouseX, double mouseY, int button) { - return widget.mouseReleased(mouseX, mouseY, button); + @Override + public boolean mouseReleased(MouseButtonEvent event) { + return widget.mouseReleased(event); } - public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - return widget.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + @Override + public boolean mouseDragged(MouseButtonEvent event, double deltaX, double deltaY) { + return widget.mouseDragged(event, deltaX, deltaY); } @Override diff --git a/src/main/java/net/vulkanmod/config/gui/VOptionScreen.java b/src/main/java/net/vulkanmod/config/gui/VOptionScreen.java index 1a6d255b3..718b9fa8c 100644 --- a/src/main/java/net/vulkanmod/config/gui/VOptionScreen.java +++ b/src/main/java/net/vulkanmod/config/gui/VOptionScreen.java @@ -1,26 +1,32 @@ package net.vulkanmod.config.gui; import com.google.common.collect.Lists; -import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.ChatFormatting; import net.minecraft.Util; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.input.MouseButtonEvent; +import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.FormattedCharSequence; import net.vulkanmod.Initializer; +import net.vulkanmod.config.UpdateChecker; +import net.vulkanmod.config.gui.render.GuiRenderer; import net.vulkanmod.config.gui.widget.VAbstractWidget; import net.vulkanmod.config.gui.widget.VButtonWidget; import net.vulkanmod.config.option.OptionPage; import net.vulkanmod.config.option.Options; +import net.vulkanmod.vulkan.VRenderSystem; import net.vulkanmod.vulkan.util.ColorUtil; import java.util.ArrayList; import java.util.List; public class VOptionScreen extends Screen { + public final static int MARGIN = 20; public final static int RED = ColorUtil.ARGB.pack(0.3f, 0.0f, 0.0f, 0.8f); final ResourceLocation ICON = ResourceLocation.fromNamespaceAndPath("vulkanmod", "vlogo_transparent.png"); @@ -85,15 +91,13 @@ protected void init() { int bottom = 60; int itemHeight = 20; - int leftMargin = 100; -// int listWidth = (int) (this.width * 0.65f); - int listWidth = Math.min((int) (this.width * 0.65f), 420); + int leftMargin = MARGIN + 90; + int listWidth = Math.min(this.width - leftMargin - MARGIN, 420); int listHeight = this.height - top - bottom; this.buildLists(leftMargin, top, listWidth, listHeight, itemHeight); int x = leftMargin + listWidth + 10; -// int width = Math.min(this.width - this.tooltipX - 10, 200); int width = this.width - x - 10; int y = 50; @@ -115,6 +119,7 @@ protected void init() { private void buildLists(int left, int top, int listWidth, int listHeight, int itemHeight) { for (OptionPage page : this.optionPages) { page.createList(left, top, listWidth, listHeight, itemHeight); + page.updateOptionStates(); } } @@ -143,8 +148,7 @@ private void buildPage() { this.pageButtons.clear(); this.clearWidgets(); -// this.addPageButtons(20, 6, 60, 20, false); - this.addPageButtons(10, 40, 80, 22, true); + this.addPageButtons(MARGIN, 40, 80, 22, true); VOptionList currentList = this.optionPages.get(this.currentListIdx).getOptionList(); this.addWidget(currentList); @@ -193,13 +197,27 @@ private void addButtons() { this.addWidget(this.applyButton); this.addWidget(this.doneButton); this.addWidget(this.supportButton); + + if (UpdateChecker.isUpdateAvailable()) { + buttonWidth = minecraft.font.width(Component.translatable("vulkanmod.options.buttons.update_available")) + 10; + var updateButton = new VButtonWidget( + x0 - buttonWidth - buttonMargin, 6, + buttonWidth, buttonHeight, + Component.translatable("vulkanmod.options.buttons.update_available").withStyle(ChatFormatting.UNDERLINE), + button -> Util.getPlatform().openUri("https://modrinth.com/mod/vulkanmod") + ); + + this.buttons.add(updateButton); + this.addWidget(updateButton); + } } - public boolean mouseClicked(double mouseX, double mouseY, int button) { + @Override + public boolean mouseClicked(MouseButtonEvent event, boolean bl) { for (GuiEventListener element : this.children()) { - if (element.mouseClicked(mouseX, mouseY, button)) { + if (element.mouseClicked(event, bl)) { this.setFocused(element); - if (button == 0) { + if (event.button() == 0) { this.setDragging(true); } @@ -212,11 +230,11 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { } @Override - public boolean mouseReleased(double mouseX, double mouseY, int button) { + public boolean mouseReleased(MouseButtonEvent event) { this.setDragging(false); this.updateState(); - return this.getChildAt(mouseX, mouseY) - .filter(guiEventListener -> guiEventListener.mouseReleased(mouseX, mouseY, button)) + return this.getChildAt(event.x(), event.y()) + .filter(guiEventListener -> guiEventListener.mouseReleased(event)) .isPresent(); } @@ -225,29 +243,13 @@ public void onClose() { this.minecraft.setScreen(this.parent); } - @Override - public void renderBackground(GuiGraphics guiGraphics, int i, int j, float f) { - if (this.minecraft.level == null) { - this.renderPanorama(guiGraphics, f); - } - - this.renderBlurredBackground(f); - this.renderMenuBackground(guiGraphics); - - } - @Override public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float delta) { - this.renderBackground(guiGraphics, 0, 0, delta); - GuiRenderer.guiGraphics = guiGraphics; - GuiRenderer.setPoseStack(guiGraphics.pose()); - - RenderSystem.enableBlend(); - - int size = minecraft.font.lineHeight * 4; + VRenderSystem.enableBlend(); - guiGraphics.blit(ICON, 30, 4, 0f, 0f, size, size, size, size); + int size = 36; + guiGraphics.blit(RenderPipelines.GUI_TEXTURED, ICON, MARGIN + 40 - 18, 4, 0f, 0f, size, size, size, size); VOptionList currentList = this.optionPages.get(this.currentListIdx).getOptionList(); currentList.updateState(mouseX, mouseY); @@ -274,8 +276,6 @@ private void renderTooltip(List list, int x, int y) { int color = ColorUtil.ARGB.pack(intensity, intensity, intensity, 0.6f); GuiRenderer.fill(x - padding, y - padding, x + width + padding, y + height + padding, color); -// intensity = 0.4f; -// color = ColorUtil.ARGB.pack(intensity, intensity, intensity, 0.9f); color = RED; GuiRenderer.renderBorder(x - padding, y - padding, x + width + padding, y + height + padding, 1, color); @@ -304,6 +304,12 @@ private void updateState() { modified |= page.optionChanged(); } + if (modified) { + for (var page : this.optionPages) { + page.optionChanged(); + } + } + this.applyButton.active = modified; } @@ -319,6 +325,7 @@ private void applyOptions() { List pages = List.copyOf(this.optionPages); for (var page : pages) { page.applyOptionChanges(); + page.updateOptionStates(); } Initializer.CONFIG.write(); diff --git a/src/main/java/net/vulkanmod/config/gui/render/GuiRenderer.java b/src/main/java/net/vulkanmod/config/gui/render/GuiRenderer.java new file mode 100644 index 000000000..e268dab92 --- /dev/null +++ b/src/main/java/net/vulkanmod/config/gui/render/GuiRenderer.java @@ -0,0 +1,101 @@ +package net.vulkanmod.config.gui.render; + +import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.blaze3d.vertex.*; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.render.TextureSetup; +import net.minecraft.network.chat.Component; +import net.minecraft.util.FormattedCharSequence; +import org.joml.Matrix3x2f; + +import java.util.List; + +public abstract class GuiRenderer { + + public static Minecraft minecraft; + public static GuiGraphics guiGraphics; + public static PoseStack pose; + public static BufferBuilder bufferBuilder; + + public static void enableScissor(int i, int j, int k, int l) { + guiGraphics.enableScissor(i, j, k, l); + } + + public static void disableScissor() { + guiGraphics.disableScissor(); + } + + public static void fillBox(int x0, int y0, int width, int height, int color) { + fill(x0, y0, x0 + width, y0 + height, 0, color); + } + + public static void fill(int x0, int y0, int x1, int y1, int color) { + fill(x0, y0, x1, y1, 0, color); + } + + public static void fill(int x0, int y0, int x1, int y1, int z, int color) { + guiGraphics.fill(x0, y0, x1, y1, color); + } + + public static void fillGradient(int x0, int y0, int x1, int y1, int color1, int color2) { + fillGradient(x0, y0, x1, y1, 0, color1, color2); + } + + public static void fillGradient(int x0, int y0, int x1, int y1, int z, int color1, int color2) { + guiGraphics.fillGradient(x0, y0, x1, y1, color1, color2); + } + + public static void renderBoxBorder(int x0, int y0, int width, int height, int borderWidth, int color) { + renderBorder(x0, y0, x0 + width, y0 + height, borderWidth, color); + } + + public static void renderBorder(int x0, int y0, int x1, int y1, int width, int color) { + GuiRenderer.fill(x0, y0, x1, y0 + width, color); + GuiRenderer.fill(x0, y1 - width, x1, y1, color); + + GuiRenderer.fill(x0, y0 + width, x0 + width, y1 - width, color); + GuiRenderer.fill(x1 - width, y0 + width, x1, y1 - width, color); + } + + public static void drawString(Font font, Component component, int x, int y, int color) { + drawString(font, component.getVisualOrderText(), x, y, color); + } + + public static void drawString(Font font, FormattedCharSequence formattedCharSequence, int x, int y, int color) { + guiGraphics.drawString(font, formattedCharSequence, x, y, color); + } + + public static void drawString(Font font, Component component, int x, int y, int color, boolean shadow) { + drawString(font, component.getVisualOrderText(), x, y, color, shadow); + } + + public static void drawString(Font font, FormattedCharSequence formattedCharSequence, int x, int y, int color, boolean shadow) { + guiGraphics.drawString(font, formattedCharSequence, x, y, color, shadow); + } + + public static void drawCenteredString(Font font, Component component, int x, int y, int color) { + FormattedCharSequence formattedCharSequence = component.getVisualOrderText(); + guiGraphics.drawString(font, formattedCharSequence, x - font.width(formattedCharSequence) / 2, y, color); + } + + public static int getMaxTextWidth(Font font, List list) { + int maxWidth = 0; + for (var text : list) { + int width = font.width(text); + if (width > maxWidth) { + maxWidth = width; + } + } + return maxWidth; + } + + public static void submitPolygon(RenderPipeline renderPipeline, TextureSetup textureSetup, float[][] vertices, int color) { + guiGraphics.guiRenderState.submitGuiElement( + new PolygonRenderState( + renderPipeline, textureSetup, new Matrix3x2f(), vertices, color, guiGraphics.scissorStack.peek() + ) + ); + } +} diff --git a/src/main/java/net/vulkanmod/config/gui/render/PolygonRenderState.java b/src/main/java/net/vulkanmod/config/gui/render/PolygonRenderState.java new file mode 100644 index 000000000..ff4b2b03d --- /dev/null +++ b/src/main/java/net/vulkanmod/config/gui/render/PolygonRenderState.java @@ -0,0 +1,73 @@ +package net.vulkanmod.config.gui.render; + +import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.gui.navigation.ScreenRectangle; +import net.minecraft.client.gui.render.TextureSetup; +import net.minecraft.client.gui.render.state.GuiElementRenderState; +import org.jetbrains.annotations.Nullable; +import org.joml.Matrix3x2f; + +public record PolygonRenderState ( + RenderPipeline pipeline, + TextureSetup textureSetup, + Matrix3x2f pose, + float[][] vertices, + int col, + @Nullable ScreenRectangle scissorArea, + @Nullable ScreenRectangle bounds +) implements GuiElementRenderState { + + public PolygonRenderState( + RenderPipeline renderPipeline, + TextureSetup textureSetup, + Matrix3x2f pose, + float[][] vertices, + int color, + @Nullable ScreenRectangle screenRectangle + ) { + this(renderPipeline, textureSetup, pose, vertices, color, screenRectangle, + getBounds(vertices, pose, screenRectangle)); + } + + @Override + public void buildVertices(VertexConsumer vertexConsumer) { + for (float[] vertex : vertices) { + float x = vertex[0]; + float y = vertex[1]; + vertexConsumer.addVertexWith2DPose(this.pose(), x, y) + .setColor(this.col); + } + } + + @Nullable + private static ScreenRectangle getBounds(float[][] vertices, Matrix3x2f matrix3x2f, @Nullable ScreenRectangle screenRectangle) { + float x0 = vertices[0][0]; + float x1 = vertices[0][0]; + float y0 = vertices[0][1]; + float y1 = vertices[0][1]; + + for (float[] vertex : vertices) { + float x = vertex[0]; + float y = vertex[1]; + + if (x < x0) { + x0 = x; + } + if (x > x1) { + x1 = x; + } + + if (y < y0) { + y0 = y; + } + if (y > y1) { + y1 = y; + } + } + + ScreenRectangle screenRectangle2 = new ScreenRectangle((int) x0, (int) y0, (int) (x1 - x0), (int) (y1 - y0)).transformMaxBounds(matrix3x2f); + return screenRectangle != null ? screenRectangle.intersection(screenRectangle2) : screenRectangle2; + } +} + diff --git a/src/main/java/net/vulkanmod/config/gui/widget/CyclingOptionWidget.java b/src/main/java/net/vulkanmod/config/gui/widget/CyclingOptionWidget.java index 20c601476..0537396cc 100644 --- a/src/main/java/net/vulkanmod/config/gui/widget/CyclingOptionWidget.java +++ b/src/main/java/net/vulkanmod/config/gui/widget/CyclingOptionWidget.java @@ -1,52 +1,53 @@ package net.vulkanmod.config.gui.widget; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.*; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; -import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.gui.render.TextureSetup; import net.minecraft.network.chat.Component; -import net.vulkanmod.config.gui.GuiRenderer; +import net.vulkanmod.config.gui.render.GuiRenderer; import net.vulkanmod.config.option.CyclingOption; +import net.vulkanmod.render.shader.CustomRenderPipelines; import net.vulkanmod.vulkan.util.ColorUtil; -import org.joml.Matrix4f; public class CyclingOptionWidget extends OptionWidget> { - private Button leftButton; - private Button rightButton; + private final Button leftButton; + private final Button rightButton; private boolean focused; - public CyclingOptionWidget(CyclingOption option, int x, int y, int width, int height, Component name) { - super(x, y, width, height, name); - this.option = option; - this.leftButton = new Button(this.controlX, 16, Button.Direction.LEFT); - this.rightButton = new Button(this.controlX + this.controlWidth - 16, 16, Button.Direction.RIGHT); + public CyclingOptionWidget(CyclingOption option, Component name) { + super(option, name); + this.leftButton = new Button(Button.Direction.LEFT); + this.rightButton = new Button(Button.Direction.RIGHT); + } + + @Override + public void setDimensions(int x, int y, int width, int height) { + super.setDimensions(x, y, width, height); -// updateDisplayedValue(option.getValueText()); + this.leftButton.setDimensions(this.controlX, 16); + this.rightButton.setDimensions(this.controlX + this.controlWidth - 16, 16); } @Override protected int getYImage(boolean hovered) { - return 0; + return 0; } public void renderControls(double mouseX, double mouseY) { - RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); - this.renderBars(); this.leftButton.setStatus(option.index() > 0); this.rightButton.setStatus(option.index() < option.getValues().length - 1); - int color = this.active ? 0xFFFFFF : 0xA0A0A0; + int color = this.active ? 0xFFFFFFFF : 0xFFA0A0A0; Font textRenderer = Minecraft.getInstance().font; int x = this.controlX + this.controlWidth / 2; int y = this.y + (this.height - 9) / 2; GuiRenderer.drawCenteredString(textRenderer, this.getDisplayedValue(), x, y, color); - this.leftButton.renderButton(GuiRenderer.guiGraphics.pose(), mouseX, mouseY); - this.rightButton.renderButton(GuiRenderer.guiGraphics.pose(), mouseX, mouseY); + this.leftButton.renderButton(mouseX, mouseY); + this.rightButton.renderButton(mouseX, mouseY); } public void renderBars() { @@ -64,14 +65,21 @@ public void renderBars() { return; for (int i = 0; i < count; i++) { - float x0 = this.controlX + margin + i * (barWidth + padding); - float y0 = this.y + this.height - 5.0f; + int x0 = this.controlX + margin + i * (barWidth + padding); + int y0 = this.y + this.height - 5; int c = i == current ? activeColor : color; - GuiRenderer.fill(x0, y0, x0 + barWidth, y0 + 1.5f, c); + GuiRenderer.fill(x0, y0, x0 + barWidth, (int) (y0 + 1.5f), c); } } + public void setActive(boolean active) { + this.active = active; + + this.leftButton.active &= active; + this.rightButton.active &= active; + } + @Override public void onClick(double mouseX, double mouseY) { if (leftButton.isHovered(mouseX, mouseY)) { @@ -103,18 +111,25 @@ public boolean isFocused() { } class Button { + final int ACTIVE_COLOR = ColorUtil.ARGB.pack(1.0f, 1.0f, 1.0f, 0.8f); + final int HOVERED_COLOR = ColorUtil.ARGB.pack(1.0f, 1.0f, 1.0f, 1.0f); + final int INACTIVE_COLOR = ColorUtil.ARGB.pack(0.3f, 0.3f, 0.3f, 0.8f); + int x; int width; boolean active; Direction direction; - Button(int x, int width, Direction direction) { - this.x = x; - this.width = width; + Button(Direction direction) { this.active = true; this.direction = direction; } + public void setDimensions(int x, int width) { + this.x = x; + this.width = width; + } + boolean isHovered(double mouseX, double mouseY) { return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; } @@ -123,44 +138,43 @@ void setStatus(boolean status) { this.active = status; } - void renderButton(PoseStack matrices, double mouseX, double mouseY) { - Tesselator tesselator = Tesselator.getInstance(); - BufferBuilder bufferBuilder = tesselator.begin(VertexFormat.Mode.TRIANGLE_STRIP, DefaultVertexFormat.POSITION); - - RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); - + void renderButton(double mouseX, double mouseY) { float f = this.isHovered(mouseX, mouseY) && this.active ? 5.0f : 4.5f; - Matrix4f matrix4f = matrices.last().pose(); - - RenderSystem.setShader(GameRenderer::getPositionShader); - RenderSystem.enableBlend(); - - if(this.isHovered(mouseX, mouseY) && this.active) - RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); - else if(this.active) - RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 0.8f); - else - RenderSystem.setShaderColor(0.3f, 0.3f, 0.3f, 0.8f); + int color; + if (this.isHovered(mouseX, mouseY) && this.active) { + color = HOVERED_COLOR; + } + else if (this.active) { + color = ACTIVE_COLOR; + } + else { + color = INACTIVE_COLOR; + } float h = f; float w = f - 1.0f; float yC = y + height * 0.5f; float xC = x + width * 0.5f; + + float[][] vertices; if (this.direction == Direction.LEFT) { - bufferBuilder.addVertex(matrix4f, xC - w, yC, 0); - bufferBuilder.addVertex(matrix4f, xC + w, yC + h, 0); - bufferBuilder.addVertex(matrix4f, xC + w, yC - h, 0); - } else { - bufferBuilder.addVertex(matrix4f, xC + w, yC, 0); - bufferBuilder.addVertex(matrix4f, xC - w, yC - h, 0); - bufferBuilder.addVertex(matrix4f, xC - w, yC + h, 0); + vertices = new float[][]{ + {xC - w, yC}, + {xC + w, yC + h}, + {xC + w, yC - h}, + }; + } + else { + vertices = new float[][]{ + {xC + w, yC}, + {xC - w, yC - h}, + {xC - w, yC + h}, + }; } - BufferUploader.drawWithShader(bufferBuilder.buildOrThrow()); - RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); - RenderSystem.setShader(GameRenderer::getPositionTexShader); + GuiRenderer.submitPolygon(CustomRenderPipelines.GUI_TRIANGLES, TextureSetup.noTexture(), vertices, color); } enum Direction { diff --git a/src/main/java/net/vulkanmod/config/gui/widget/OptionWidget.java b/src/main/java/net/vulkanmod/config/gui/widget/OptionWidget.java index a9fe679ce..e70d8e05f 100644 --- a/src/main/java/net/vulkanmod/config/gui/widget/OptionWidget.java +++ b/src/main/java/net/vulkanmod/config/gui/widget/OptionWidget.java @@ -1,31 +1,19 @@ package net.vulkanmod.config.gui.widget; -import com.mojang.blaze3d.systems.RenderSystem; -import net.minecraft.Util; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.narration.NarratableEntry; import net.minecraft.client.gui.narration.NarrationElementOutput; -import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.input.MouseButtonEvent; import net.minecraft.client.resources.sounds.SimpleSoundInstance; import net.minecraft.client.sounds.SoundManager; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundEvents; -import net.minecraft.util.Mth; -import net.vulkanmod.config.gui.GuiElement; -import net.vulkanmod.config.gui.GuiRenderer; -import net.vulkanmod.config.option.CyclingOption; +import net.vulkanmod.config.gui.render.GuiRenderer; import net.vulkanmod.config.option.Option; -import net.vulkanmod.render.util.MathUtil; import net.vulkanmod.vulkan.util.ColorUtil; -import java.util.Objects; - -public abstract class OptionWidget> extends VAbstractWidget - implements NarratableEntry { - +public abstract class OptionWidget> extends VAbstractWidget implements NarratableEntry { public int controlX; public int controlWidth; private final Component name; @@ -33,24 +21,22 @@ public abstract class OptionWidget> extends VAbstractWidget protected boolean controlHovered; - O option; + final O option; - public OptionWidget(int x, int y, int width, int height, Component name) { - this.x = x; - this.y = y; - this.width = width; - this.height = height; + public OptionWidget(O option, Component name) { + this.option = option; this.name = name; this.displayedValue = Component.literal("N/A"); + } + + @Override + public void setDimensions(int x, int y, int width, int height) { + super.setDimensions(x, y, width, height); this.controlWidth = Math.min((int) (width * 0.5f) - 8, 120); this.controlX = this.x + this.width - this.controlWidth - 8; } - public void setOption(O option) { - this.option = option; - } - public void render(double mouseX, double mouseY) { if (!this.visible) { return; @@ -69,12 +55,7 @@ public void updateState() { public void renderWidget(double mouseX, double mouseY) { Minecraft minecraftClient = Minecraft.getInstance(); - RenderSystem.setShader(GameRenderer::getPositionTexShader); - RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); int i = this.getYImage(this.isHovered()); - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); - RenderSystem.enableDepthTest(); int xPadding = 0; int yPadding = 0; @@ -84,14 +65,11 @@ public void renderWidget(double mouseX, double mouseY) { this.renderHovering(0, 0); - color = this.active ? 0xFFFFFF : 0xA0A0A0; -// j = 0xB0f0d0a0; + color = this.active ? 0xFFFFFFFF : 0xFFA0A0A0; Font textRenderer = minecraftClient.font; GuiRenderer.drawString(textRenderer, this.getName().getVisualOrderText(), this.x + 8, this.y + (this.height - 8) / 2, color); - RenderSystem.enableBlend(); - this.renderControls(mouseX, mouseY); } @@ -122,32 +100,32 @@ protected boolean isValidClickButton(int button) { } @Override - public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - if (this.isValidClickButton(button)) { - this.onDrag(mouseX, mouseY, deltaX, deltaY); + public boolean mouseDragged(MouseButtonEvent event, double deltaX, double deltaY) { + if (this.isValidClickButton(event.button())) { + this.onDrag(event.x(), event.y(), deltaX, deltaY); return true; } return false; } @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { + public boolean mouseClicked(MouseButtonEvent event, boolean bl) { if (!this.active || !this.visible) { return false; } - if (this.isValidClickButton(button) && this.clicked(mouseX, mouseY)) { + if (this.isValidClickButton(event.button()) && this.clicked(event.x(), event.y())) { this.playDownSound(Minecraft.getInstance().getSoundManager()); - this.onClick(mouseX, mouseY); + this.onClick(event.x(), event.y()); return true; } return false; } @Override - public boolean mouseReleased(double mouseX, double mouseY, int button) { - if (this.isValidClickButton(button)) { - this.onRelease(mouseX, mouseY); + public boolean mouseReleased(MouseButtonEvent event) { + if (this.isValidClickButton(event.button())) { + this.onRelease(event.x(), event.y()); return true; } return false; diff --git a/src/main/java/net/vulkanmod/config/gui/widget/RangeOptionWidget.java b/src/main/java/net/vulkanmod/config/gui/widget/RangeOptionWidget.java index 7cef7e107..47ccb0ddd 100644 --- a/src/main/java/net/vulkanmod/config/gui/widget/RangeOptionWidget.java +++ b/src/main/java/net/vulkanmod/config/gui/widget/RangeOptionWidget.java @@ -1,12 +1,12 @@ package net.vulkanmod.config.gui.widget; -import com.mojang.blaze3d.systems.RenderSystem; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; +import net.minecraft.client.input.KeyEvent; import net.minecraft.client.sounds.SoundManager; import net.minecraft.network.chat.Component; import net.minecraft.util.Mth; -import net.vulkanmod.config.gui.GuiRenderer; +import net.vulkanmod.config.gui.render.GuiRenderer; import net.vulkanmod.config.option.RangeOption; import net.vulkanmod.vulkan.util.ColorUtil; import org.lwjgl.glfw.GLFW; @@ -16,11 +16,9 @@ public class RangeOptionWidget extends OptionWidget { private boolean focused; - public RangeOptionWidget(RangeOption option, int x, int y, int width, int height, Component name) { - super(x, y, width, height, name); - this.setOption(option); + public RangeOptionWidget(RangeOption option, Component name) { + super(option, name); this.setValue(option.getScaledValue()); - } @Override @@ -30,36 +28,34 @@ protected int getYImage(boolean hovered) { @Override protected void renderControls(double mouseX, double mouseY) { - RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); - int valueX = this.controlX + (int) (this.value * (this.controlWidth)); - if (this.controlHovered) { + if (this.controlHovered && this.active) { int halfWidth = 2; int halfHeight = 4; - float y0 = this.y + this.height * 0.5f - 1.0f; - float y1 = y0 + 2.0f; + int y0 = (int) (this.y + this.height * 0.5f - 1.0f); + int y1 = (int) (y0 + 2.0f); GuiRenderer.fill(this.controlX, y0, this.controlX + this.controlWidth, y1, ColorUtil.ARGB.pack(1.0f, 1.0f, 1.0f, 0.1f)); GuiRenderer.fill(this.controlX, y0, valueX - halfWidth, y1, ColorUtil.ARGB.pack(1.0f, 1.0f, 1.0f, 0.3f)); int color = ColorUtil.ARGB.pack(1.0f, 1.0f, 1.0f, 0.3f); GuiRenderer.renderBorder(valueX - halfWidth, y0 - halfHeight, valueX + halfWidth, y1 + halfHeight, 1, color); -// GuiRenderer.fill(valueX - halfWidth, y0 - 3.0f, valueX + halfWidth, y1 + 3.0f, color); } else { - float y0 = this.y + this.height - 5.0f; - float y1 = y0 + 1.5f; + int y0 = (int) (this.y + this.height - 5.0f); + int y1 = (int) (y0 + 1.5f); GuiRenderer.fill(this.controlX, y0, this.controlX + this.controlWidth, y1, ColorUtil.ARGB.pack(1.0f, 1.0f, 1.0f, 0.3f)); - GuiRenderer.fill(this.controlX, y0, valueX, y1, ColorUtil.ARGB.pack(1.0f, 1.0f, 1.0f, 0.8f)); + + float alpha = this.active ? 0.8f : 0.3f; + GuiRenderer.fill(this.controlX, y0, valueX, y1, ColorUtil.ARGB.pack(1.0f, 1.0f, 1.0f, alpha)); } - int color = this.active ? 0xFFFFFF : 0xA0A0A0; + int color = this.active ? 0xFFFFFFFF : 0xFFA0A0A0; Font font = Minecraft.getInstance().font; var text = this.getDisplayedValue(); int width = font.width(text); int x = this.controlX + this.controlWidth / 2 - width / 2; -// int x = (int) (this.x + 0.5f * width); int y = this.y + (this.height - 9) / 2; GuiRenderer.drawString(font, text.getVisualOrderText(), x, y, color); } @@ -70,9 +66,9 @@ public void onClick(double mouseX, double mouseY) { } @Override - public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - boolean isLeft = keyCode == GLFW.GLFW_KEY_LEFT; - boolean isRight = keyCode == GLFW.GLFW_KEY_RIGHT; + public boolean keyPressed(KeyEvent event) { + boolean isLeft = event.key() == GLFW.GLFW_KEY_LEFT; + boolean isRight = event.key() == GLFW.GLFW_KEY_RIGHT; if (isLeft || isRight) { float direction = isLeft ? -1.0f : 1.0f; diff --git a/src/main/java/net/vulkanmod/config/gui/widget/SwitchOptionWidget.java b/src/main/java/net/vulkanmod/config/gui/widget/SwitchOptionWidget.java index 340902f3c..61966ed0c 100644 --- a/src/main/java/net/vulkanmod/config/gui/widget/SwitchOptionWidget.java +++ b/src/main/java/net/vulkanmod/config/gui/widget/SwitchOptionWidget.java @@ -3,32 +3,31 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.network.chat.Component; -import net.vulkanmod.config.gui.GuiRenderer; +import net.vulkanmod.config.gui.render.GuiRenderer; import net.vulkanmod.config.option.SwitchOption; import net.vulkanmod.vulkan.util.ColorUtil; public class SwitchOptionWidget extends OptionWidget { private boolean focused; - public SwitchOptionWidget(SwitchOption option, int x, int y, int width, int height, Component name) { - super(x, y, width, height, name); - this.option = option; + public SwitchOptionWidget(SwitchOption option, Component name) { + super(option, name); updateDisplayedValue(); } @Override protected void renderControls(double mouseX, double mouseY) { int center = controlX + controlWidth / 2; - float halfWidth = 12; - float x0 = center - halfWidth; - float y0 = y + 4; - float height = this.height - 8; + int halfWidth = 12; + int x0 = center - halfWidth; + int y0 = y + 4; + int height = this.height - 8; int color; - float w1 = halfWidth - 4; - float h1 = height - 4; + int w1 = halfWidth - 4; + int h1 = height - 4; if (this.option.getNewValue()) { - float x1 = x0 + halfWidth + 2; + int x1 = x0 + halfWidth + 2; color = ColorUtil.ARGB.pack(0.4f, 0.4f, 0.4f, 1.0f); GuiRenderer.fillBox(x0 + 2, y0 + 2, x1 - (x0 + 2) - 1, h1, color); @@ -43,7 +42,7 @@ protected void renderControls(double mouseX, double mouseY) { color = ColorUtil.ARGB.pack(0.6f, 0.6f, 0.6f, 1.0f); GuiRenderer.renderBoxBorder(x0, y0, halfWidth * 2, height, 1, color); - color = this.active ? 0xFFFFFF : 0xA0A0A0; + color = this.active ? 0xFFFFFFFF : 0xFFA0A0A0; Font textRenderer = Minecraft.getInstance().font; int margin = Math.max( textRenderer.width(Component.translatable("options.on").getString()) / 3, diff --git a/src/main/java/net/vulkanmod/config/gui/widget/VAbstractWidget.java b/src/main/java/net/vulkanmod/config/gui/widget/VAbstractWidget.java index 58bbd0d0e..43959f7a8 100644 --- a/src/main/java/net/vulkanmod/config/gui/widget/VAbstractWidget.java +++ b/src/main/java/net/vulkanmod/config/gui/widget/VAbstractWidget.java @@ -1,12 +1,13 @@ package net.vulkanmod.config.gui.widget; import net.minecraft.client.Minecraft; +import net.minecraft.client.input.MouseButtonEvent; import net.minecraft.client.resources.sounds.SimpleSoundInstance; import net.minecraft.client.sounds.SoundManager; import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundEvents; import net.vulkanmod.config.gui.GuiElement; -import net.vulkanmod.config.gui.GuiRenderer; +import net.vulkanmod.config.gui.render.GuiRenderer; import net.vulkanmod.vulkan.util.ColorUtil; public abstract class VAbstractWidget extends GuiElement { @@ -16,6 +17,13 @@ public abstract class VAbstractWidget extends GuiElement { protected Component message; + public void setDimensions(int x, int y, int width, int height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + public void render(double mX, double mY) { this.updateState(mX, mY); this.renderWidget(mX, mY); @@ -33,6 +41,10 @@ public void onRelease(double mX, double mY) { protected void onDrag(double mX, double mY, double f, double g) { } + public void setActive(boolean active) { + this.active = active; + } + protected void renderHovering(int xPadding, int yPadding) { float hoverMultiplier = this.getHoverMultiplier(200); @@ -56,13 +68,13 @@ protected void renderHovering(int xPadding, int yPadding) { } @Override - public boolean mouseClicked(double mX, double mY, int button) { + public boolean mouseClicked(MouseButtonEvent event, boolean bl) { if (this.active && this.visible) { - if (this.isValidClickButton(button)) { - boolean bl = this.clicked(mX, mY); - if (bl) { + if (this.isValidClickButton(event.button())) { + boolean clicked = this.clicked(event.x(), event.y()); + if (clicked) { this.playDownSound(Minecraft.getInstance().getSoundManager()); - this.onClick(mX, mY); + this.onClick(event.x(), event.y()); return true; } } @@ -81,9 +93,9 @@ protected boolean clicked(double mX, double mY) { } @Override - public boolean mouseReleased(double mX, double mY, int button) { - if (this.isValidClickButton(button)) { - this.onRelease(mX, mY); + public boolean mouseReleased(MouseButtonEvent event) { + if (this.isValidClickButton(event.button())) { + this.onRelease(event.x(), event.y()); return true; } else { return false; @@ -95,9 +107,9 @@ protected boolean isValidClickButton(int button) { } @Override - public boolean mouseDragged(double mX, double mY, int button, double f, double g) { - if (this.isValidClickButton(button)) { - this.onDrag(mX, mY, f, g); + public boolean mouseDragged(MouseButtonEvent event, double d, double e) { + if (this.isValidClickButton(event.button())) { + this.onDrag(event.x(), event.y(), d, e); return true; } else { return false; diff --git a/src/main/java/net/vulkanmod/config/gui/widget/VButtonWidget.java b/src/main/java/net/vulkanmod/config/gui/widget/VButtonWidget.java index 3664d9429..b1effb5ed 100644 --- a/src/main/java/net/vulkanmod/config/gui/widget/VButtonWidget.java +++ b/src/main/java/net/vulkanmod/config/gui/widget/VButtonWidget.java @@ -1,12 +1,11 @@ package net.vulkanmod.config.gui.widget; -import com.mojang.blaze3d.systems.RenderSystem; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; -import net.minecraft.client.renderer.GameRenderer; import net.minecraft.network.chat.Component; import net.minecraft.util.Mth; -import net.vulkanmod.config.gui.GuiRenderer; +import net.vulkanmod.config.gui.render.GuiRenderer; +import net.vulkanmod.vulkan.VRenderSystem; import net.vulkanmod.vulkan.util.ColorUtil; import java.util.function.Consumer; @@ -27,10 +26,6 @@ public VButtonWidget(int x, int y, int width, int height, Component message, Con public void renderWidget(double mouseX, double mouseY) { Minecraft minecraftClient = Minecraft.getInstance(); Font textRenderer = minecraftClient.font; - RenderSystem.setShader(GameRenderer::getPositionTexShader); - RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, this.alpha); - - RenderSystem.enableBlend(); int xPadding = 0; int yPadding = 0; @@ -42,21 +37,16 @@ public void renderWidget(double mouseX, double mouseY) { this.renderHovering(0, 0); } - int j = this.active ? 0xFFFFFF : 0xA0A0A0; - GuiRenderer.drawCenteredString(textRenderer, this.message, this.x + this.width / 2, this.y + (this.height - 8) / 2, j | Mth.ceil(this.alpha * 255.0f) << 24); - - RenderSystem.enableBlend(); - - if(this.selected) { -// color = ColorUtil.ARGB.pack(1.0f, 1.0f, 1.0f, 1.0f); + if (this.selected) { color = ColorUtil.ARGB.pack(0.3f, 0.0f, 0.0f, 1.0f); -// GuiRenderer.fillBox(this.x, this.y + this.height - 1, this.width, 1, color); - GuiRenderer.fillBox(this.x, this.y, 1.5f, this.height, color); + GuiRenderer.fillBox(this.x, this.y, (int) 1.5f, this.height, color); -// color = ColorUtil.ARGB.pack(0.5f, 0.5f, 0.5f, 0.2f); color = ColorUtil.ARGB.pack(0.3f, 0.0f, 0.0f, 0.2f); GuiRenderer.fillBox(this.x, this.y, this.width, this.height, color); } + + int j = this.active ? 0xFFFFFF : 0xA0A0A0; + GuiRenderer.drawCenteredString(textRenderer, this.message, this.x + this.width / 2, this.y + (this.height - 8) / 2, j | Mth.ceil(this.alpha * 255.0f) << 24); } public void setSelected(boolean selected) { diff --git a/src/main/java/net/vulkanmod/config/option/CyclingOption.java b/src/main/java/net/vulkanmod/config/option/CyclingOption.java index d6080f7fd..45487f278 100644 --- a/src/main/java/net/vulkanmod/config/option/CyclingOption.java +++ b/src/main/java/net/vulkanmod/config/option/CyclingOption.java @@ -20,8 +20,8 @@ public CyclingOption(Component name, E[] values, Consumer setter, Supplier } @Override - public OptionWidget createOptionWidget(int x, int y, int width, int height) { - return new CyclingOptionWidget(this, x, y, width, height, this.name); + public OptionWidget createWidget() { + return new CyclingOptionWidget(this, this.name); } public void updateOption(E[] values, Consumer setter, Supplier getter) { diff --git a/src/main/java/net/vulkanmod/config/option/Option.java b/src/main/java/net/vulkanmod/config/option/Option.java index a1425ccf8..6918a4e5d 100644 --- a/src/main/java/net/vulkanmod/config/option/Option.java +++ b/src/main/java/net/vulkanmod/config/option/Option.java @@ -19,8 +19,11 @@ public abstract class Option { protected Function translator; + OptionWidget widget; + protected boolean active; protected Runnable onChange; + protected Supplier activationFn; public Option(Component name, Consumer setter, Supplier getter, Function translator) { this.name = name; @@ -59,10 +62,19 @@ public Option setTranslator(Function translator) { public Option setActive(boolean active) { this.active = active; + this.widget.active = active; return this; } - public abstract OptionWidget createOptionWidget(int x, int y, int width, int height); + abstract OptionWidget createWidget(); + + public OptionWidget getWidget() { + if (this.widget == null) { + this.widget = this.createWidget(); + } + + return this.widget; + } public void setNewValue(T t) { this.newValue = t; @@ -71,6 +83,17 @@ public void setNewValue(T t) { onChange.run(); } + public void updateActiveState() { + if (this.activationFn != null) { + this.active = this.activationFn.get(); + } + else { + this.active = true; + } + + this.widget.setActive(this.active); + } + public Component getName() { return this.name; } @@ -79,14 +102,15 @@ public void setOnChange(Runnable runnable) { onChange = runnable; } + public void setActivationFn(Supplier activationFn) { + this.activationFn = activationFn; + } + public boolean isChanged() { return !this.newValue.equals(this.value); } public void apply() { - if(!isChanged()) - return; - onApply.accept(this.newValue); this.value = this.newValue; } diff --git a/src/main/java/net/vulkanmod/config/option/OptionPage.java b/src/main/java/net/vulkanmod/config/option/OptionPage.java index 8d783fe4e..7000e1468 100644 --- a/src/main/java/net/vulkanmod/config/option/OptionPage.java +++ b/src/main/java/net/vulkanmod/config/option/OptionPage.java @@ -36,8 +36,17 @@ public boolean optionChanged() { public void applyOptionChanges() { for (var block : this.optionBlocks) { for (var option : block.options()) { - if (option.isChanged()) + if (option.isChanged()) { option.apply(); + } + } + } + } + + public void updateOptionStates() { + for (var block : this.optionBlocks) { + for (var option : block.options()) { + option.updateActiveState(); } } } diff --git a/src/main/java/net/vulkanmod/config/option/Options.java b/src/main/java/net/vulkanmod/config/option/Options.java index b84b7d3a2..560e6d2c9 100644 --- a/src/main/java/net/vulkanmod/config/option/Options.java +++ b/src/main/java/net/vulkanmod/config/option/Options.java @@ -3,12 +3,16 @@ import com.mojang.blaze3d.platform.Window; import net.minecraft.client.*; import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ParticleStatus; import net.vulkanmod.Initializer; import net.vulkanmod.config.Config; import net.vulkanmod.config.gui.OptionBlock; import net.vulkanmod.config.video.VideoModeManager; import net.vulkanmod.config.video.VideoModeSet; +import net.vulkanmod.config.video.WindowMode; +import net.vulkanmod.render.chunk.WorldRenderer; import net.vulkanmod.render.chunk.build.light.LightMode; +import net.vulkanmod.render.vertex.TerrainRenderType; import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.device.DeviceManager; @@ -76,70 +80,76 @@ public static OptionBlock[] getVideoOpts() { new OptionBlock("", new Option[]{ resolutionOption, RefreshRate, - new SwitchOption(Component.translatable("options.fullscreen"), + new CyclingOption<>(Component.translatable("vulkanmod.options.windowMode"), + WindowMode.values(), value -> { - minecraftOptions.fullscreen().set(value); -// window.toggleFullScreen(); - fullscreenDirty = true; - }, - () -> minecraftOptions.fullscreen().get()), - new SwitchOption(Component.translatable("vulkanmod.options.windowedFullscreen"), - value -> { - config.windowedFullscreen = value; + boolean exclusiveFullscreen = value == WindowMode.EXCLUSIVE_FULLSCREEN; + minecraftOptions.fullscreen() + .set(exclusiveFullscreen); + + config.windowMode = value.mode; fullscreenDirty = true; }, - () -> config.windowedFullscreen), + () -> WindowMode.fromValue(config.windowMode)) + .setTranslator(value -> Component.translatable(WindowMode.getComponentName(value))), new RangeOption(Component.translatable("options.framerateLimit"), - 10, 260, 10, - value -> Component.nullToEmpty(value == 260 ? - Component.translatable("options.framerateLimit.max").getString() : - String.valueOf(value)), - value -> { - minecraftOptions.framerateLimit().set(value); - window.setFramerateLimit(value); - }, - () -> minecraftOptions.framerateLimit().get()), + 10, 260, 10, + value -> Component.nullToEmpty(value == 260 ? + Component.translatable( + "options.framerateLimit.max") + .getString() : + String.valueOf(value)), + value -> { + minecraftOptions.framerateLimit().set(value); + minecraft.getFramerateLimitTracker().setFramerateLimit(value); + }, + () -> minecraftOptions.framerateLimit().get()), new SwitchOption(Component.translatable("options.vsync"), - value -> { - minecraftOptions.enableVsync().set(value); - window.updateVsync(value); - }, - () -> minecraftOptions.enableVsync().get()), + value -> { + minecraftOptions.enableVsync().set(value); + window.updateVsync(value); + }, + () -> minecraftOptions.enableVsync().get()), + new CyclingOption<>(Component.translatable("options.inactivityFpsLimit"), + InactivityFpsLimit.values(), + value -> minecraftOptions.inactivityFpsLimit().set(value), + () -> minecraftOptions.inactivityFpsLimit().get()) + .setTranslator(inactivityFpsLimit -> Component.translatable(inactivityFpsLimit.getKey())) }), new OptionBlock("", new Option[]{ new RangeOption(Component.translatable("options.guiScale"), - 0, window.calculateScale(0, minecraft.isEnforceUnicode()), 1, - value -> Component.translatable((value == 0) - ? "options.guiScale.auto" - : String.valueOf(value)), - value -> { - minecraftOptions.guiScale().set(value); - minecraft.resizeDisplay(); - }, - () -> (minecraftOptions.guiScale().get())), + 0, window.calculateScale(0, minecraft.isEnforceUnicode()), 1, + value -> Component.translatable((value == 0) + ? "options.guiScale.auto" + : String.valueOf(value)), + value -> { + minecraftOptions.guiScale().set(value); + minecraft.resizeDisplay(); + }, + () -> (minecraftOptions.guiScale().get())), new RangeOption(Component.translatable("options.gamma"), - 0, 100, 1, - value -> Component.translatable(switch (value) { - case 0 -> "options.gamma.min"; - case 50 -> "options.gamma.default"; - case 100 -> "options.gamma.max"; - default -> String.valueOf(value); - }), - value -> minecraftOptions.gamma().set(value * 0.01), - () -> (int) (minecraftOptions.gamma().get() * 100.0)), + 0, 100, 1, + value -> Component.translatable(switch (value) { + case 0 -> "options.gamma.min"; + case 50 -> "options.gamma.default"; + case 100 -> "options.gamma.max"; + default -> String.valueOf(value); + }), + value -> minecraftOptions.gamma().set(value * 0.01), + () -> (int) (minecraftOptions.gamma().get() * 100.0)), }), new OptionBlock("", new Option[]{ new SwitchOption(Component.translatable("options.viewBobbing"), - (value) -> minecraftOptions.bobView().set(value), - () -> minecraftOptions.bobView().get()), + (value) -> minecraftOptions.bobView().set(value), + () -> minecraftOptions.bobView().get()), new CyclingOption<>(Component.translatable("options.attackIndicator"), - AttackIndicatorStatus.values(), - value -> minecraftOptions.attackIndicator().set(value), - () -> minecraftOptions.attackIndicator().get()) + AttackIndicatorStatus.values(), + value -> minecraftOptions.attackIndicator().set(value), + () -> minecraftOptions.attackIndicator().get()) .setTranslator(value -> Component.translatable(value.getKey())), new SwitchOption(Component.translatable("options.autosaveIndicator"), - value -> minecraftOptions.showAutosaveIndicator().set(value), - () -> minecraftOptions.showAutosaveIndicator().get()), + value -> minecraftOptions.showAutosaveIndicator().set(value), + () -> minecraftOptions.showAutosaveIndicator().get()), }) }; } @@ -148,48 +158,52 @@ public static OptionBlock[] getGraphicsOpts() { return new OptionBlock[]{ new OptionBlock("", new Option[]{ new RangeOption(Component.translatable("options.renderDistance"), - 2, 32, 1, - (value) -> minecraftOptions.renderDistance().set(value), - () -> minecraftOptions.renderDistance().get()), + 2, 32, 1, + (value) -> minecraftOptions.renderDistance().set(value), + () -> minecraftOptions.renderDistance().get()), new RangeOption(Component.translatable("options.simulationDistance"), - 5, 32, 1, - (value) -> minecraftOptions.simulationDistance().set(value), - () -> minecraftOptions.simulationDistance().get()), + 5, 32, 1, + (value) -> minecraftOptions.simulationDistance().set(value), + () -> minecraftOptions.simulationDistance().get()), new CyclingOption<>(Component.translatable("options.prioritizeChunkUpdates"), - PrioritizeChunkUpdates.values(), - value -> minecraftOptions.prioritizeChunkUpdates().set(value), - () -> minecraftOptions.prioritizeChunkUpdates().get()) + PrioritizeChunkUpdates.values(), + value -> minecraftOptions.prioritizeChunkUpdates().set(value), + () -> minecraftOptions.prioritizeChunkUpdates().get()) .setTranslator(value -> Component.translatable(value.getKey())), }), new OptionBlock("", new Option[]{ new CyclingOption<>(Component.translatable("options.graphics"), - new GraphicsStatus[]{GraphicsStatus.FAST, GraphicsStatus.FANCY}, - value -> minecraftOptions.graphicsMode().set(value), - () -> minecraftOptions.graphicsMode().get()) + new GraphicsStatus[]{GraphicsStatus.FAST, GraphicsStatus.FANCY}, + value -> minecraftOptions.graphicsMode().set(value), + () -> minecraftOptions.graphicsMode().get()) .setTranslator(graphicsMode -> Component.translatable(graphicsMode.getKey())), new CyclingOption<>(Component.translatable("options.particles"), - new ParticleStatus[]{ParticleStatus.MINIMAL, ParticleStatus.DECREASED, ParticleStatus.ALL}, - value -> minecraftOptions.particles().set(value), - () -> minecraftOptions.particles().get()) + new ParticleStatus[]{ParticleStatus.MINIMAL, ParticleStatus.DECREASED, ParticleStatus.ALL}, + value -> minecraftOptions.particles().set(value), + () -> minecraftOptions.particles().get()) .setTranslator(particlesMode -> Component.translatable(particlesMode.getKey())), new CyclingOption<>(Component.translatable("options.renderClouds"), - CloudStatus.values(), - value -> minecraftOptions.cloudStatus().set(value), - () -> minecraftOptions.cloudStatus().get()) + CloudStatus.values(), + value -> minecraftOptions.cloudStatus().set(value), + () -> minecraftOptions.cloudStatus().get()) .setTranslator(value -> Component.translatable(value.getKey())), + new RangeOption(Component.translatable("options.renderCloudsDistance"), + 2, 128, 1, + (value) -> minecraftOptions.cloudRange().set(value), + () -> minecraftOptions.cloudRange().get()), new CyclingOption<>(Component.translatable("options.ao"), - new Integer[]{LightMode.FLAT, LightMode.SMOOTH, LightMode.SUB_BLOCK}, - (value) -> { - if (value > LightMode.FLAT) - minecraftOptions.ambientOcclusion().set(true); - else - minecraftOptions.ambientOcclusion().set(false); + new Integer[]{LightMode.FLAT, LightMode.SMOOTH, LightMode.SUB_BLOCK}, + (value) -> { + if (value > LightMode.FLAT) + minecraftOptions.ambientOcclusion().set(true); + else + minecraftOptions.ambientOcclusion().set(false); - config.ambientOcclusion = value; + config.ambientOcclusion = value; - minecraft.levelRenderer.allChanged(); - }, - () -> config.ambientOcclusion) + minecraft.levelRenderer.allChanged(); + }, + () -> config.ambientOcclusion) .setTranslator(value -> Component.translatable(switch (value) { case LightMode.FLAT -> "options.off"; case LightMode.SMOOTH -> "options.on"; @@ -198,33 +212,33 @@ public static OptionBlock[] getGraphicsOpts() { })) .setTooltip(Component.translatable("vulkanmod.options.ao.subBlock.tooltip")), new RangeOption(Component.translatable("options.biomeBlendRadius"), - 0, 7, 1, - value -> { - int v = value * 2 + 1; - return Component.nullToEmpty("%d x %d".formatted(v, v)); - }, - (value) -> { - minecraftOptions.biomeBlendRadius().set(value); - minecraft.levelRenderer.allChanged(); - }, - () -> minecraftOptions.biomeBlendRadius().get()), + 0, 7, 1, + value -> { + int v = value * 2 + 1; + return Component.nullToEmpty("%d x %d".formatted(v, v)); + }, + (value) -> { + minecraftOptions.biomeBlendRadius().set(value); + minecraft.levelRenderer.allChanged(); + }, + () -> minecraftOptions.biomeBlendRadius().get()), }), new OptionBlock("", new Option[]{ new SwitchOption(Component.translatable("options.entityShadows"), - value -> minecraftOptions.entityShadows().set(value), - () -> minecraftOptions.entityShadows().get()), + value -> minecraftOptions.entityShadows().set(value), + () -> minecraftOptions.entityShadows().get()), new RangeOption(Component.translatable("options.entityDistanceScaling"), - 50, 500, 25, - value -> minecraftOptions.entityDistanceScaling().set(value * 0.01), - () -> minecraftOptions.entityDistanceScaling().get().intValue() * 100), + 50, 500, 25, + value -> minecraftOptions.entityDistanceScaling().set(value * 0.01), + () -> minecraftOptions.entityDistanceScaling().get().intValue() * 100), new CyclingOption<>(Component.translatable("options.mipmapLevels"), - new Integer[]{0, 1, 2, 3, 4}, - value -> { - minecraftOptions.mipmapLevels().set(value); - minecraft.updateMaxMipLevel(value); - minecraft.delayTextureReload(); - }, - () -> minecraftOptions.mipmapLevels().get()) + new Integer[]{0, 1, 2, 3, 4}, + value -> { + minecraftOptions.mipmapLevels().set(value); + minecraft.updateMaxMipLevel(value); + minecraft.delayTextureReload(); + }, + () -> minecraftOptions.mipmapLevels().get()) .setTranslator(value -> Component.nullToEmpty(value.toString())) }) }; @@ -234,9 +248,9 @@ public static OptionBlock[] getOptimizationOpts() { return new OptionBlock[]{ new OptionBlock("", new Option[]{ new CyclingOption<>(Component.translatable("vulkanmod.options.advCulling"), - new Integer[]{1, 2, 3, 10}, - value -> config.advCulling = value, - () -> config.advCulling) + new Integer[]{1, 2, 3, 10}, + value -> config.advCulling = value, + () -> config.advCulling) .setTranslator(value -> Component.translatable(switch (value) { case 1 -> "vulkanmod.options.advCulling.aggressive"; case 2 -> "vulkanmod.options.advCulling.normal"; @@ -246,19 +260,27 @@ public static OptionBlock[] getOptimizationOpts() { })) .setTooltip(Component.translatable("vulkanmod.options.advCulling.tooltip")), new SwitchOption(Component.translatable("vulkanmod.options.entityCulling"), - value -> config.entityCulling = value, - () -> config.entityCulling) + value -> config.entityCulling = value, + () -> config.entityCulling) .setTooltip(Component.translatable("vulkanmod.options.entityCulling.tooltip")), new SwitchOption(Component.translatable("vulkanmod.options.uniqueOpaqueLayer"), - value -> { - config.uniqueOpaqueLayer = value; - minecraft.levelRenderer.allChanged(); - }, - () -> config.uniqueOpaqueLayer) + value -> { + config.uniqueOpaqueLayer = value; + TerrainRenderType.updateMapping(); + minecraft.levelRenderer.allChanged(); + }, + () -> config.uniqueOpaqueLayer) .setTooltip(Component.translatable("vulkanmod.options.uniqueOpaqueLayer.tooltip")), + new SwitchOption(Component.translatable("vulkanmod.options.backfaceCulling"), + value -> { + config.backFaceCulling = value; + Minecraft.getInstance().levelRenderer.allChanged(); + }, + () -> config.backFaceCulling) + .setTooltip(Component.translatable("vulkanmod.options.backfaceCulling.tooltip")), new SwitchOption(Component.translatable("vulkanmod.options.indirectDraw"), - value -> config.indirectDraw = value, - () -> config.indirectDraw) + value -> config.indirectDraw = value, + () -> config.indirectDraw) .setTooltip(Component.translatable("vulkanmod.options.indirectDraw.tooltip")), }) }; @@ -268,26 +290,46 @@ public static OptionBlock[] getOptimizationOpts() { public static OptionBlock[] getOtherOpts() { return new OptionBlock[]{ new OptionBlock("", new Option[]{ + new RangeOption(Component.translatable("vulkanmod.options.builderThreads"), + 0, (Runtime.getRuntime().availableProcessors() - 1), 1, + value -> { + config.builderThreads = value; + WorldRenderer.getInstance().getTaskDispatcher().createThreads(value); + }, + () -> config.builderThreads) + .setTranslator(value -> { + if (value == 0) + return Component.translatable("vulkanmod.options.builderThreads.auto"); + else + return Component.nullToEmpty(String.valueOf(value)); + }), new RangeOption(Component.translatable("vulkanmod.options.frameQueue"), - 2, 5, 1, - value -> { - config.frameQueueSize = value; - Renderer.scheduleSwapChainUpdate(); - }, () -> config.frameQueueSize) + 2, 5, 1, + value -> { + config.frameQueueSize = value; + Renderer.scheduleSwapChainUpdate(); + }, () -> config.frameQueueSize) .setTooltip(Component.translatable("vulkanmod.options.frameQueue.tooltip")), + new SwitchOption(Component.translatable("vulkanmod.options.textureAnimations"), + value -> { + config.textureAnimations = value; + }, + () -> config.textureAnimations), + }), + new OptionBlock("", new Option[]{ new CyclingOption<>(Component.translatable("vulkanmod.options.deviceSelector"), - IntStream.range(-1, DeviceManager.suitableDevices.size()).boxed().toArray(Integer[]::new), - value -> config.device = value, - () -> config.device) + IntStream.range(-1, DeviceManager.suitableDevices.size()).boxed() + .toArray(Integer[]::new), + value -> config.device = value, + () -> config.device) .setTranslator(value -> Component.translatable((value == -1) - ? "vulkanmod.options.deviceSelector.auto" - : DeviceManager.suitableDevices.get(value).deviceName) + ? "vulkanmod.options.deviceSelector.auto" + : DeviceManager.suitableDevices.get( + value).deviceName) ) .setTooltip(Component.nullToEmpty("%s: %s".formatted( - Component.translatable("vulkanmod.options.deviceSelector.tooltip").getString(), - DeviceManager.device.deviceName - )) - ) + Component.translatable("vulkanmod.options.deviceSelector.tooltip").getString(), + DeviceManager.device.deviceName))) }) }; diff --git a/src/main/java/net/vulkanmod/config/option/RangeOption.java b/src/main/java/net/vulkanmod/config/option/RangeOption.java index 1a3270cb3..89d5f0355 100644 --- a/src/main/java/net/vulkanmod/config/option/RangeOption.java +++ b/src/main/java/net/vulkanmod/config/option/RangeOption.java @@ -25,8 +25,8 @@ public RangeOption(Component name, int min, int max, int step, Consumer this(name, min, max, step, (i) -> Component.literal(String.valueOf(i)), setter, getter); } - public OptionWidget createOptionWidget(int x, int y, int width, int height) { - return new RangeOptionWidget(this, x, y, width, height, this.name); + public OptionWidget createWidget() { + return new RangeOptionWidget(this, this.name); } public Component getName() { diff --git a/src/main/java/net/vulkanmod/config/option/SwitchOption.java b/src/main/java/net/vulkanmod/config/option/SwitchOption.java index aa4fd84b0..455810d83 100644 --- a/src/main/java/net/vulkanmod/config/option/SwitchOption.java +++ b/src/main/java/net/vulkanmod/config/option/SwitchOption.java @@ -13,8 +13,8 @@ public SwitchOption(Component name, Consumer setter, Supplier } @Override - public OptionWidget createOptionWidget(int x, int y, int width, int height) { - return new SwitchOptionWidget(this, x, y, width, height, this.name); + public OptionWidget createWidget() { + return new SwitchOptionWidget(this, this.name); } } diff --git a/src/main/java/net/vulkanmod/config/video/WindowMode.java b/src/main/java/net/vulkanmod/config/video/WindowMode.java new file mode 100644 index 000000000..621f06dea --- /dev/null +++ b/src/main/java/net/vulkanmod/config/video/WindowMode.java @@ -0,0 +1,31 @@ +package net.vulkanmod.config.video; + +public enum WindowMode { + WINDOWED(0), + WINDOWED_FULLSCREEN(1), + EXCLUSIVE_FULLSCREEN(2); + + public final int mode; + + WindowMode(int mode) { + this.mode = mode; + } + + public static WindowMode fromValue(int value) { + return switch (value) { + case 0 -> WINDOWED; + case 1 -> WINDOWED_FULLSCREEN; + case 2 -> EXCLUSIVE_FULLSCREEN; + + default -> throw new IllegalStateException("Unexpected value: " + value); + }; + } + + public static String getComponentName(WindowMode windowMode) { + return switch (windowMode) { + case WINDOWED -> "vulkanmod.options.windowMode.windowed"; + case WINDOWED_FULLSCREEN -> "vulkanmod.options.windowMode.windowedFullscreen"; + case EXCLUSIVE_FULLSCREEN -> "options.fullscreen"; + }; + } +} diff --git a/src/main/java/net/vulkanmod/gl/GlFramebuffer.java b/src/main/java/net/vulkanmod/gl/GlFramebuffer.java deleted file mode 100644 index 0201441ec..000000000 --- a/src/main/java/net/vulkanmod/gl/GlFramebuffer.java +++ /dev/null @@ -1,247 +0,0 @@ -package net.vulkanmod.gl; - -import com.mojang.blaze3d.pipeline.RenderTarget; -import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; -import net.minecraft.client.Minecraft; -import net.vulkanmod.vulkan.Renderer; -import net.vulkanmod.vulkan.VRenderSystem; -import net.vulkanmod.vulkan.framebuffer.Framebuffer; -import net.vulkanmod.vulkan.framebuffer.RenderPass; -import net.vulkanmod.vulkan.texture.VulkanImage; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL30; - -import static org.lwjgl.vulkan.VK11.VK_ATTACHMENT_LOAD_OP_LOAD; -import static org.lwjgl.vulkan.VK11.VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - -public class GlFramebuffer { - private static int ID_COUNTER = 1; - private static final Int2ReferenceOpenHashMap map = new Int2ReferenceOpenHashMap<>(); - private static int boundId = 0; - private static GlFramebuffer boundFramebuffer; - - public static void resetBoundFramebuffer() { - boundFramebuffer = null; - boundId = 0; - } - - public static void beginRendering(GlFramebuffer glFramebuffer) { - Renderer.getInstance().beginRendering(glFramebuffer.renderPass, glFramebuffer.framebuffer); - - Framebuffer framebuffer = glFramebuffer.framebuffer; - int viewWidth = framebuffer.getWidth(); - int viewHeight = framebuffer.getHeight(); - - Renderer.setInvertedViewport(0, 0, viewWidth, viewHeight); - Renderer.setScissor(0, 0, viewWidth, viewHeight); - - // TODO: invert cull instead of disabling - VRenderSystem.disableCull(); - - boundId = glFramebuffer.id; - } - - public static int genFramebufferId() { - int id = ID_COUNTER; - map.put(id, new GlFramebuffer(id)); - ID_COUNTER++; - return id; - } - - public static void bindFramebuffer(int target, int id) { - // target - // 36160 GL_FRAMEBUFFER - // 36161 GL_RENDERBUFFER - - if (boundId == id) - return; - - if (id == 0) { - Renderer.getInstance().endRenderPass(); - - if (Renderer.isRecording()) { - RenderTarget renderTarget = Minecraft.getInstance().getMainRenderTarget(); - renderTarget.bindWrite(true); - } - - boundFramebuffer = null; - boundId = 0; - return; - } - - GlFramebuffer glFramebuffer = map.get(id); - - if (glFramebuffer == null) - throw new NullPointerException("No Framebuffer with ID: %d ".formatted(id)); - - if (glFramebuffer.framebuffer != null) { - beginRendering(glFramebuffer); - } - - boundFramebuffer = glFramebuffer; - } - - public static void deleteFramebuffer(int id) { - if (id == 0) { - return; - } - - boundFramebuffer = map.remove(id); - - if (boundFramebuffer == null) - throw new NullPointerException("bound framebuffer is null"); - - boundFramebuffer.cleanUp(); - boundFramebuffer = null; - } - - public static void framebufferTexture2D(int target, int attachment, int texTarget, int texture, int level) { - if (attachment != GL30.GL_COLOR_ATTACHMENT0 && attachment != GL30.GL_DEPTH_ATTACHMENT) { - throw new UnsupportedOperationException(); - } - if (texTarget != GL11.GL_TEXTURE_2D) { - throw new UnsupportedOperationException(); - } - if (level != 0) { - throw new UnsupportedOperationException(); - } - - boundFramebuffer.setAttachmentTexture(attachment, texture); - } - - public static void framebufferRenderbuffer(int target, int attachment, int renderbuffertarget, int renderbuffer) { - if (boundFramebuffer == null) - return; - - boundFramebuffer.setAttachmentRenderbuffer(attachment, renderbuffer); - } - - public static int glCheckFramebufferStatus(int target) { - //TODO - return GL30.GL_FRAMEBUFFER_COMPLETE; - } - - public static GlFramebuffer getBoundFramebuffer() { - return boundFramebuffer; - } - - public static GlFramebuffer getFramebuffer(int id) { - return map.get(id); - } - - private final int id; - Framebuffer framebuffer; - RenderPass renderPass; - - VulkanImage colorAttachment; - VulkanImage depthAttachment; - - GlFramebuffer(int i) { - this.id = i; - } - - boolean beginRendering() { - return Renderer.getInstance().beginRendering(this.renderPass, this.framebuffer); - } - - void setAttachmentTexture(int attachment, int texture) { - GlTexture glTexture = GlTexture.getTexture(texture); - - if (glTexture == null) - throw new NullPointerException(String.format("Texture %d is null", texture)); - - if (glTexture.vulkanImage == null) - return; - - switch (attachment) { - case (GL30.GL_COLOR_ATTACHMENT0) -> this.setColorAttachment(glTexture); - - case (GL30.GL_DEPTH_ATTACHMENT) -> this.setDepthAttachment(glTexture); - - default -> throw new IllegalStateException("Unexpected value: " + attachment); - } - } - - void setAttachmentRenderbuffer(int attachment, int texture) { - GlRenderbuffer renderbuffer = GlRenderbuffer.getRenderbuffer(texture); - - if (renderbuffer == null) - throw new NullPointerException(String.format("Texture %d is null", texture)); - - if (renderbuffer.vulkanImage == null) - return; - - switch (attachment) { - case (GL30.GL_COLOR_ATTACHMENT0) -> this.setColorAttachment(renderbuffer); - - case (GL30.GL_DEPTH_ATTACHMENT) -> this.setDepthAttachment(renderbuffer); - - default -> throw new IllegalStateException("Unexpected value: " + attachment); - } - } - - void setColorAttachment(GlTexture texture) { - this.colorAttachment = texture.vulkanImage; - createAndBind(); - } - - void setDepthAttachment(GlTexture texture) { - //TODO check if texture is in depth format - this.depthAttachment = texture.vulkanImage; - createAndBind(); - } - - void setColorAttachment(GlRenderbuffer texture) { - this.colorAttachment = texture.vulkanImage; - createAndBind(); - } - - void setDepthAttachment(GlRenderbuffer texture) { - //TODO check if texture is in depth format - this.depthAttachment = texture.vulkanImage; - createAndBind(); - } - - void createAndBind() { - // Cannot create without color attachment - if (this.colorAttachment == null) - return; - - if (this.framebuffer != null) { - this.cleanUp(); - } - - boolean hasDepthImage = this.depthAttachment != null; - VulkanImage depthImage = this.depthAttachment; - - this.framebuffer = Framebuffer.builder(this.colorAttachment, depthImage).build(); - RenderPass.Builder builder = RenderPass.builder(this.framebuffer); - - builder.getColorAttachmentInfo() - .setLoadOp(VK_ATTACHMENT_LOAD_OP_LOAD) - .setFinalLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - if (hasDepthImage) - builder.getDepthAttachmentInfo().setOps(VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_LOAD); - - this.renderPass = builder.build(); - - GlFramebuffer.beginRendering(this); - } - - public Framebuffer getFramebuffer() { - return framebuffer; - } - - public RenderPass getRenderPass() { - return renderPass; - } - - void cleanUp() { - this.framebuffer.cleanUp(false); - this.renderPass.cleanUp(); - - this.framebuffer = null; - this.renderPass = null; - } -} diff --git a/src/main/java/net/vulkanmod/gl/GlUtil.java b/src/main/java/net/vulkanmod/gl/GlUtil.java index 5cd12df11..fe8edea75 100644 --- a/src/main/java/net/vulkanmod/gl/GlUtil.java +++ b/src/main/java/net/vulkanmod/gl/GlUtil.java @@ -88,11 +88,8 @@ public static int vulkanFormat(int glFormat, int type) { case GL11.GL_UNSIGNED_BYTE -> VK_FORMAT_R8_UNORM; default -> throw new IllegalStateException("Unexpected type: " + type); }; - case GL11.GL_DEPTH_COMPONENT, GL30.GL_DEPTH_COMPONENT32F, GL30.GL_DEPTH_COMPONENT24 -> -// switch (type) { -// case GL11.GL_FLOAT -> VK_FORMAT_D32_SFLOAT; -// default -> throw new IllegalStateException("Unexpected value: " + type); -// }; + case GL11.GL_DEPTH_COMPONENT, GL30.GL_DEPTH_COMPONENT32, + GL30.GL_DEPTH_COMPONENT32F, GL30.GL_DEPTH_COMPONENT24 -> Vulkan.getDefaultDepthFormat(); default -> throw new IllegalStateException("Unexpected format: " + glFormat); @@ -104,10 +101,6 @@ public static int vulkanFormat(int glInternalFormat) { return switch (glInternalFormat) { case GL30.GL_UNSIGNED_INT_8_8_8_8_REV -> VK_FORMAT_R8G8B8A8_UINT; case GL11.GL_DEPTH_COMPONENT, GL30.GL_DEPTH_COMPONENT32F, GL30.GL_DEPTH_COMPONENT24 -> -// switch (type) { -// case GL11.GL_FLOAT -> VK_FORMAT_D32_SFLOAT; -// default -> throw new IllegalStateException("Unexpected value: " + type); -// }; Vulkan.getDefaultDepthFormat(); default -> throw new IllegalStateException("Unexpected value: " + glInternalFormat); diff --git a/src/main/java/net/vulkanmod/gl/GlBuffer.java b/src/main/java/net/vulkanmod/gl/VkGlBuffer.java similarity index 78% rename from src/main/java/net/vulkanmod/gl/GlBuffer.java rename to src/main/java/net/vulkanmod/gl/VkGlBuffer.java index 09091728e..1a2d6b4d5 100644 --- a/src/main/java/net/vulkanmod/gl/GlBuffer.java +++ b/src/main/java/net/vulkanmod/gl/VkGlBuffer.java @@ -7,27 +7,28 @@ import java.nio.ByteBuffer; import java.nio.IntBuffer; -// TODO: This class is only used to emulate a CPU buffer for texture copying purposes -// any other use is not supported -public class GlBuffer { +// TODO: Implement missing features. +// This class is only used to emulate a CPU buffer for texture copying purposes +public class VkGlBuffer { private static int ID_COUNTER = 1; - private static final Int2ReferenceOpenHashMap map = new Int2ReferenceOpenHashMap<>(); + private static final Int2ReferenceOpenHashMap map = new Int2ReferenceOpenHashMap<>(); private static int boundId = 0; - private static GlBuffer boundBuffer; + private static VkGlBuffer boundBuffer; - private static GlBuffer pixelPackBufferBound; - private static GlBuffer pixelUnpackBufferBound; + private static VkGlBuffer arrayBufferBound; + private static VkGlBuffer pixelPackBufferBound; + private static VkGlBuffer pixelUnpackBufferBound; public static int glGenBuffers() { int id = ID_COUNTER; - map.put(id, new GlBuffer(id)); + map.put(id, new VkGlBuffer(id)); ID_COUNTER++; return id; } public static void glBindBuffer(int target, int buffer) { boundId = buffer; - GlBuffer glBuffer = map.get(buffer); + VkGlBuffer glBuffer = map.get(buffer); if (buffer > 0 && glBuffer == null) throw new NullPointerException("bound texture is null"); @@ -39,6 +40,7 @@ public static void glBindBuffer(int target, int buffer) { switch (target) { case GL32.GL_PIXEL_PACK_BUFFER -> pixelPackBufferBound = glBuffer; case GL32.GL_PIXEL_UNPACK_BUFFER -> pixelUnpackBufferBound = glBuffer; + case GL32.GL_ARRAY_BUFFER -> arrayBufferBound = glBuffer; default -> throw new IllegalStateException("Unexpected value: " + target); } } @@ -52,7 +54,7 @@ public static void glBufferData(int target, ByteBuffer byteBuffer, int usage) { } public static void glBufferData(int target, long size, int usage) { - GlBuffer buffer = switch (target) { + VkGlBuffer buffer = switch (target) { case GL32.GL_PIXEL_PACK_BUFFER -> pixelPackBufferBound; case GL32.GL_PIXEL_UNPACK_BUFFER -> pixelUnpackBufferBound; default -> throw new IllegalStateException("Unexpected value: " + target); @@ -62,7 +64,7 @@ public static void glBufferData(int target, long size, int usage) { } public static ByteBuffer glMapBuffer(int target, int access) { - GlBuffer buffer = switch (target) { + VkGlBuffer buffer = switch (target) { case GL32.GL_PIXEL_PACK_BUFFER -> pixelPackBufferBound; case GL32.GL_PIXEL_UNPACK_BUFFER -> pixelUnpackBufferBound; default -> throw new IllegalStateException("Unexpected value: " + target); @@ -90,11 +92,11 @@ public static void glDeleteBuffers(int id) { buffer.freeData(); } - public static GlBuffer getPixelUnpackBufferBound() { + public static VkGlBuffer getPixelUnpackBufferBound() { return pixelUnpackBufferBound; } - public static GlBuffer getPixelPackBufferBound() { + public static VkGlBuffer getPixelPackBufferBound() { return pixelPackBufferBound; } @@ -108,7 +110,7 @@ private static void checkTarget(int target) { ByteBuffer data; - public GlBuffer(int id) { + public VkGlBuffer(int id) { this.id = id; } diff --git a/src/main/java/net/vulkanmod/gl/VkGlFramebuffer.java b/src/main/java/net/vulkanmod/gl/VkGlFramebuffer.java new file mode 100644 index 000000000..7048f38cd --- /dev/null +++ b/src/main/java/net/vulkanmod/gl/VkGlFramebuffer.java @@ -0,0 +1,250 @@ +package net.vulkanmod.gl; + +import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; +import net.vulkanmod.vulkan.Renderer; +import net.vulkanmod.vulkan.VRenderSystem; +import net.vulkanmod.vulkan.framebuffer.Framebuffer; +import net.vulkanmod.vulkan.framebuffer.RenderPass; +import net.vulkanmod.vulkan.texture.ImageUtil; +import net.vulkanmod.vulkan.texture.VulkanImage; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL30; + +import static org.lwjgl.vulkan.VK11.VK_ATTACHMENT_LOAD_OP_LOAD; +import static org.lwjgl.vulkan.VK11.VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + +public class VkGlFramebuffer { + private static int idCounter = 1; + + private static final Int2ReferenceOpenHashMap map = new Int2ReferenceOpenHashMap<>(); + private static VkGlFramebuffer boundFramebuffer; + private static VkGlFramebuffer readFramebuffer; + + public static void resetBoundFramebuffer() { + boundFramebuffer = null; + } + + public static void beginRendering(VkGlFramebuffer glFramebuffer) { + boolean begunRendering = glFramebuffer.beginRendering(); + + if (begunRendering) { + Framebuffer framebuffer = glFramebuffer.framebuffer; + int viewWidth = framebuffer.getWidth(); + int viewHeight = framebuffer.getHeight(); + + Renderer.setInvertedViewport(0, 0, viewWidth, viewHeight); + Renderer.setScissor(0, 0, viewWidth, viewHeight); + + // TODO: invert cull instead of disabling + VRenderSystem.disableCull(); + } + + boundFramebuffer = glFramebuffer; + } + + public static int genFramebufferId() { + int id = idCounter; + map.put(id, new VkGlFramebuffer(id)); + idCounter++; + return id; + } + + public static void bindFramebuffer(int target, int id) { + if (id == 0) { + Renderer.getInstance().endRenderPass(); + + if (Renderer.isRecording()) { + Renderer.getInstance().getMainPass().rebindMainTarget(); + } + + boundFramebuffer = null; + return; + } + + VkGlFramebuffer glFramebuffer = map.get(id); + + if (glFramebuffer == null) + throw new NullPointerException("No Framebuffer with ID: %d ".formatted(id)); + + if (glFramebuffer.needsUpdate) { + glFramebuffer.create(); + } + + switch (target) { + case GL30.GL_DRAW_FRAMEBUFFER, GL30.GL_FRAMEBUFFER -> { + if (glFramebuffer.framebuffer != null) { + beginRendering(glFramebuffer); + } + + boundFramebuffer = glFramebuffer; + } + case GL30.GL_READ_FRAMEBUFFER -> { + readFramebuffer = glFramebuffer; + } + } + + } + + public static void deleteFramebuffer(int id) { + if (id == 0) { + return; + } + + boundFramebuffer = map.remove(id); + + if (boundFramebuffer == null) + throw new NullPointerException("bound framebuffer is null"); + + boundFramebuffer.cleanUp(true); + boundFramebuffer = null; + } + + public static void framebufferTexture2D(int target, int attachment, int texTarget, int texture, int level) { + if (attachment != GL30.GL_COLOR_ATTACHMENT0 && attachment != GL30.GL_DEPTH_ATTACHMENT) { + throw new UnsupportedOperationException(); + } + if (texTarget != GL11.GL_TEXTURE_2D) { + throw new UnsupportedOperationException(); + } + if (level != 0) { + throw new UnsupportedOperationException(); + } + + boundFramebuffer.setAttachmentTexture(attachment, texture); + boundFramebuffer.create(); + VkGlFramebuffer.beginRendering(boundFramebuffer); + } + + public static void framebufferRenderbuffer(int target, int attachment, int renderbuffertarget, int renderbuffer) { + if (boundFramebuffer == null) + return; + + boundFramebuffer.setAttachmentRenderbuffer(attachment, renderbuffer); + boundFramebuffer.create(); + VkGlFramebuffer.beginRendering(boundFramebuffer); + } + + public static void glBlitFramebuffer(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, + int dstY1, int mask, int filter) { + // TODO: add missing parameters + ImageUtil.blitFramebuffer(boundFramebuffer.colorAttachment, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1); + } + + public static int glCheckFramebufferStatus(int target) { + //TODO + return GL30.GL_FRAMEBUFFER_COMPLETE; + } + + public static VkGlFramebuffer getBoundFramebuffer() { + return boundFramebuffer; + } + + public static VkGlFramebuffer getFramebuffer(int id) { + return map.get(id); + } + + public final int id; + Framebuffer framebuffer; + RenderPass renderPass; + + VulkanImage colorAttachment; + VulkanImage depthAttachment; + + boolean needsUpdate; + + VkGlFramebuffer(int i) { + this.id = i; + } + + boolean beginRendering() { + return Renderer.getInstance().beginRenderPass(this.renderPass, this.framebuffer); + } + + public void setAttachmentTexture(int attachment, int id) { + VkGlTexture vkGlTexture = VkGlTexture.getTexture(id); + + if (vkGlTexture == null) + throw new NullPointerException(String.format("Texture %d is null", id)); + + setAttachmentImage(attachment, vkGlTexture.getVulkanImage()); + } + + public void setAttachmentRenderbuffer(int attachment, int id) { + VkGlRenderbuffer renderbuffer = VkGlRenderbuffer.getRenderbuffer(id); + + if (renderbuffer == null) + throw new NullPointerException(String.format("Texture %d is null", id)); + + setAttachmentImage(attachment, renderbuffer.getVulkanImage()); + } + + public void setAttachmentImage(int attachment, VulkanImage image) { + if (image == null) + throw new NullPointerException("Image is null"); + + switch (attachment) { + case (GL30.GL_COLOR_ATTACHMENT0) -> this.setColorAttachment(image); + case (GL30.GL_DEPTH_ATTACHMENT) -> this.setDepthAttachment(image); + + default -> throw new IllegalStateException("Unexpected value: " + attachment); + } + + this.needsUpdate = true; + } + + void setColorAttachment(VulkanImage image) { + this.colorAttachment = image; + } + + void setDepthAttachment(VulkanImage image) { + //TODO check if texture is in depth format + this.depthAttachment = image; + } + + public void create() { + // Cannot create without color attachment + if (this.colorAttachment == null) + return; + + if (this.framebuffer != null) { + this.cleanUp(false); + } + + boolean hasDepthImage = this.depthAttachment != null; + VulkanImage depthImage = this.depthAttachment; + + this.framebuffer = Framebuffer.builder(this.colorAttachment, depthImage) + .build(); + RenderPass.Builder builder = RenderPass.builder(this.framebuffer); + + builder.getColorAttachmentInfo() + .setLoadOp(VK_ATTACHMENT_LOAD_OP_LOAD) + .setFinalLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + if (hasDepthImage) { + builder.getDepthAttachmentInfo() + .setOps(VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_LOAD); + } + + this.renderPass = builder.build(); + this.needsUpdate = false; + } + + public Framebuffer getFramebuffer() { + return framebuffer; + } + + public RenderPass getRenderPass() { + return renderPass; + } + + void cleanUp(boolean freeAttachments) { + if (framebuffer != null) { + this.framebuffer.cleanUp(freeAttachments); + this.renderPass.cleanUp(); + } + + this.framebuffer = null; + this.renderPass = null; + } +} diff --git a/src/main/java/net/vulkanmod/gl/VkGlProgram.java b/src/main/java/net/vulkanmod/gl/VkGlProgram.java new file mode 100644 index 000000000..2cce606f2 --- /dev/null +++ b/src/main/java/net/vulkanmod/gl/VkGlProgram.java @@ -0,0 +1,55 @@ +package net.vulkanmod.gl; + +import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; +import net.vulkanmod.vulkan.shader.Pipeline; + +public class VkGlProgram { + private static int ID_COUNTER = 1; + private static final Int2ReferenceOpenHashMap map = new Int2ReferenceOpenHashMap<>(); + private static int boundProgramId = 0; + private static VkGlProgram boundProgram; + + public static VkGlProgram getBoundProgram() { + return boundProgram; + } + + public static VkGlProgram getProgram(int id) { + return map.get(id); + } + + public static int genProgramId() { + int id = ID_COUNTER; + map.put(id, new VkGlProgram(id)); + ID_COUNTER++; + return id; + } + + public static void glUseProgram(int id) { + boundProgramId = id; + boundProgram = map.get(id); + + if (id <= 0) { + return; + } + + if (boundProgram == null) { + throw new NullPointerException("bound texture is null"); + } + + } + + int id; + Pipeline pipeline; + + VkGlProgram(int i) { + this.id = i; + } + + public void bindPipeline(Pipeline pipeline) { + this.pipeline = pipeline; + } + + public Pipeline getPipeline() { + return this.pipeline; + } +} diff --git a/src/main/java/net/vulkanmod/gl/GlRenderbuffer.java b/src/main/java/net/vulkanmod/gl/VkGlRenderbuffer.java similarity index 78% rename from src/main/java/net/vulkanmod/gl/GlRenderbuffer.java rename to src/main/java/net/vulkanmod/gl/VkGlRenderbuffer.java index 47c3376ea..63b7a62ed 100644 --- a/src/main/java/net/vulkanmod/gl/GlRenderbuffer.java +++ b/src/main/java/net/vulkanmod/gl/VkGlRenderbuffer.java @@ -13,15 +13,15 @@ import static org.lwjgl.vulkan.VK10.*; -public class GlRenderbuffer { +public class VkGlRenderbuffer { private static int ID_COUNTER = 1; - private static final Int2ReferenceOpenHashMap map = new Int2ReferenceOpenHashMap<>(); + private static final Int2ReferenceOpenHashMap map = new Int2ReferenceOpenHashMap<>(); private static int boundId = 0; - private static GlRenderbuffer bound; + private static VkGlRenderbuffer bound; public static int genId() { int id = ID_COUNTER; - map.put(id, new GlRenderbuffer(id)); + map.put(id, new VkGlRenderbuffer(id)); ID_COUNTER++; return id; } @@ -45,7 +45,7 @@ public static void deleteRenderbuffer(int i) { map.remove(i); } - public static GlRenderbuffer getRenderbuffer(int id) { + public static VkGlRenderbuffer getRenderbuffer(int id) { return map.get(id); } @@ -99,12 +99,12 @@ public static void generateMipmap(int target) { } public static void setVulkanImage(int id, VulkanImage vulkanImage) { - GlRenderbuffer texture = map.get(id); + VkGlRenderbuffer texture = map.get(id); texture.vulkanImage = vulkanImage; } - public static GlRenderbuffer getBound() { + public static VkGlRenderbuffer getBound() { return bound; } @@ -117,7 +117,7 @@ public static GlRenderbuffer getBound() { int maxLod = 0; int minFilter, magFilter = GL11.GL_LINEAR; - public GlRenderbuffer(int id) { + public VkGlRenderbuffer(int id) { this.id = id; } @@ -159,16 +159,34 @@ void updateSampler() { if (vulkanImage == null) return; - byte samplerFlags = magFilter == GL11.GL_LINEAR ? SamplerManager.LINEAR_FILTERING_BIT : 0; + int addressMode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + int vkMagFilter, vkMinFilter, mipmapMode; - samplerFlags |= switch (minFilter) { - case GL11.GL_LINEAR_MIPMAP_LINEAR -> - SamplerManager.USE_MIPMAPS_BIT | SamplerManager.MIPMAP_LINEAR_FILTERING_BIT; - case GL11.GL_NEAREST_MIPMAP_NEAREST -> SamplerManager.USE_MIPMAPS_BIT; - default -> 0; + switch (minFilter) { + case GL11.GL_LINEAR_MIPMAP_LINEAR, GL11.GL_LINEAR -> { + vkMinFilter = VK_FILTER_LINEAR; mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + } + case GL11.GL_LINEAR_MIPMAP_NEAREST -> { + vkMinFilter = VK_FILTER_LINEAR; mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + } + case GL11.GL_NEAREST_MIPMAP_NEAREST, GL11.GL_NEAREST -> { + vkMinFilter = VK_FILTER_NEAREST; mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + } + case GL11.GL_NEAREST_MIPMAP_LINEAR -> { + vkMinFilter = VK_FILTER_NEAREST; mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + } + default -> throw new IllegalStateException("Unexpected min filter value: %d".formatted(minFilter)); + } + + vkMagFilter = switch (magFilter) { + case GL11.GL_LINEAR -> VK_FILTER_LINEAR; + case GL11.GL_NEAREST -> VK_FILTER_NEAREST; + default -> throw new IllegalStateException("Unexpected mag filter value: %d".formatted(magFilter)); }; - vulkanImage.updateTextureSampler(maxLod, samplerFlags); + long sampler = SamplerManager.getSampler(addressMode, addressMode, vkMinFilter, vkMagFilter, mipmapMode, maxLod, false, 0, -1); + + vulkanImage.setSampler(sampler); } private void uploadImage(ByteBuffer pixels) { diff --git a/src/main/java/net/vulkanmod/gl/VkGlShader.java b/src/main/java/net/vulkanmod/gl/VkGlShader.java new file mode 100644 index 000000000..95b70bff0 --- /dev/null +++ b/src/main/java/net/vulkanmod/gl/VkGlShader.java @@ -0,0 +1,45 @@ +package net.vulkanmod.gl; + +import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; + +public class VkGlShader { + private static int ID_COUNTER = 1; + private static final Int2ReferenceOpenHashMap map = new Int2ReferenceOpenHashMap<>(); + private static int boundTextureId = 0; + + public static int glCreateShader(int type) { + int id = ID_COUNTER++; + VkGlShader shader = new VkGlShader(id, type); + + map.put(id, shader); + return id; + } + + public static void glDeleteShader(int i) { + map.remove(i); + } + + public static void glShaderSource(int i, String string) { + VkGlShader shader = map.get(i); + shader.source = string; + } + + public static void glCompileShader(int i) { + + } + + public static int glGetShaderi(int i, int j) { + return 0; + } + + final int id; + final int type; + + String source; + + VkGlShader(int id, int type) { + this.id = id; + this.type = type; + } + +} diff --git a/src/main/java/net/vulkanmod/gl/GlTexture.java b/src/main/java/net/vulkanmod/gl/VkGlTexture.java similarity index 62% rename from src/main/java/net/vulkanmod/gl/GlTexture.java rename to src/main/java/net/vulkanmod/gl/VkGlTexture.java index 4658fbc70..d1a3ecec0 100644 --- a/src/main/java/net/vulkanmod/gl/GlTexture.java +++ b/src/main/java/net/vulkanmod/gl/VkGlTexture.java @@ -1,6 +1,7 @@ package net.vulkanmod.gl; import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; +import net.vulkanmod.Initializer; import net.vulkanmod.vulkan.memory.MemoryManager; import net.vulkanmod.vulkan.texture.ImageUtil; import net.vulkanmod.vulkan.texture.SamplerManager; @@ -16,21 +17,25 @@ import static org.lwjgl.vulkan.VK10.*; -public class GlTexture { +public class VkGlTexture { private static int ID_COUNTER = 1; - private static final Int2ReferenceOpenHashMap map = new Int2ReferenceOpenHashMap<>(); + private static final Int2ReferenceOpenHashMap map = new Int2ReferenceOpenHashMap<>(); private static int boundTextureId = 0; - private static GlTexture boundTexture; + private static VkGlTexture boundTexture; private static int activeTexture = 0; + private static int unpackRowLength; + private static int unpackSkipRows; + private static int unpackSkipPixels; + public static void bindIdToImage(int id, VulkanImage vulkanImage) { - GlTexture texture = map.get(id); + VkGlTexture texture = map.get(id); texture.vulkanImage = vulkanImage; } public static int genTextureId() { int id = ID_COUNTER; - map.put(id, new GlTexture(id)); + map.put(id, new VkGlTexture(id)); ID_COUNTER++; return id; } @@ -39,11 +44,14 @@ public static void bindTexture(int id) { boundTextureId = id; boundTexture = map.get(id); - if (id <= 0) + if (id <= 0) { return; + } - if (boundTexture == null) - throw new NullPointerException("bound texture is null"); + if (boundTexture == null) { + Initializer.LOGGER.error("Invalid id({}) value", id); + return; + } VulkanImage vulkanImage = boundTexture.vulkanImage; if (vulkanImage != null) @@ -57,13 +65,13 @@ public static void glDeleteTextures(IntBuffer intBuffer) { } public static void glDeleteTextures(int i) { - GlTexture glTexture = map.remove(i); + VkGlTexture glTexture = map.remove(i); VulkanImage image = glTexture != null ? glTexture.vulkanImage : null; if (image != null) MemoryManager.getInstance().addToFreeable(image); } - public static GlTexture getTexture(int id) { + public static VkGlTexture getTexture(int id) { if (id == 0) return null; @@ -79,7 +87,9 @@ public static void texImage2D(int target, int level, int internalFormat, int wid if (checkParams(level, width, height)) return; - boundTexture.allocateIfNeeded(width, height, internalFormat, type); + boundTexture.updateParams(level, width, height, internalFormat, type); + boundTexture.allocateIfNeeded(); + VTextureSelector.bindTexture(activeTexture, boundTexture.vulkanImage); texSubImage2D(target, level, 0, 0, width, height, format, type, pixels); @@ -89,7 +99,9 @@ public static void texImage2D(int target, int level, int internalFormat, int wid if (checkParams(level, width, height)) return; - boundTexture.allocateIfNeeded(width, height, internalFormat, type); + boundTexture.updateParams(level, width, height, internalFormat, type); + boundTexture.allocateIfNeeded(); + VTextureSelector.bindTexture(activeTexture, boundTexture.vulkanImage); texSubImage2D(target, level, 0, 0, width, height, format, type, pixels); @@ -99,11 +111,6 @@ private static boolean checkParams(int level, int width, int height) { if (width == 0 || height == 0) return true; - // TODO: levels - if (level != 0) { -// throw new UnsupportedOperationException(); - return true; - } return false; } @@ -113,7 +120,7 @@ public static void texSubImage2D(int target, int level, int xOffset, int yOffset ByteBuffer src; - GlBuffer glBuffer = GlBuffer.getPixelUnpackBufferBound(); + VkGlBuffer glBuffer = VkGlBuffer.getPixelUnpackBufferBound(); if (glBuffer != null) { glBuffer.data.position((int) pixels); @@ -127,14 +134,16 @@ public static void texSubImage2D(int target, int level, int xOffset, int yOffset } if (src != null) - boundTexture.uploadSubImage(xOffset, yOffset, width, height, format, src); + boundTexture.uploadSubImage(level, xOffset, yOffset, width, height, format, src); } private static ByteBuffer getByteBuffer(int width, int height, long pixels) { ByteBuffer src; // TODO: hardcoded format size int formatSize = 4; - src = MemoryUtil.memByteBuffer(pixels, width * height * formatSize); + int rowLength = unpackRowLength != 0 ? unpackRowLength : width; + int offset = (unpackSkipRows * rowLength + unpackSkipPixels) * formatSize; + src = MemoryUtil.memByteBuffer(pixels + offset, (rowLength * height - unpackSkipPixels) * formatSize); return src; } @@ -144,7 +153,7 @@ public static void texSubImage2D(int target, int level, int xOffset, int yOffset ByteBuffer src; - GlBuffer glBuffer = GlBuffer.getPixelUnpackBufferBound(); + VkGlBuffer glBuffer = VkGlBuffer.getPixelUnpackBufferBound(); if (glBuffer != null) { if (pixels != null) { throw new IllegalStateException("Trying to use pixel buffer when there is a Pixel Unpack Buffer bound."); @@ -157,13 +166,16 @@ public static void texSubImage2D(int target, int level, int xOffset, int yOffset } if (src != null) - boundTexture.uploadSubImage(xOffset, yOffset, width, height, format, src); + boundTexture.uploadSubImage(level, xOffset, yOffset, width, height, format, src); } public static void texParameteri(int target, int pName, int param) { if (target != GL11.GL_TEXTURE_2D) throw new UnsupportedOperationException("target != GL_TEXTURE_2D not supported"); + if (boundTexture == null) + return; + switch (pName) { case GL30.GL_TEXTURE_MAX_LEVEL -> boundTexture.setMaxLevel(param); case GL30.GL_TEXTURE_MAX_LOD -> boundTexture.setMaxLod(param); @@ -181,6 +193,28 @@ public static void texParameteri(int target, int pName, int param) { //TODO } + public static int getTexParameteri(int target, int pName) { + if (target != GL11.GL_TEXTURE_2D) + throw new UnsupportedOperationException("target != GL_TEXTURE_2D not supported"); + + if (boundTexture == null) + return -1; + + return switch (pName) { + case GL11.GL_TEXTURE_INTERNAL_FORMAT -> GlUtil.getGlFormat(boundTexture.vulkanImage.format); + case GL11.GL_TEXTURE_WIDTH -> boundTexture.vulkanImage.width; + case GL11.GL_TEXTURE_HEIGHT -> boundTexture.vulkanImage.height; + + case GL30.GL_TEXTURE_MAX_LEVEL -> boundTexture.maxLevel; + case GL30.GL_TEXTURE_MAX_LOD -> boundTexture.maxLod; + + case GL11.GL_TEXTURE_MAG_FILTER -> boundTexture.magFilter; + case GL11.GL_TEXTURE_MIN_FILTER -> boundTexture.minFilter; + + default -> -1; + }; + } + public static int getTexLevelParameter(int target, int level, int pName) { if (target != GL11.GL_TEXTURE_2D) throw new UnsupportedOperationException("target != GL_TEXTURE_2D not supported"); @@ -197,6 +231,14 @@ public static int getTexLevelParameter(int target, int level, int pName) { }; } + public static void pixelStoreI(int pName, int value) { + switch (pName) { + case GL11.GL_UNPACK_ROW_LENGTH -> unpackRowLength = value; + case GL11.GL_UNPACK_SKIP_ROWS -> unpackSkipRows = value; + case GL11.GL_UNPACK_SKIP_PIXELS -> unpackSkipPixels = value; + } + } + public static void generateMipmap(int target) { if (target != GL11.GL_TEXTURE_2D) throw new UnsupportedOperationException("target != GL_TEXTURE_2D not supported"); @@ -208,7 +250,7 @@ public static void generateMipmap(int target) { public static void getTexImage(int tex, int level, int format, int type, long pixels) { VulkanImage image = boundTexture.vulkanImage; - GlBuffer buffer = GlBuffer.getPixelPackBufferBound(); + VkGlBuffer buffer = VkGlBuffer.getPixelPackBufferBound(); long ptr; if (buffer != null) { buffer.data.position((int) pixels); @@ -223,38 +265,53 @@ public static void getTexImage(int tex, int level, int format, int type, long pi } public static void setVulkanImage(int id, VulkanImage vulkanImage) { - GlTexture texture = map.get(id); + VkGlTexture texture = map.get(id); texture.vulkanImage = vulkanImage; } - public static GlTexture getBoundTexture() { + public static VkGlTexture getBoundTexture() { return boundTexture; } - final int id; + public final int id; VulkanImage vulkanImage; - int internalFormat; + + int width, height; + int vkFormat; boolean needsUpdate = false; int maxLevel = 0; int maxLod = 0; - int minFilter, magFilter = GL11.GL_LINEAR; + int minFilter = GL11.GL_NEAREST, magFilter = GL11.GL_NEAREST; boolean clamp = true; - public GlTexture(int id) { + public VkGlTexture(int id) { this.id = id; } - void allocateIfNeeded(int width, int height, int internalFormat, int type) { - this.internalFormat = internalFormat; - int vkFormat = GlUtil.vulkanFormat(internalFormat, type); + void updateParams(int level, int width, int height, int internalFormat, int type) { + if (level > this.maxLevel) { + this.maxLevel = level; + + this.needsUpdate = true; + } + + if (level == 0) { + int vkFormat = GlUtil.vulkanFormat(internalFormat, type); - needsUpdate |= vulkanImage == null || - vulkanImage.width != width || vulkanImage.height != height || - vkFormat != vulkanImage.format; + if (this.vulkanImage == null || this.width != width || this.height != height || vkFormat != vulkanImage.format) { + this.width = width; + this.height = height; + this.vkFormat = vkFormat; + this.needsUpdate = true; + } + } + } + + void allocateIfNeeded() { if (needsUpdate) { allocateImage(width, height, vkFormat); updateSampler(); @@ -267,37 +324,57 @@ void allocateImage(int width, int height, int vkFormat) { if (this.vulkanImage != null) this.vulkanImage.free(); - if (VulkanImage.isDepthFormat(vkFormat)) - this.vulkanImage = VulkanImage.createDepthImage(vkFormat, - width, height, + if (VulkanImage.isDepthFormat(vkFormat)) { + this.vulkanImage = VulkanImage.createDepthImage( + vkFormat, width, height, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, false, true); - else + } + else { this.vulkanImage = new VulkanImage.Builder(width, height) + .setName(String.format("GlTexture %d", this.id)) .setMipLevels(maxLevel + 1) .setFormat(vkFormat) .addUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) .createVulkanImage(); + } } void updateSampler() { if (vulkanImage == null) return; - byte samplerFlags; - samplerFlags = clamp ? SamplerManager.CLAMP_BIT : 0; - samplerFlags |= magFilter == GL11.GL_LINEAR ? SamplerManager.LINEAR_FILTERING_BIT : 0; + int addressMode = clamp ? VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : VK_SAMPLER_ADDRESS_MODE_REPEAT; + int vkMagFilter, vkMinFilter, mipmapMode; + + switch (minFilter) { + case GL11.GL_LINEAR_MIPMAP_LINEAR, GL11.GL_LINEAR -> { + vkMinFilter = VK_FILTER_LINEAR; mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + } + case GL11.GL_LINEAR_MIPMAP_NEAREST -> { + vkMinFilter = VK_FILTER_LINEAR; mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + } + case GL11.GL_NEAREST_MIPMAP_NEAREST, GL11.GL_NEAREST -> { + vkMinFilter = VK_FILTER_NEAREST; mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + } + case GL11.GL_NEAREST_MIPMAP_LINEAR -> { + vkMinFilter = VK_FILTER_NEAREST; mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + } + default -> throw new IllegalStateException("Unexpected min filter value: %d".formatted(minFilter)); + } - samplerFlags |= switch (minFilter) { - case GL11.GL_LINEAR_MIPMAP_LINEAR -> SamplerManager.USE_MIPMAPS_BIT | SamplerManager.MIPMAP_LINEAR_FILTERING_BIT; - case GL11.GL_NEAREST_MIPMAP_NEAREST -> SamplerManager.USE_MIPMAPS_BIT; - default -> 0; + vkMagFilter = switch (magFilter) { + case GL11.GL_LINEAR -> VK_FILTER_LINEAR; + case GL11.GL_NEAREST -> VK_FILTER_NEAREST; + default -> throw new IllegalStateException("Unexpected mag filter value: %d".formatted(magFilter)); }; - vulkanImage.updateTextureSampler(maxLod, samplerFlags); + long sampler = SamplerManager.getSampler(addressMode, addressMode, vkMinFilter, vkMagFilter, mipmapMode, maxLod, false, 0, -1); + + vulkanImage.setSampler(sampler); } - private void uploadSubImage(int xOffset, int yOffset, int width, int height, int format, ByteBuffer pixels) { + private void uploadSubImage(int level, int xOffset, int yOffset, int width, int height, int format, ByteBuffer pixels) { ByteBuffer src; if (format == GL11.GL_RGB && vulkanImage.format == VK_FORMAT_R8G8B8A8_UNORM) { src = GlUtil.RGBtoRGBA_buffer(pixels); @@ -307,7 +384,7 @@ private void uploadSubImage(int xOffset, int yOffset, int width, int height, int src = pixels; } - this.vulkanImage.uploadSubTextureAsync(0, width, height, xOffset, yOffset, 0, 0, 0, src); + this.vulkanImage.uploadSubTextureAsync(level, width, height, xOffset, yOffset, 0, 0, unpackRowLength, src); if (src != pixels) { MemoryUtil.memFree(src); @@ -381,6 +458,10 @@ public VulkanImage getVulkanImage() { public void setVulkanImage(VulkanImage vulkanImage) { this.vulkanImage = vulkanImage; + this.width = vulkanImage.width; + this.height = vulkanImage.height; + this.maxLevel = vulkanImage.mipLevels; + this.vkFormat = vulkanImage.format; } } diff --git a/src/main/java/net/vulkanmod/interfaces/ExtendedRenderTarget.java b/src/main/java/net/vulkanmod/interfaces/ExtendedRenderTarget.java deleted file mode 100644 index f5da47f6d..000000000 --- a/src/main/java/net/vulkanmod/interfaces/ExtendedRenderTarget.java +++ /dev/null @@ -1,10 +0,0 @@ -package net.vulkanmod.interfaces; - -import net.vulkanmod.vulkan.framebuffer.RenderPass; - -public interface ExtendedRenderTarget { - - boolean isBound(); - - RenderPass getRenderPass(); -} diff --git a/src/main/java/net/vulkanmod/interfaces/ShaderMixed.java b/src/main/java/net/vulkanmod/interfaces/ShaderMixed.java deleted file mode 100644 index e1676144f..000000000 --- a/src/main/java/net/vulkanmod/interfaces/ShaderMixed.java +++ /dev/null @@ -1,8 +0,0 @@ -package net.vulkanmod.interfaces; - -import net.vulkanmod.vulkan.shader.GraphicsPipeline; - -public interface ShaderMixed { - - GraphicsPipeline getPipeline(); -} diff --git a/src/main/java/net/vulkanmod/interfaces/biome/BiomeManagerExtended.java b/src/main/java/net/vulkanmod/interfaces/biome/BiomeManagerExtended.java new file mode 100644 index 000000000..6cb365021 --- /dev/null +++ b/src/main/java/net/vulkanmod/interfaces/biome/BiomeManagerExtended.java @@ -0,0 +1,13 @@ +package net.vulkanmod.interfaces.biome; + +import net.minecraft.world.level.biome.BiomeManager; + +public interface BiomeManagerExtended { + + static BiomeManagerExtended of(BiomeManager biomeManager) { + return (BiomeManagerExtended) biomeManager; + } + + long getBiomeZoomSeed(); + +} diff --git a/src/main/java/net/vulkanmod/interfaces/color/BlockColorsExtended.java b/src/main/java/net/vulkanmod/interfaces/color/BlockColorsExtended.java new file mode 100644 index 000000000..69579509e --- /dev/null +++ b/src/main/java/net/vulkanmod/interfaces/color/BlockColorsExtended.java @@ -0,0 +1,13 @@ +package net.vulkanmod.interfaces.color; + +import net.minecraft.client.color.block.BlockColors; +import net.vulkanmod.render.chunk.build.color.BlockColorRegistry; + +public interface BlockColorsExtended { + + static BlockColorsExtended from(BlockColors blockColors) { + return (BlockColorsExtended) blockColors; + } + + BlockColorRegistry getColorResolverMap(); +} diff --git a/src/main/java/net/vulkanmod/interfaces/shader/ExtendedRenderPipeline.java b/src/main/java/net/vulkanmod/interfaces/shader/ExtendedRenderPipeline.java new file mode 100644 index 000000000..0975acc28 --- /dev/null +++ b/src/main/java/net/vulkanmod/interfaces/shader/ExtendedRenderPipeline.java @@ -0,0 +1,20 @@ +package net.vulkanmod.interfaces.shader; + +import com.mojang.blaze3d.pipeline.RenderPipeline; +import net.vulkanmod.render.engine.EGlProgram; +import net.vulkanmod.vulkan.shader.GraphicsPipeline; + +public interface ExtendedRenderPipeline { + + static ExtendedRenderPipeline of(RenderPipeline renderPipeline) { + return (ExtendedRenderPipeline) renderPipeline; + } + + void setPipeline(GraphicsPipeline pipeline); + + void setProgram(EGlProgram program); + + GraphicsPipeline getPipeline(); + + EGlProgram getProgram(); +} diff --git a/src/main/java/net/vulkanmod/mixin/chunk/ClientChunkCacheM.java b/src/main/java/net/vulkanmod/mixin/chunk/ClientChunkCacheM.java index 0b32f688b..0f5e9d392 100644 --- a/src/main/java/net/vulkanmod/mixin/chunk/ClientChunkCacheM.java +++ b/src/main/java/net/vulkanmod/mixin/chunk/ClientChunkCacheM.java @@ -6,6 +6,7 @@ import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.levelgen.Heightmap; import net.vulkanmod.render.chunk.ChunkStatusMap; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; @@ -14,6 +15,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.Map; import java.util.function.Consumer; @Mixin(ClientChunkCache.class) @@ -21,12 +23,14 @@ public class ClientChunkCacheM { @Inject(method = "replaceWithPacketData", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientLevel;onChunkLoaded(Lnet/minecraft/world/level/ChunkPos;)V")) - private void setChunkStatus(int x, int z, FriendlyByteBuf friendlyByteBuf, CompoundTag compoundTag, Consumer consumer, CallbackInfoReturnable<@Nullable LevelChunk> cir) { + private void setChunkStatus(int x, int z, FriendlyByteBuf friendlyByteBuf, Map map, + Consumer consumer, + CallbackInfoReturnable cir) { ChunkStatusMap.INSTANCE.setChunkStatus(x, z, ChunkStatusMap.DATA_READY); } @Inject(method = "drop", at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/multiplayer/ClientChunkCache$Storage;replace(ILnet/minecraft/world/level/chunk/LevelChunk;Lnet/minecraft/world/level/chunk/LevelChunk;)Lnet/minecraft/world/level/chunk/LevelChunk;")) + target = "Lnet/minecraft/client/multiplayer/ClientChunkCache$Storage;drop(ILnet/minecraft/world/level/chunk/LevelChunk;)V")) private void resetChunkStatus(ChunkPos chunkPos, CallbackInfo ci) { ChunkStatusMap.INSTANCE.resetChunkStatus(chunkPos.x, chunkPos.z, ChunkStatusMap.DATA_READY); } diff --git a/src/main/java/net/vulkanmod/mixin/chunk/ClientPacketListenerM.java b/src/main/java/net/vulkanmod/mixin/chunk/ClientPacketListenerM.java index dd2368259..aaa05df76 100644 --- a/src/main/java/net/vulkanmod/mixin/chunk/ClientPacketListenerM.java +++ b/src/main/java/net/vulkanmod/mixin/chunk/ClientPacketListenerM.java @@ -14,7 +14,7 @@ public class ClientPacketListenerM { @Inject(method = "applyLightData", at = @At("RETURN")) - private void setChunkStatus(int x, int z, ClientboundLightUpdatePacketData clientboundLightUpdatePacketData, CallbackInfo ci) { + private void setChunkStatus(int x, int z, ClientboundLightUpdatePacketData clientboundLightUpdatePacketData, boolean bl, CallbackInfo ci) { ChunkStatusMap.INSTANCE.setChunkStatus(x, z, ChunkStatusMap.LIGHT_READY); } diff --git a/src/main/java/net/vulkanmod/mixin/chunk/FrustumMixin.java b/src/main/java/net/vulkanmod/mixin/chunk/FrustumMixin.java index 4959c34d2..7fdfcc70e 100644 --- a/src/main/java/net/vulkanmod/mixin/chunk/FrustumMixin.java +++ b/src/main/java/net/vulkanmod/mixin/chunk/FrustumMixin.java @@ -4,8 +4,11 @@ import net.vulkanmod.interfaces.FrustumMixed; import net.vulkanmod.render.chunk.frustum.VFrustum; import org.joml.Matrix4f; +import org.joml.Vector4f; +import org.spongepowered.asm.mixin.Final; 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.CallbackInfo; @@ -16,13 +19,15 @@ public class FrustumMixin implements FrustumMixed { @Shadow private double camX; @Shadow private double camY; @Shadow private double camZ; - private final VFrustum vFrustum = new VFrustum(); + @Shadow @Final private Matrix4f matrix; + @Shadow private Vector4f viewVector; - @Inject(method = "calculateFrustum", at = @At("HEAD"), cancellable = true) + @Unique private final VFrustum vFrustum = new VFrustum(); + + @Inject(method = "calculateFrustum", at = @At("HEAD")) private void calculateFrustum(Matrix4f modelView, Matrix4f projection, CallbackInfo ci) { -// this.vFrustum = new VFrustum(modelView, projection); this.vFrustum.calculateFrustum(modelView, projection); - ci.cancel(); + this.viewVector = this.matrix.transformTranspose(new Vector4f(0.0F, 0.0F, 1.0F, 0.0F)); } @Inject(method = "prepare", at = @At("RETURN")) diff --git a/src/main/java/net/vulkanmod/mixin/chunk/LevelRendererMixin.java b/src/main/java/net/vulkanmod/mixin/chunk/LevelRendererMixin.java index 394213f7b..c4471218b 100644 --- a/src/main/java/net/vulkanmod/mixin/chunk/LevelRendererMixin.java +++ b/src/main/java/net/vulkanmod/mixin/chunk/LevelRendererMixin.java @@ -1,5 +1,7 @@ package net.vulkanmod.mixin.chunk; +import com.mojang.blaze3d.buffers.GpuBufferSlice; +import com.mojang.blaze3d.resource.GraphicsResourceAllocator; import com.mojang.blaze3d.vertex.PoseStack; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import net.minecraft.client.Camera; @@ -8,14 +10,22 @@ import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.*; import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; +import net.minecraft.client.renderer.chunk.ChunkSectionLayerGroup; +import net.minecraft.client.renderer.chunk.ChunkSectionsToRender; import net.minecraft.client.renderer.culling.Frustum; import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.client.renderer.feature.FeatureRenderDispatcher; +import net.minecraft.client.renderer.state.LevelRenderState; import net.minecraft.core.BlockPos; import net.minecraft.server.level.BlockDestructionProgress; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.phys.Vec3; import net.vulkanmod.render.chunk.WorldRenderer; +import net.vulkanmod.render.profiling.Profiler; +import net.vulkanmod.render.vertex.TerrainRenderType; import org.joml.Matrix4f; +import org.joml.Matrix4fc; +import org.joml.Vector4f; import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -26,18 +36,19 @@ @Mixin(LevelRenderer.class) public abstract class LevelRendererMixin { + @Shadow @Final private Long2ObjectMap> destructionProgress; - @Shadow @Final - private RenderBuffers renderBuffers; + @Unique private WorldRenderer worldRenderer; - @Shadow @Final - private Long2ObjectMap> destructionProgress; - - private WorldRenderer worldRenderer; + @Unique double camX, camY, camZ; + @Unique Matrix4f modelView, projection; @Inject(method = "", at = @At("RETURN")) - private void init(Minecraft minecraft, EntityRenderDispatcher entityRenderDispatcher, BlockEntityRenderDispatcher blockEntityRenderDispatcher, RenderBuffers renderBuffers, CallbackInfo ci) { - this.worldRenderer = WorldRenderer.init(this.renderBuffers); + private void init(Minecraft minecraft, EntityRenderDispatcher entityRenderDispatcher, + BlockEntityRenderDispatcher blockEntityRenderDispatcher, RenderBuffers renderBuffers, + LevelRenderState levelRenderState, FeatureRenderDispatcher featureRenderDispatcher, + CallbackInfo ci) { + this.worldRenderer = WorldRenderer.init(entityRenderDispatcher, blockEntityRenderDispatcher, renderBuffers, levelRenderState, featureRenderDispatcher); } @Inject(method = "setLevel", at = @At("RETURN")) @@ -50,12 +61,20 @@ private void onAllChanged(CallbackInfo ci) { this.worldRenderer.allChanged(); } - @Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;checkPoseStack(Lcom/mojang/blaze3d/vertex/PoseStack;)V", ordinal = 1, shift = At.Shift.BEFORE)) - private void renderBlockEntities(DeltaTracker deltaTracker, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, Matrix4f matrix4f2, CallbackInfo ci) { - Vec3 pos = camera.getPosition(); - PoseStack poseStack = new PoseStack(); + @Inject(method = "extractVisibleBlockEntities", at = @At("HEAD"), cancellable = true) + private void onExtractVisibleBlockEntities(Camera camera, float partialTick, LevelRenderState levelRenderState, + CallbackInfo ci) { + this.worldRenderer.setPartialTick(partialTick); - this.worldRenderer.renderBlockEntities(poseStack, pos.x(), pos.y(), pos.z(), this.destructionProgress, deltaTracker.getGameTimeDeltaPartialTick(false)); + ci.cancel(); + } + + @Inject(method = "submitBlockEntities", at = @At(value = "RETURN"), cancellable = true) + private void onSubmitBlockEntities(PoseStack poseStack, LevelRenderState levelRenderState, + SubmitNodeStorage submitNodeStorage, CallbackInfo ci) { + this.worldRenderer.renderBlockEntities(poseStack, levelRenderState, submitNodeStorage, this.destructionProgress); + + ci.cancel(); } /** @@ -63,8 +82,9 @@ private void renderBlockEntities(DeltaTracker deltaTracker, boolean bl, Camera c * @reason */ @Overwrite - private void setupRender(Camera camera, Frustum frustum, boolean isCapturedFrustum, boolean spectator) { - this.worldRenderer.setupRenderer(camera, frustum, isCapturedFrustum, spectator); + private void cullTerrain(Camera camera, Frustum frustum, boolean spectator) { + // TODO: port capture frustum + this.worldRenderer.setupRenderer(camera, frustum, false, spectator); } /** @@ -76,13 +96,43 @@ public boolean isSectionCompiled(BlockPos blockPos) { return this.worldRenderer.isSectionCompiled(blockPos); } - /** - * @author - * @reason - */ + @Inject(method = "renderLevel", at = @At("HEAD")) + private void updateMatrices(GraphicsResourceAllocator graphicsResourceAllocator, DeltaTracker deltaTracker, + boolean bl, Camera camera, Matrix4f modelView, Matrix4f projection, Matrix4f matrix4f, + GpuBufferSlice gpuBufferSlice, Vector4f vector4f, boolean bl2, CallbackInfo ci) { + this.modelView = modelView; + this.projection = projection; + } + @Overwrite - private void renderSectionLayer(RenderType renderType, double camX, double camY, double camZ, Matrix4f modelView, Matrix4f projectionMatrix) { - this.worldRenderer.renderSectionLayer(renderType, camX, camY, camZ, modelView, projectionMatrix); + private ChunkSectionsToRender prepareChunkRenders(Matrix4fc matrix4fc, double camX, double camY, double camZ) { + this.camX = camX; + this.camY = camY; + this.camZ = camZ; + + return null; + } + + @Redirect(method = "method_62214", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/chunk/ChunkSectionsToRender;renderGroup(Lnet/minecraft/client/renderer/chunk/ChunkSectionLayerGroup;)V")) + private void renderSectionLayer(ChunkSectionsToRender instance, ChunkSectionLayerGroup chunkSectionLayerGroup) { + if (chunkSectionLayerGroup == ChunkSectionLayerGroup.OPAQUE) { + Profiler profiler = Profiler.getMainProfiler(); + profiler.push("Opaque_terrain"); + + this.worldRenderer.renderSectionLayer(TerrainRenderType.SOLID, camX, camY, camZ, modelView, projection); + this.worldRenderer.renderSectionLayer(TerrainRenderType.CUTOUT, camX, camY, camZ, modelView, projection); + this.worldRenderer.renderSectionLayer(TerrainRenderType.CUTOUT_MIPPED, camX, camY, camZ, modelView, projection); + } + else if (chunkSectionLayerGroup == ChunkSectionLayerGroup.TRANSLUCENT) { + Profiler profiler = Profiler.getMainProfiler(); + profiler.pop(); + profiler.push("Translucent_terrain"); + + this.worldRenderer.renderSectionLayer(TerrainRenderType.TRANSLUCENT, camX, camY, camZ, modelView, projection); + + profiler.pop(); + } + } /** @@ -90,7 +140,7 @@ private void renderSectionLayer(RenderType renderType, double camX, double camY, * @reason */ @Overwrite - public void onChunkLoaded(ChunkPos chunkPos) { + public void onChunkReadyToRender(ChunkPos chunkPos) { } /** @@ -129,7 +179,7 @@ public int countRenderedSections() { return this.worldRenderer.getVisibleSectionsCount(); } - @Redirect(method = "renderWorldBorder", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;getDepthFar()F")) + @Redirect(method = "addWeatherPass", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;getDepthFar()F")) private float getRenderDistanceZFar(GameRenderer instance) { return instance.getRenderDistance() * 4F; } diff --git a/src/main/java/net/vulkanmod/mixin/chunk/RenderBuffersM.java b/src/main/java/net/vulkanmod/mixin/chunk/RenderBuffersM.java deleted file mode 100644 index 743885028..000000000 --- a/src/main/java/net/vulkanmod/mixin/chunk/RenderBuffersM.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.vulkanmod.mixin.chunk; - -import net.minecraft.client.renderer.RenderBuffers; -import net.minecraft.client.renderer.SectionBufferBuilderPool; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(RenderBuffers.class) -public class RenderBuffersM { - - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SectionBufferBuilderPool;allocate(I)Lnet/minecraft/client/renderer/SectionBufferBuilderPool;")) - private SectionBufferBuilderPool red2(int i) { - return null; - } -} diff --git a/src/main/java/net/vulkanmod/mixin/chunk/SectionBufferBuilderPoolM.java b/src/main/java/net/vulkanmod/mixin/chunk/SectionBufferBuilderPoolM.java new file mode 100644 index 000000000..18e653849 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/chunk/SectionBufferBuilderPoolM.java @@ -0,0 +1,15 @@ +package net.vulkanmod.mixin.chunk; + +import net.minecraft.client.renderer.SectionBufferBuilderPool; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +@Mixin(SectionBufferBuilderPool.class) +public class SectionBufferBuilderPoolM { + + @ModifyVariable(method = "allocate", at = @At("STORE"), ordinal = 1) + private static int skipAllocation(int value) { + return 0; + } +} diff --git a/src/main/java/net/vulkanmod/mixin/chunk/SectionRenderDispatcherM.java b/src/main/java/net/vulkanmod/mixin/chunk/SectionRenderDispatcherM.java index 9dbdab773..35a1bafc7 100644 --- a/src/main/java/net/vulkanmod/mixin/chunk/SectionRenderDispatcherM.java +++ b/src/main/java/net/vulkanmod/mixin/chunk/SectionRenderDispatcherM.java @@ -1,7 +1,6 @@ package net.vulkanmod.mixin.chunk; import net.minecraft.client.renderer.chunk.SectionRenderDispatcher; -import net.minecraft.util.thread.ProcessorMailbox; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -9,6 +8,7 @@ @Mixin(SectionRenderDispatcher.class) public class SectionRenderDispatcherM { - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/thread/ProcessorMailbox;tell(Ljava/lang/Object;)V")) - private void redirectTask(ProcessorMailbox instance, Object object) {} + // TODO +// @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/thread/ProcessorMailbox;tell(Ljava/lang/Object;)V")) +// private void redirectTask(ProcessorMailbox instance, Object object) {} } diff --git a/src/main/java/net/vulkanmod/mixin/compatibility/EffectInstanceM.java b/src/main/java/net/vulkanmod/mixin/compatibility/EffectInstanceM.java deleted file mode 100644 index 1e3d2827b..000000000 --- a/src/main/java/net/vulkanmod/mixin/compatibility/EffectInstanceM.java +++ /dev/null @@ -1,228 +0,0 @@ -package net.vulkanmod.mixin.compatibility; - -import com.google.gson.JsonObject; -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.shaders.BlendMode; -import com.mojang.blaze3d.shaders.EffectProgram; -import com.mojang.blaze3d.shaders.Program; -import com.mojang.blaze3d.shaders.ProgramManager; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.DefaultVertexFormat; -import net.minecraft.client.renderer.EffectInstance; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.Resource; -import net.minecraft.server.packs.resources.ResourceProvider; -import net.vulkanmod.vulkan.Renderer; -import net.vulkanmod.vulkan.shader.GraphicsPipeline; -import net.vulkanmod.vulkan.shader.Pipeline; -import net.vulkanmod.vulkan.shader.layout.Uniform; -import net.vulkanmod.vulkan.shader.descriptor.UBO; -import net.vulkanmod.vulkan.shader.parser.GlslConverter; -import net.vulkanmod.vulkan.util.MappedBuffer; -import org.apache.commons.io.IOUtils; -import org.lwjgl.opengl.GL30; -import org.lwjgl.system.MemoryUtil; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.function.IntSupplier; -import java.util.function.Supplier; - -@Mixin(EffectInstance.class) -public class EffectInstanceM { - - @Shadow @Final private Map uniformMap; - @Shadow @Final private List uniforms; - - @Shadow private boolean dirty; - @Shadow private static EffectInstance lastAppliedEffect; - @Shadow @Final private BlendMode blend; - @Shadow private static int lastProgramId; - @Shadow @Final private int programId; - @Shadow @Final private List samplerLocations; - @Shadow @Final private List samplerNames; - @Shadow @Final private Map samplerMap; - - @Shadow @Final private String name; - private static GraphicsPipeline lastPipeline; - - private GraphicsPipeline pipeline; - - @Inject(method = "", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/renderer/EffectInstance;updateLocations()V", - shift = At.Shift.AFTER), - locals = LocalCapture.CAPTURE_FAILHARD - ) - private void inj(ResourceProvider resourceProvider, String string, CallbackInfo ci, ResourceLocation resourceLocation, Resource resource, Reader reader, JsonObject jsonObject, String string2, String string3) { - createShaders(resourceProvider, string2, string3); - } - - @Redirect(method = "", at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/renderer/EffectInstance;getOrCreate(Lnet/minecraft/server/packs/resources/ResourceProvider;Lcom/mojang/blaze3d/shaders/Program$Type;Ljava/lang/String;)Lcom/mojang/blaze3d/shaders/EffectProgram;")) - private EffectProgram redirectShader(ResourceProvider resourceProvider, Program.Type type, String string) { - return null; - } - - /** - * @author - * @reason - */ - @Overwrite - public void close() { - - for (com.mojang.blaze3d.shaders.Uniform uniform : this.uniforms) { - uniform.close(); - } - - //TODO -// ProgramManager.releaseProgram(this); - } - - private void createShaders(ResourceProvider resourceManager, String vertexShader, String fragShader) { - - try { - String[] vshPathInfo = this.decompose(vertexShader, ':'); - ResourceLocation vshLocation = ResourceLocation.fromNamespaceAndPath(vshPathInfo[0], "shaders/program/" + vshPathInfo[1] + ".vsh"); - Resource resource = resourceManager.getResourceOrThrow(vshLocation); - InputStream inputStream = resource.open(); - String vshSrc = IOUtils.toString(inputStream, StandardCharsets.UTF_8); - - String[] fshPathInfo = this.decompose(fragShader, ':'); - ResourceLocation fshLocation = ResourceLocation.fromNamespaceAndPath(fshPathInfo[0], "shaders/program/" + fshPathInfo[1] + ".fsh"); - resource = resourceManager.getResourceOrThrow(fshLocation); - inputStream = resource.open(); - String fshSrc = IOUtils.toString(inputStream, StandardCharsets.UTF_8); - - //TODO - GlslConverter converter = new GlslConverter(); - - converter.process(vshSrc, fshSrc); - UBO ubo = converter.getUBO(); - this.setUniformSuppliers(ubo); - - Pipeline.Builder builder = new Pipeline.Builder(DefaultVertexFormat.POSITION); - builder.setUniforms(Collections.singletonList(ubo), converter.getSamplerList()); - builder.compileShaders(this.name, converter.getVshConverted(), converter.getFshConverted()); - - this.pipeline = builder.createGraphicsPipeline(); - - } catch (IOException e) { - throw new RuntimeException(e); - } - - } - - private void setUniformSuppliers(UBO ubo) { - - for(Uniform v_uniform : ubo.getUniforms()) { - com.mojang.blaze3d.shaders.Uniform uniform = this.uniformMap.get(v_uniform.getName()); - - Supplier supplier; - ByteBuffer byteBuffer; - - if (uniform.getType() <= 3) { - byteBuffer = MemoryUtil.memByteBuffer(uniform.getIntBuffer()); - } - else if (uniform.getType() <= 10) { - byteBuffer = MemoryUtil.memByteBuffer(uniform.getFloatBuffer()); - } - else { - throw new RuntimeException("out of bounds value for uniform " + uniform); - } - - MappedBuffer mappedBuffer = MappedBuffer.createFromBuffer(byteBuffer); - supplier = () -> mappedBuffer; - - v_uniform.setSupplier(supplier); - } - - } - - private String[] decompose(String string, char c) { - String[] strings = new String[]{"minecraft", string}; - int i = string.indexOf(c); - if (i >= 0) { - strings[1] = string.substring(i + 1); - if (i >= 1) { - strings[0] = string.substring(0, i); - } - } - - return strings; - } - - /** - * @author - * @reason - */ - @Overwrite - public void apply() { - this.dirty = false; - this.blend.apply(); - - Renderer renderer = Renderer.getInstance(); - - if (this.pipeline != lastPipeline) { - renderer.bindGraphicsPipeline(pipeline); - lastPipeline = this.pipeline; - } - - for(int i = 0; i < this.samplerLocations.size(); ++i) { - String string = this.samplerNames.get(i); - IntSupplier intSupplier = this.samplerMap.get(string); - if (intSupplier != null) { - RenderSystem.activeTexture(GL30.GL_TEXTURE0 + i); - int j = intSupplier.getAsInt(); - if (j != -1) { - RenderSystem.bindTexture(j); - com.mojang.blaze3d.shaders.Uniform.uploadInteger(this.samplerLocations.get(i), i); - } - } - } - - for (com.mojang.blaze3d.shaders.Uniform uniform : this.uniforms) { - uniform.upload(); - } - - renderer.uploadAndBindUBOs(pipeline); - - } - - /** - * @author - * @reason - */ - @Overwrite - public void clear() { - RenderSystem.assertOnRenderThread(); - ProgramManager.glUseProgram(0); - lastProgramId = -1; - lastAppliedEffect = null; - lastPipeline = null; - - for(int i = 0; i < this.samplerLocations.size(); ++i) { - if (this.samplerMap.get(this.samplerNames.get(i)) != null) { - GlStateManager._activeTexture(GL30.GL_TEXTURE0 + i); - GlStateManager._bindTexture(0); - } - } - - } -} diff --git a/src/main/java/net/vulkanmod/mixin/compatibility/PostChainM.java b/src/main/java/net/vulkanmod/mixin/compatibility/PostChainM.java deleted file mode 100644 index 885440c65..000000000 --- a/src/main/java/net/vulkanmod/mixin/compatibility/PostChainM.java +++ /dev/null @@ -1,291 +0,0 @@ -package net.vulkanmod.mixin.compatibility; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.mojang.blaze3d.pipeline.RenderTarget; -import com.mojang.blaze3d.systems.RenderSystem; -import net.minecraft.client.renderer.PostChain; -import net.minecraft.client.renderer.PostPass; -import net.minecraft.client.renderer.texture.AbstractTexture; -import net.minecraft.client.renderer.texture.TextureManager; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.ChainedJsonException; -import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.util.GsonHelper; -import net.vulkanmod.vulkan.Renderer; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -import java.io.IOException; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -@Mixin(PostChain.class) -public abstract class PostChainM { - - @Shadow private int screenWidth; - @Shadow private int screenHeight; - - @Shadow @Final private Map customRenderTargets; - @Shadow @Final private RenderTarget screenTarget; - @Shadow @Final private List passes; - - @Shadow private float lastStamp; - @Shadow private float time; - - @Shadow public abstract void addTempTarget(String string, int i, int j); - @Shadow protected abstract void parseTargetNode(JsonElement jsonElement) throws ChainedJsonException; - @Shadow protected abstract void parseUniformNode(JsonElement jsonElement) throws ChainedJsonException; - -// /** -// * @author -// * @reason -// */ -// @Overwrite -// private void load(TextureManager textureManager, ResourceLocation resourceLocation) throws IOException, JsonSyntaxException { -// Resource resource = this.resourceManager.getResourceOrThrow(resourceLocation); -// -// try { -// Reader reader = resource.openAsReader(); -// -// try { -// JsonObject jsonObject = GsonHelper.parse(reader); -// JsonArray jsonArray; -// int i; -// JsonElement jsonElement; -// if (GsonHelper.isArrayNode(jsonObject, "targets")) { -// jsonArray = jsonObject.getAsJsonArray("targets"); -// i = 0; -// -// Iterator iterator; -// for(iterator = jsonArray.iterator(); iterator.hasNext(); ++i) { -// jsonElement = iterator.next(); -// -// try { -// this.parseTargetNode(jsonElement); -// } catch (Exception var14) { -// ChainedJsonException chainedJsonException = ChainedJsonException.forException(var14); -// chainedJsonException.prependJsonKey("targets[" + i + "]"); -// throw chainedJsonException; -// } -// } -// } -// -// if (GsonHelper.isArrayNode(jsonObject, "passes")) { -// jsonArray = jsonObject.getAsJsonArray("passes"); -// i = 0; -// -// Iterator iterator; -// for(iterator = jsonArray.iterator(); iterator.hasNext(); ++i) { -// jsonElement = iterator.next(); -// -// try { -// this.parsePassNode(textureManager, jsonElement); -// } catch (Exception var13) { -// ChainedJsonException chainedJsonException = ChainedJsonException.forException(var13); -// chainedJsonException.prependJsonKey("passes[" + i + "]"); -// throw chainedJsonException; -// } -// } -// } -// } catch (Throwable var15) { -// try { -// reader.close(); -// } catch (Throwable var12) { -// var15.addSuppressed(var12); -// } -// -// throw var15; -// } -// -// reader.close(); -// -// } catch (Exception var16) { -// ChainedJsonException chainedJsonException2 = ChainedJsonException.forException(var16); -// String var10001 = resourceLocation.getPath(); -// chainedJsonException2.setFilenameAndFlush(var10001 + " (" + resource.sourcePackId() + ")"); -// throw chainedJsonException2; -// } -// } - -// /** -// * @author -// * @reason -// */ -// @Overwrite -// private void parseTargetNode(JsonElement jsonElement) throws ChainedJsonException { -// if (GsonHelper.isStringValue(jsonElement)) { -// this.addTempTarget(jsonElement.getAsString(), this.screenWidth, this.screenHeight); -// } else { -// JsonObject jsonObject = GsonHelper.convertToJsonObject(jsonElement, "target"); -// String string = GsonHelper.getAsString(jsonObject, "name"); -// int i = GsonHelper.getAsInt(jsonObject, "width", this.screenWidth); -// int j = GsonHelper.getAsInt(jsonObject, "height", this.screenHeight); -// if (this.customRenderTargets.containsKey(string)) { -// throw new ChainedJsonException(string + " is already defined"); -// } -// -// this.addTempTarget(string, i, j); -// } -// -// } - -// /** -// * @author -// * @reason -// */ -// @Overwrite -// private void parsePassNode(TextureManager textureManager, JsonElement jsonElement) throws IOException { -// JsonObject jsonObject = GsonHelper.convertToJsonObject(jsonElement, "pass"); -// String string = GsonHelper.getAsString(jsonObject, "name"); -// String string2 = GsonHelper.getAsString(jsonObject, "intarget"); -// String string3 = GsonHelper.getAsString(jsonObject, "outtarget"); -// RenderTarget renderTarget = this.getRenderTarget(string2); -// RenderTarget renderTarget2 = this.getRenderTarget(string3); -// if (renderTarget == null) { -// throw new ChainedJsonException("Input target '" + string2 + "' does not exist"); -// } else if (renderTarget2 == null) { -// throw new ChainedJsonException("Output target '" + string3 + "' does not exist"); -// } else { -// PostPass postPass = this.addPass(string, renderTarget, renderTarget2); -// JsonArray jsonArray = GsonHelper.getAsJsonArray(jsonObject, "auxtargets", null); -// if (jsonArray != null) { -// int i = 0; -// -// for(Iterator var12 = jsonArray.iterator(); var12.hasNext(); ++i) { -// JsonElement jsonElement2 = (JsonElement)var12.next(); -// -// try { -// JsonObject jsonObject2 = GsonHelper.convertToJsonObject(jsonElement2, "auxtarget"); -// String string4 = GsonHelper.getAsString(jsonObject2, "name"); -// String string5 = GsonHelper.getAsString(jsonObject2, "id"); -// boolean bl; -// String string6; -// if (string5.endsWith(":depth")) { -// bl = true; -// string6 = string5.substring(0, string5.lastIndexOf(58)); -// } else { -// bl = false; -// string6 = string5; -// } -// -// RenderTarget renderTarget3 = this.getRenderTarget(string6); -// if (renderTarget3 == null) { -// if (bl) { -// throw new ChainedJsonException("Render target '" + string6 + "' can't be used as depth buffer"); -// } -// -// ResourceLocation resourceLocation = new ResourceLocation("textures/effect/" + string6 + ".png"); -// this.resourceManager.getResource(resourceLocation).orElseThrow(() -> { -// return new ChainedJsonException("Render target or texture '" + string6 + "' does not exist"); -// }); -// RenderSystem.setShaderTexture(0, resourceLocation); -// textureManager.bindForSetup(resourceLocation); -// AbstractTexture abstractTexture = textureManager.getTexture(resourceLocation); -// int j = GsonHelper.getAsInt(jsonObject2, "width"); -// int k = GsonHelper.getAsInt(jsonObject2, "height"); -// boolean bl2 = GsonHelper.getAsBoolean(jsonObject2, "bilinear"); -// if (bl2) { -// RenderSystem.texParameter(3553, 10241, 9729); -// RenderSystem.texParameter(3553, 10240, 9729); -// } else { -// RenderSystem.texParameter(3553, 10241, 9728); -// RenderSystem.texParameter(3553, 10240, 9728); -// } -// -// Objects.requireNonNull(abstractTexture); -// postPass.addAuxAsset(string4, abstractTexture::getId, j, k); -// } else if (bl) { -// Objects.requireNonNull(renderTarget3); -// postPass.addAuxAsset(string4, renderTarget3::getDepthTextureId, renderTarget3.width, renderTarget3.height); -// } else { -// Objects.requireNonNull(renderTarget3); -// postPass.addAuxAsset(string4, renderTarget3::getColorTextureId, renderTarget3.width, renderTarget3.height); -// } -// } catch (Exception e) { -// ChainedJsonException chainedJsonException = ChainedJsonException.forException(e); -// chainedJsonException.prependJsonKey("auxtargets[" + i + "]"); -// throw chainedJsonException; -// } -// } -// } -// -// JsonArray jsonArray2 = GsonHelper.getAsJsonArray(jsonObject, "uniforms", null); -// if (jsonArray2 != null) { -// int l = 0; -// -// for(Iterator var29 = jsonArray2.iterator(); var29.hasNext(); ++l) { -// JsonElement jsonElement3 = var29.next(); -// -// try { -// this.parseUniformNode(jsonElement3); -// } catch (Exception var25) { -// ChainedJsonException chainedJsonException2 = ChainedJsonException.forException(var25); -// chainedJsonException2.prependJsonKey("uniforms[" + l + "]"); -// throw chainedJsonException2; -// } -// } -// } -// -// } -// } -// -// private RenderTarget getRenderTarget(@Nullable String string) { -// if (string == null) { -// return null; -// } else { -// return string.equals("minecraft:main") ? this.screenTarget : this.customRenderTargets.get(string); -// } -// } -// -// public PostPass addPass(String string, RenderTarget renderTarget, RenderTarget renderTarget2) throws IOException { -// PostPass postPass = new PostPass(this.resourceManager, string, renderTarget, renderTarget2); -// this.passes.add(this.passes.size(), postPass); -// return postPass; -// } - - @Shadow protected abstract void setFilterMode(int i); - - /** - * @author - * @reason - */ - @Overwrite - public void process(float f) { - if (f < this.lastStamp) { - this.time += 1.0F - this.lastStamp; - this.time += f; - } else { - this.time += f - this.lastStamp; - } - - this.lastStamp = f; - - while(this.time > 20.0F) { - this.time -= 20.0F; - } - - int filterMode = 9728; - - for(PostPass postPass : this.passes) { - int passFilterMode = postPass.getFilterMode(); - if (filterMode != passFilterMode) { - this.setFilterMode(passFilterMode); - filterMode = passFilterMode; - } - - postPass.process(this.time / 20.0F); - } - - this.setFilterMode(9728); - - Renderer.resetViewport(); - } - -} diff --git a/src/main/java/net/vulkanmod/mixin/compatibility/PostPassM.java b/src/main/java/net/vulkanmod/mixin/compatibility/PostPassM.java index 14c111690..db125cafa 100644 --- a/src/main/java/net/vulkanmod/mixin/compatibility/PostPassM.java +++ b/src/main/java/net/vulkanmod/mixin/compatibility/PostPassM.java @@ -1,104 +1,39 @@ package net.vulkanmod.mixin.compatibility; -import com.mojang.blaze3d.pipeline.MainTarget; -import com.mojang.blaze3d.pipeline.RenderTarget; -import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.buffers.GpuBufferSlice; +import com.mojang.blaze3d.resource.ResourceHandle; import com.mojang.blaze3d.vertex.*; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.EffectInstance; import net.minecraft.client.renderer.PostPass; +import net.vulkanmod.render.engine.*; import net.vulkanmod.vulkan.Renderer; -import net.vulkanmod.vulkan.VRenderSystem; -import net.vulkanmod.vulkan.util.DrawUtil; -import org.joml.Matrix4f; -import org.lwjgl.opengl.GL11; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.List; -import java.util.Objects; -import java.util.function.IntSupplier; +import java.util.Map; @Mixin(PostPass.class) -public class PostPassM { +public abstract class PostPassM { + @Shadow @Final private List inputs; - @Shadow @Final public RenderTarget inTarget; + @Inject(method = "method_67884", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/GpuDevice;createCommandEncoder()Lcom/mojang/blaze3d/systems/CommandEncoder;")) + private void transitionLayouts(ResourceHandle resourceHandle, GpuBufferSlice gpuBufferSlice, Map map, + CallbackInfo ci) { + Renderer.getInstance().endRenderPass(); - @Shadow @Final public RenderTarget outTarget; + for (var input : this.inputs) { + VkGpuTexture gpuTexture = (VkGpuTexture) input.texture(map).texture(); - @Shadow @Final private EffectInstance effect; - - @Shadow @Final private List auxAssets; - - @Shadow @Final private List auxNames; - - @Shadow @Final private List auxWidths; - - @Shadow @Final private List auxHeights; - - @Shadow private Matrix4f shaderOrthoMatrix; - - /** - * @author - * @reason - */ - @Overwrite - public void process(float f) { - this.inTarget.unbindWrite(); - float g = (float)this.outTarget.width; - float h = (float)this.outTarget.height; - RenderSystem.viewport(0, 0, (int)g, (int)h); - - Objects.requireNonNull(this.inTarget); - this.effect.setSampler("DiffuseSampler", this.inTarget::getColorTextureId); - - if(this.inTarget instanceof MainTarget) - this.inTarget.bindRead(); - - for(int i = 0; i < this.auxAssets.size(); ++i) { - this.effect.setSampler(this.auxNames.get(i), this.auxAssets.get(i)); - this.effect.safeGetUniform("AuxSize" + i).set((float) this.auxWidths.get(i), (float) this.auxHeights.get(i)); - } - - this.effect.safeGetUniform("ProjMat").set(this.shaderOrthoMatrix); - this.effect.safeGetUniform("InSize").set((float)this.inTarget.width, (float)this.inTarget.height); - this.effect.safeGetUniform("OutSize").set(g, h); - this.effect.safeGetUniform("Time").set(f); - Minecraft minecraft = Minecraft.getInstance(); - this.effect.safeGetUniform("ScreenSize").set((float)minecraft.getWindow().getWidth(), (float)minecraft.getWindow().getHeight()); - - this.outTarget.clear(Minecraft.ON_OSX); - this.outTarget.bindWrite(false); - - VRenderSystem.disableCull(); - VRenderSystem.depthFunc(519); - VRenderSystem.setPrimitiveTopologyGL(GL11.GL_TRIANGLES); - - Renderer.setInvertedViewport(0, 0, this.outTarget.width, this.outTarget.height); - Renderer.resetScissor(); - - this.effect.apply(); - - BufferBuilder bufferBuilder = Tesselator.getInstance().begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION); - bufferBuilder.addVertex(0.0f, 0.0f, 500.0f); - bufferBuilder.addVertex(g, 0.0f, 500.0f); - bufferBuilder.addVertex(g, h, 500.0f); - bufferBuilder.addVertex(0.0f, h, 500.0f); - BufferUploader.draw(bufferBuilder.buildOrThrow()); - RenderSystem.depthFunc(515); - - this.effect.clear(); - this.outTarget.unbindWrite(); - this.inTarget.unbindRead(); - - for (Object object : this.auxAssets) { - if (object instanceof RenderTarget) { - ((RenderTarget) object).unbindRead(); + if (gpuTexture.needsClear()) { + gpuTexture.getFbo(null).bind(); } - } - VRenderSystem.enableCull(); + gpuTexture.getVulkanImage().readOnlyLayout(); + } } + } diff --git a/src/main/java/net/vulkanmod/mixin/compatibility/ProgramM.java b/src/main/java/net/vulkanmod/mixin/compatibility/ProgramM.java deleted file mode 100644 index 7771c43f9..000000000 --- a/src/main/java/net/vulkanmod/mixin/compatibility/ProgramM.java +++ /dev/null @@ -1,44 +0,0 @@ -package net.vulkanmod.mixin.compatibility; - -import com.mojang.blaze3d.preprocessor.GlslPreprocessor; -import com.mojang.blaze3d.shaders.Program; -import net.vulkanmod.gl.GlUtil; -import net.vulkanmod.vulkan.shader.SPIRVUtils; -import org.apache.commons.io.IOUtils; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; - -@Mixin(Program.class) -public class ProgramM { - - /** - * @author - * @reason - */ - @Overwrite - public static int compileShaderInternal(Program.Type type, String string, InputStream inputStream, String string2, GlslPreprocessor glslPreprocessor) throws IOException { - String string3 = IOUtils.toString(inputStream, StandardCharsets.UTF_8); - if (string3 == null) { - throw new IOException("Could not load program " + type.getName()); - } else { -// int i = GlStateManager.glCreateShader(type.getGlType()); -// GlStateManager.glShaderSource(i, glslPreprocessor.process(string3)); -// GlStateManager.glCompileShader(i); -// if (GlStateManager.glGetShaderi(i, 35713) == 0) { -// String string4 = StringUtils.trim(GlStateManager.glGetShaderInfoLog(i, 32768)); -// throw new IOException("Couldn't compile " + type.getName() + " program (" + string2 + ", " + string + ") : " + string4); -// } else { -// return i; -// } - - //TODO maybe not needed? - glslPreprocessor.process(string3); - SPIRVUtils.compileShader(string2 + ":" + string, string3, GlUtil.extToShaderKind(type.getExtension())); - } - return 0; - } -} diff --git a/src/main/java/net/vulkanmod/mixin/compatibility/UniformM.java b/src/main/java/net/vulkanmod/mixin/compatibility/UniformM.java deleted file mode 100644 index 75c2985cd..000000000 --- a/src/main/java/net/vulkanmod/mixin/compatibility/UniformM.java +++ /dev/null @@ -1,42 +0,0 @@ -package net.vulkanmod.mixin.compatibility; - -import com.mojang.blaze3d.shaders.Uniform; -import com.mojang.blaze3d.systems.RenderSystem; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(Uniform.class) -public class UniformM { - - /** - * @author - * @reason - */ - @Overwrite - public static int glGetUniformLocation(int i, CharSequence charSequence) { - //TODO - return 1; - } - - /** - * @author - * @reason - */ - @Overwrite - public static int glGetAttribLocation(int i, CharSequence charSequence) { - return 0; - } - - @Inject(method = "upload", at = @At("HEAD"), cancellable = true) - public void cancelUpload(CallbackInfo ci) { - ci.cancel(); - } - - @Inject(method = "uploadInteger", at = @At("HEAD"), cancellable = true) - private static void cancelUploadInteger(int i, int j, CallbackInfo ci) { - ci.cancel(); - } -} diff --git a/src/main/java/net/vulkanmod/mixin/compatibility/gl/GL11M.java b/src/main/java/net/vulkanmod/mixin/compatibility/gl/GL11M.java index 3328002fc..33c7cbbb2 100644 --- a/src/main/java/net/vulkanmod/mixin/compatibility/gl/GL11M.java +++ b/src/main/java/net/vulkanmod/mixin/compatibility/gl/GL11M.java @@ -1,15 +1,14 @@ package net.vulkanmod.mixin.compatibility.gl; -import net.vulkanmod.gl.GlTexture; +import net.vulkanmod.gl.VkGlTexture; +import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.VRenderSystem; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11C; import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.NativeType; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; import org.jetbrains.annotations.Nullable; import java.nio.ByteBuffer; @@ -24,6 +23,16 @@ public class GL11M { */ @Overwrite(remap = false) public static void glScissor(@NativeType("GLint") int x, @NativeType("GLint") int y, @NativeType("GLsizei") int width, @NativeType("GLsizei") int height) { + Renderer.setScissor(x, y, width, height); + } + + /** + * @author + * @reason + */ + @Overwrite(remap = false) + public static void glViewport(@NativeType("GLint") int x, @NativeType("GLint") int y, @NativeType("GLsizei") int w, @NativeType("GLsizei") int h) { + Renderer.setViewport(x, y, w, h); } /** @@ -32,7 +41,7 @@ public static void glScissor(@NativeType("GLint") int x, @NativeType("GLint") in */ @Overwrite(remap = false) public static void glBindTexture(@NativeType("GLenum") int target, @NativeType("GLuint") int texture) { - GlTexture.bindTexture(texture); + VkGlTexture.bindTexture(texture); } /** @@ -51,7 +60,7 @@ public static void glLineWidth(@NativeType("GLfloat") float width) { @NativeType("void") @Overwrite(remap = false) public static int glGenTextures() { - return GlTexture.genTextureId(); + return VkGlTexture.genTextureId(); } /** @@ -61,7 +70,7 @@ public static int glGenTextures() { @NativeType("GLboolean") @Overwrite(remap = false) public static boolean glIsEnabled(@NativeType("GLenum") int cap) { - return false; + return true; } /** @@ -92,6 +101,20 @@ public static void glClearColor(@NativeType("GLfloat") float red, @NativeType("G VRenderSystem.setClearColor(red, green, blue, alpha); } + @Overwrite(remap = false) + public static void glDepthFunc(@NativeType("GLenum") int func) { + VRenderSystem.depthFunc(func); + } + + /** + * @author + * @reason + */ + @Overwrite(remap = false) + public static void glClearDepth(@NativeType("GLdouble") double depth) { + VRenderSystem.clearDepth(depth); + } + /** * @author * @reason @@ -117,7 +140,7 @@ public static int glGetInteger(@NativeType("GLenum") int pname) { */ @Overwrite(remap = false) public static void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, @Nullable ByteBuffer pixels) { - GlTexture.texImage2D(target, level, internalformat, width, height, border, format, type, pixels); + VkGlTexture.texImage2D(target, level, internalformat, width, height, border, format, type, pixels); } /** @@ -126,7 +149,7 @@ public static void glTexImage2D(int target, int level, int internalformat, int w */ @Overwrite(remap = false) public static void glTexImage2D(@NativeType("GLenum") int target, @NativeType("GLint") int level, @NativeType("GLint") int internalformat, @NativeType("GLsizei") int width, @NativeType("GLsizei") int height, @NativeType("GLint") int border, @NativeType("GLenum") int format, @NativeType("GLenum") int type, @NativeType("void const *") long pixels) { - GlTexture.texImage2D(target, level, internalformat, width, height, border, format, type, pixels); + VkGlTexture.texImage2D(target, level, internalformat, width, height, border, format, type, pixels); } /** @@ -135,7 +158,7 @@ public static void glTexImage2D(@NativeType("GLenum") int target, @NativeType("G */ @Overwrite(remap = false) public static void glTexSubImage2D(int target, int level, int xOffset, int yOffset, int width, int height, int format, int type, long pixels) { - GlTexture.texSubImage2D(target, level, xOffset, yOffset, width, height, format, type, pixels); + VkGlTexture.texSubImage2D(target, level, xOffset, yOffset, width, height, format, type, pixels); } /** @@ -144,7 +167,7 @@ public static void glTexSubImage2D(int target, int level, int xOffset, int yOffs */ @Overwrite(remap = false) public static void glTexSubImage2D(int target, int level, int xOffset, int yOffset, int width, int height, int format, int type, @Nullable ByteBuffer pixels) { - GlTexture.texSubImage2D(target, level, xOffset, yOffset, width, height, format, type, pixels); + VkGlTexture.texSubImage2D(target, level, xOffset, yOffset, width, height, format, type, pixels); } /** @@ -153,7 +176,7 @@ public static void glTexSubImage2D(int target, int level, int xOffset, int yOffs */ @Overwrite(remap = false) public static void glTexSubImage2D(int target, int level, int xOffset, int yOffset, int width, int height, int format, int type, @Nullable IntBuffer pixels) { - GlTexture.texSubImage2D(target, level, xOffset, yOffset, width, height, format, type, MemoryUtil.memByteBuffer(pixels)); + VkGlTexture.texSubImage2D(target, level, xOffset, yOffset, width, height, format, type, MemoryUtil.memByteBuffer(pixels)); } /** @@ -162,7 +185,7 @@ public static void glTexSubImage2D(int target, int level, int xOffset, int yOffs */ @Overwrite(remap = false) public static void glTexParameteri(@NativeType("GLenum") int target, @NativeType("GLenum") int pname, @NativeType("GLint") int param) { - GlTexture.texParameteri(target, pname, param); + VkGlTexture.texParameteri(target, pname, param); } /** @@ -174,13 +197,31 @@ public static void glTexParameterf(@NativeType("GLenum") int target, @NativeType } + /** + * @author + * @reason + */ + @Overwrite(remap = false) + public static int glGetTexParameteri(@NativeType("GLenum") int target, @NativeType("GLenum") int pname) { + return VkGlTexture.getTexParameteri(target, pname); + } + /** * @author * @reason */ @Overwrite(remap = false) public static int glGetTexLevelParameteri(@NativeType("GLenum") int target, @NativeType("GLint") int level, @NativeType("GLenum") int pname) { - return GlTexture.getTexLevelParameter(target, level, pname); + return VkGlTexture.getTexLevelParameter(target, level, pname); + } + + /** + * @author + * @reason + */ + @Overwrite(remap = false) + public static void glPixelStorei(@NativeType("GLenum") int pname, @NativeType("GLint") int param) { + VkGlTexture.pixelStoreI(pname, param); } /** @@ -222,7 +263,7 @@ public static void glHint(@NativeType("GLenum") int target, @NativeType("GLenum" */ @Overwrite(remap = false) public static void glDeleteTextures(@NativeType("GLuint const *") int texture) { - GlTexture.glDeleteTextures(texture); + VkGlTexture.glDeleteTextures(texture); } /** @@ -231,7 +272,7 @@ public static void glDeleteTextures(@NativeType("GLuint const *") int texture) { */ @Overwrite(remap = false) public static void glDeleteTextures(@NativeType("GLuint const *") IntBuffer textures) { - GlTexture.glDeleteTextures(textures); + VkGlTexture.glDeleteTextures(textures); } /** @@ -240,7 +281,7 @@ public static void glDeleteTextures(@NativeType("GLuint const *") IntBuffer text */ @Overwrite(remap = false) public static void glGetTexImage(@NativeType("GLenum") int tex, @NativeType("GLint") int level, @NativeType("GLenum") int format, @NativeType("GLenum") int type, @NativeType("void *") long pixels) { - GlTexture.getTexImage(tex, level, format, type, pixels); + VkGlTexture.getTexImage(tex, level, format, type, pixels); } /** @@ -249,7 +290,7 @@ public static void glGetTexImage(@NativeType("GLenum") int tex, @NativeType("GLi */ @Overwrite(remap = false) public static void glGetTexImage(@NativeType("GLenum") int tex, @NativeType("GLint") int level, @NativeType("GLenum") int format, @NativeType("GLenum") int type, @NativeType("void *") ByteBuffer pixels) { - GlTexture.getTexImage(tex, level, format, type, MemoryUtil.memAddress(pixels)); + VkGlTexture.getTexImage(tex, level, format, type, MemoryUtil.memAddress(pixels)); } /** @@ -258,7 +299,7 @@ public static void glGetTexImage(@NativeType("GLenum") int tex, @NativeType("GLi */ @Overwrite(remap = false) public static void glGetTexImage(@NativeType("GLenum") int tex, @NativeType("GLint") int level, @NativeType("GLenum") int format, @NativeType("GLenum") int type, @NativeType("void *") IntBuffer pixels) { - GlTexture.getTexImage(tex, level, format, type, MemoryUtil.memAddress(pixels)); + VkGlTexture.getTexImage(tex, level, format, type, MemoryUtil.memAddress(pixels)); } /** @@ -269,4 +310,24 @@ public static void glGetTexImage(@NativeType("GLenum") int tex, @NativeType("GLi public static void glCopyTexSubImage2D(@NativeType("GLenum") int target, @NativeType("GLint") int level, @NativeType("GLint") int xoffset, @NativeType("GLint") int yoffset, @NativeType("GLint") int x, @NativeType("GLint") int y, @NativeType("GLsizei") int width, @NativeType("GLsizei") int height) { // TODO } + + /** + * @author + * @reason + */ + @Overwrite(remap = false) + public static void glBlendFunc(@NativeType("GLenum") int sfactor, @NativeType("GLenum") int dfactor) { + // TODO + } + + + + /** + * @author + * @reason + */ + @Overwrite(remap = false) + public static void glPolygonOffset(@NativeType("GLfloat") float factor, @NativeType("GLfloat") float units) { + VRenderSystem.polygonOffset(factor, units); + } } diff --git a/src/main/java/net/vulkanmod/mixin/compatibility/gl/GL15M.java b/src/main/java/net/vulkanmod/mixin/compatibility/gl/GL15M.java index 6c6353496..65cc49840 100644 --- a/src/main/java/net/vulkanmod/mixin/compatibility/gl/GL15M.java +++ b/src/main/java/net/vulkanmod/mixin/compatibility/gl/GL15M.java @@ -1,6 +1,6 @@ package net.vulkanmod.mixin.compatibility.gl; -import net.vulkanmod.gl.GlBuffer; +import net.vulkanmod.gl.VkGlBuffer; import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL15; import org.lwjgl.system.NativeType; @@ -19,7 +19,7 @@ public class GL15M { @Overwrite(remap = false) @NativeType("void") public static int glGenBuffers() { - return GlBuffer.glGenBuffers(); + return VkGlBuffer.glGenBuffers(); } /** @@ -27,7 +27,7 @@ public static int glGenBuffers() { */ @Overwrite(remap = false) public static void glBindBuffer(@NativeType("GLenum") int target, @NativeType("GLuint") int buffer) { - GlBuffer.glBindBuffer(target, buffer); + VkGlBuffer.glBindBuffer(target, buffer); } /** @@ -35,7 +35,7 @@ public static void glBindBuffer(@NativeType("GLenum") int target, @NativeType("G */ @Overwrite(remap = false) public static void glBufferData(@NativeType("GLenum") int target, @NativeType("void const *") ByteBuffer data, @NativeType("GLenum") int usage) { - GlBuffer.glBufferData(target, data, usage); + VkGlBuffer.glBufferData(target, data, usage); } /** @@ -43,7 +43,7 @@ public static void glBufferData(@NativeType("GLenum") int target, @NativeType("v */ @Overwrite(remap = false) public static void glBufferData(int i, long l, int j) { - GlBuffer.glBufferData(i, l, j); + VkGlBuffer.glBufferData(i, l, j); } /** @@ -52,7 +52,7 @@ public static void glBufferData(int i, long l, int j) { @Overwrite(remap = false) @NativeType("void *") public static ByteBuffer glMapBuffer(@NativeType("GLenum") int target, @NativeType("GLenum") int access) { - return GlBuffer.glMapBuffer(target, access); + return VkGlBuffer.glMapBuffer(target, access); } /** @@ -62,7 +62,7 @@ public static ByteBuffer glMapBuffer(@NativeType("GLenum") int target, @NativeTy @Nullable @NativeType("void *") public static ByteBuffer glMapBuffer(@NativeType("GLenum") int target, @NativeType("GLenum") int access, long length, @Nullable ByteBuffer old_buffer) { - return GlBuffer.glMapBuffer(target, access); + return VkGlBuffer.glMapBuffer(target, access); } /** @@ -71,7 +71,7 @@ public static ByteBuffer glMapBuffer(@NativeType("GLenum") int target, @NativeTy @Overwrite(remap = false) @NativeType("GLboolean") public static boolean glUnmapBuffer(@NativeType("GLenum") int target) { - return GlBuffer.glUnmapBuffer(target); + return VkGlBuffer.glUnmapBuffer(target); } /** @@ -79,7 +79,7 @@ public static boolean glUnmapBuffer(@NativeType("GLenum") int target) { */ @Overwrite(remap = false) public static void glDeleteBuffers(int i) { - GlBuffer.glDeleteBuffers(i); + VkGlBuffer.glDeleteBuffers(i); } /** @@ -87,6 +87,6 @@ public static void glDeleteBuffers(int i) { */ @Overwrite(remap = false) public static void glDeleteBuffers(@NativeType("GLuint const *") IntBuffer buffers) { - GlBuffer.glDeleteBuffers(buffers); + VkGlBuffer.glDeleteBuffers(buffers); } } diff --git a/src/main/java/net/vulkanmod/mixin/compatibility/gl/GL30M.java b/src/main/java/net/vulkanmod/mixin/compatibility/gl/GL30M.java index 1a34e6bb9..0823849ec 100644 --- a/src/main/java/net/vulkanmod/mixin/compatibility/gl/GL30M.java +++ b/src/main/java/net/vulkanmod/mixin/compatibility/gl/GL30M.java @@ -1,8 +1,8 @@ package net.vulkanmod.mixin.compatibility.gl; -import net.vulkanmod.gl.GlFramebuffer; -import net.vulkanmod.gl.GlRenderbuffer; -import net.vulkanmod.gl.GlTexture; +import net.vulkanmod.gl.VkGlFramebuffer; +import net.vulkanmod.gl.VkGlRenderbuffer; +import net.vulkanmod.gl.VkGlTexture; import org.lwjgl.opengl.GL30; import org.lwjgl.system.NativeType; import org.spongepowered.asm.mixin.Mixin; @@ -17,7 +17,7 @@ public class GL30M { */ @Overwrite(remap = false) public static void glGenerateMipmap(@NativeType("GLenum") int target) { - GlTexture.generateMipmap(target); + VkGlTexture.generateMipmap(target); } /** @@ -27,7 +27,7 @@ public static void glGenerateMipmap(@NativeType("GLenum") int target) { @NativeType("void") @Overwrite(remap = false) public static int glGenFramebuffers() { - return GlFramebuffer.genFramebufferId(); + return VkGlFramebuffer.genFramebufferId(); } /** @@ -36,7 +36,7 @@ public static int glGenFramebuffers() { */ @Overwrite(remap = false) public static void glBindFramebuffer(@NativeType("GLenum") int target, @NativeType("GLuint") int framebuffer) { - GlFramebuffer.bindFramebuffer(target, framebuffer); + VkGlFramebuffer.bindFramebuffer(target, framebuffer); } /** @@ -45,7 +45,7 @@ public static void glBindFramebuffer(@NativeType("GLenum") int target, @NativeTy */ @Overwrite(remap = false) public static void glFramebufferTexture2D(@NativeType("GLenum") int target, @NativeType("GLenum") int attachment, @NativeType("GLenum") int textarget, @NativeType("GLuint") int texture, @NativeType("GLint") int level) { - GlFramebuffer.framebufferTexture2D(target, attachment, textarget, texture, level); + VkGlFramebuffer.framebufferTexture2D(target, attachment, textarget, texture, level); } /** @@ -63,7 +63,7 @@ public static void glFramebufferRenderbuffer(@NativeType("GLenum") int target, @ */ @Overwrite(remap = false) public static void glDeleteFramebuffers(@NativeType("GLuint const *") int framebuffer) { - GlFramebuffer.deleteFramebuffer(framebuffer); + VkGlFramebuffer.deleteFramebuffer(framebuffer); } /** @@ -73,7 +73,16 @@ public static void glDeleteFramebuffers(@NativeType("GLuint const *") int frameb @Overwrite(remap = false) @NativeType("GLenum") public static int glCheckFramebufferStatus(@NativeType("GLenum") int target) { - return GlFramebuffer.glCheckFramebufferStatus(target); + return VkGlFramebuffer.glCheckFramebufferStatus(target); + } + + /** + * @author + * @reason + */ + @Overwrite(remap = false) + public static void glBlitFramebuffer(@NativeType("GLint") int srcX0, @NativeType("GLint") int srcY0, @NativeType("GLint") int srcX1, @NativeType("GLint") int srcY1, @NativeType("GLint") int dstX0, @NativeType("GLint") int dstY0, @NativeType("GLint") int dstX1, @NativeType("GLint") int dstY1, @NativeType("GLbitfield") int mask, @NativeType("GLenum") int filter) { + VkGlFramebuffer.glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); } //RENDER BUFFER @@ -85,7 +94,7 @@ public static int glCheckFramebufferStatus(@NativeType("GLenum") int target) { @NativeType("void") @Overwrite(remap = false) public static int glGenRenderbuffers() { - return GlRenderbuffer.genId(); + return VkGlRenderbuffer.genId(); } /** @@ -94,7 +103,7 @@ public static int glGenRenderbuffers() { */ @Overwrite(remap = false) public static void glBindRenderbuffer(@NativeType("GLenum") int target, @NativeType("GLuint") int framebuffer) { - GlRenderbuffer.bindRenderbuffer(target, framebuffer); + VkGlRenderbuffer.bindRenderbuffer(target, framebuffer); } /** @@ -103,7 +112,7 @@ public static void glBindRenderbuffer(@NativeType("GLenum") int target, @NativeT */ @Overwrite(remap = false) public static void glRenderbufferStorage(@NativeType("GLenum") int target, @NativeType("GLenum") int internalformat, @NativeType("GLsizei") int width, @NativeType("GLsizei") int height) { - GlRenderbuffer.renderbufferStorage(target, internalformat, width, height); + VkGlRenderbuffer.renderbufferStorage(target, internalformat, width, height); } /** @@ -112,6 +121,6 @@ public static void glRenderbufferStorage(@NativeType("GLenum") int target, @Nati */ @Overwrite(remap = false) public static void glDeleteRenderbuffers(@NativeType("GLuint const *") int renderbuffer) { - GlRenderbuffer.deleteRenderbuffer(renderbuffer); + VkGlRenderbuffer.deleteRenderbuffer(renderbuffer); } } diff --git a/src/main/java/net/vulkanmod/mixin/debug/DebugEntryMemoryM.java b/src/main/java/net/vulkanmod/mixin/debug/DebugEntryMemoryM.java new file mode 100644 index 000000000..cd6e90fd6 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/debug/DebugEntryMemoryM.java @@ -0,0 +1,55 @@ +package net.vulkanmod.mixin.debug; + +import net.minecraft.client.gui.components.debug.DebugEntryMemory; +import net.minecraft.client.gui.components.debug.DebugScreenDisplayer; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.chunk.LevelChunk; +import net.vulkanmod.vulkan.memory.MemoryManager; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +import java.lang.management.ManagementFactory; +import java.util.List; +import java.util.Locale; + +@Mixin(DebugEntryMemory.class) +public abstract class DebugEntryMemoryM { + + @Shadow @Final private static ResourceLocation GROUP; + + @Shadow + protected static long bytesToMegabytes(long l) { + return 0; + } + + // TODO +// @Shadow @Final private DebugEntryMemory.AllocationRateCalculator allocationRateCalculator; + + @Overwrite + public void display(DebugScreenDisplayer debugScreenDisplayer, @Nullable Level level, @Nullable LevelChunk levelChunk, @Nullable LevelChunk levelChunk2) { + long l = Runtime.getRuntime().maxMemory(); + long m = Runtime.getRuntime().totalMemory(); + long n = Runtime.getRuntime().freeMemory(); + long o = m - n; + debugScreenDisplayer.addToGroup( + GROUP, + List.of( + String.format(Locale.ROOT, "Mem: %2d%% %03d/%03dMB", o * 100L / l, bytesToMegabytes(o), bytesToMegabytes(l)), +// String.format(Locale.ROOT, "Allocation rate: %03dMB/s", bytesToMegabytes(this.allocationRateCalculator.bytesAllocatedPerSecond(o))), + String.format(Locale.ROOT, "Allocated: %2d%% %03dMB", m * 100L / l, bytesToMegabytes(m)), + String.format("Off-heap: " + getOffHeapMemory() + "MB"), + "NativeMemory: %dMB".formatted(MemoryManager.getInstance().getNativeMemoryMB()), + "DeviceMemory: %dMB".formatted(MemoryManager.getInstance().getAllocatedDeviceMemoryMB()) + ) + ); + + } + + private long getOffHeapMemory() { + return bytesToMegabytes(ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getUsed()); + } +} diff --git a/src/main/java/net/vulkanmod/mixin/debug/DebugEntrySystemSpecsM.java b/src/main/java/net/vulkanmod/mixin/debug/DebugEntrySystemSpecsM.java new file mode 100644 index 000000000..2c8d18ebf --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/debug/DebugEntrySystemSpecsM.java @@ -0,0 +1,49 @@ +package net.vulkanmod.mixin.debug; + +import com.mojang.blaze3d.platform.GLX; +import com.mojang.blaze3d.systems.GpuDevice; +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.components.debug.DebugEntrySystemSpecs; +import net.minecraft.client.gui.components.debug.DebugScreenDisplayer; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.chunk.LevelChunk; +import net.vulkanmod.Initializer; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; +import java.util.Locale; + +@Mixin(DebugEntrySystemSpecs.class) +public class DebugEntrySystemSpecsM { + + @Shadow @Final private static ResourceLocation GROUP; + + @Inject(method = "display", at = @At("HEAD"), cancellable = true) + private void display(DebugScreenDisplayer debugScreenDisplayer, Level level, LevelChunk levelChunk, + LevelChunk levelChunk2, CallbackInfo ci) { + GpuDevice gpuDevice = RenderSystem.getDevice(); + debugScreenDisplayer.addToGroup( + GROUP, + List.of( + String.format(Locale.ROOT, "Java: %s", System.getProperty("java.version")), + String.format(Locale.ROOT, "CPU: %s", GLX._getCpuInfo()), + String.format( + Locale.ROOT, "Display: %dx%d (%s)", Minecraft.getInstance().getWindow().getWidth(), Minecraft.getInstance().getWindow().getHeight(), gpuDevice.getVendor() + ), + gpuDevice.getRenderer(), + String.format(Locale.ROOT, "%s %s", gpuDevice.getBackendName(), gpuDevice.getVersion()), + String.format(Locale.ROOT, "VulkanMod %s", Initializer.getVersion()) + ) + ); + + ci.cancel(); + } + +} diff --git a/src/main/java/net/vulkanmod/mixin/debug/DebugScreenEntriesM.java b/src/main/java/net/vulkanmod/mixin/debug/DebugScreenEntriesM.java new file mode 100644 index 000000000..1f0843edd --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/debug/DebugScreenEntriesM.java @@ -0,0 +1,25 @@ +package net.vulkanmod.mixin.debug; + +import net.minecraft.client.gui.components.debug.DebugScreenEntries; +import net.minecraft.client.gui.components.debug.DebugScreenEntry; +import net.minecraft.resources.ResourceLocation; +import net.vulkanmod.render.profiling.DebugEntryMemoryStats; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(DebugScreenEntries.class) +public abstract class DebugScreenEntriesM { + + @Shadow + public static ResourceLocation register(ResourceLocation resourceLocation, DebugScreenEntry debugScreenEntry) { + return null; + } + + @Inject(method = "", at = @At("RETURN")) + private static void addEntry(CallbackInfo ci) { + register(ResourceLocation.fromNamespaceAndPath("vkmod","stats"), new DebugEntryMemoryStats()); + } +} diff --git a/src/main/java/net/vulkanmod/mixin/debug/DebugScreenOverlayM.java b/src/main/java/net/vulkanmod/mixin/debug/DebugScreenOverlayM.java deleted file mode 100644 index da44e8b84..000000000 --- a/src/main/java/net/vulkanmod/mixin/debug/DebugScreenOverlayM.java +++ /dev/null @@ -1,80 +0,0 @@ -package net.vulkanmod.mixin.debug; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.components.DebugScreenOverlay; -import net.vulkanmod.render.chunk.WorldRenderer; -import net.vulkanmod.vulkan.SystemInfo; -import net.vulkanmod.vulkan.Vulkan; -import net.vulkanmod.vulkan.device.Device; -import net.vulkanmod.vulkan.memory.MemoryManager; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -import java.lang.management.ManagementFactory; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import static net.vulkanmod.Initializer.getVersion; - -@Mixin(DebugScreenOverlay.class) -public abstract class DebugScreenOverlayM { - - @Shadow - @Final - private Minecraft minecraft; - - @Shadow - private static long bytesToMegabytes(long bytes) { - return 0; - } - - @Shadow - @Final - private Font font; - - @Shadow - protected abstract List getGameInformation(); - - @Shadow - protected abstract List getSystemInformation(); - - @Redirect(method = "getSystemInformation", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/Lists;newArrayList([Ljava/lang/Object;)Ljava/util/ArrayList;")) - private ArrayList redirectList(Object[] elements) { - ArrayList strings = new ArrayList<>(); - - long maxMemory = Runtime.getRuntime().maxMemory(); - long totalMemory = Runtime.getRuntime().totalMemory(); - long freeMemory = Runtime.getRuntime().freeMemory(); - long usedMemory = totalMemory - freeMemory; - - Device device = Vulkan.getDevice(); - - strings.add(String.format("Java: %s", System.getProperty("java.version"))); - strings.add(String.format("Mem: % 2d%% %03d/%03dMB", usedMemory * 100L / maxMemory, bytesToMegabytes(usedMemory), bytesToMegabytes(maxMemory))); - strings.add(String.format("Allocated: % 2d%% %03dMB", totalMemory * 100L / maxMemory, bytesToMegabytes(totalMemory))); - strings.add(String.format("Off-heap: " + getOffHeapMemory() + "MB")); - strings.add("NativeMemory: %dMB".formatted(MemoryManager.getInstance().getNativeMemoryMB())); - strings.add("DeviceMemory: %dMB".formatted(MemoryManager.getInstance().getAllocatedDeviceMemoryMB())); - strings.add(""); - strings.add("VulkanMod " + getVersion()); - strings.add("CPU: " + SystemInfo.cpuInfo); - strings.add("GPU: " + device.deviceName); - strings.add("Driver: " + device.driverVersion); - strings.add("Vulkan: " + device.vkVersion); - strings.add(""); - strings.add(""); - - Collections.addAll(strings, WorldRenderer.getInstance().getChunkAreaManager().getStats()); - - return strings; - } - - private long getOffHeapMemory() { - return bytesToMegabytes(ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getUsed()); - } -} diff --git a/src/main/java/net/vulkanmod/mixin/debug/GlDebugInfoM.java b/src/main/java/net/vulkanmod/mixin/debug/GlDebugInfoM.java deleted file mode 100644 index 10986a42a..000000000 --- a/src/main/java/net/vulkanmod/mixin/debug/GlDebugInfoM.java +++ /dev/null @@ -1,44 +0,0 @@ -package net.vulkanmod.mixin.debug; - -import com.mojang.blaze3d.platform.GlUtil; -import net.vulkanmod.vulkan.SystemInfo; -import net.vulkanmod.vulkan.Vulkan; -import net.vulkanmod.vulkan.device.Device; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -@Mixin(GlUtil.class) -public class GlDebugInfoM { - - /** - * @author - */ - @Overwrite - public static String getVendor() { - return Vulkan.getDevice() != null ? Vulkan.getDevice().vendorIdString : "n/a"; - } - - /** - * @author - */ - @Overwrite - public static String getRenderer() { - return Vulkan.getDevice() != null ? Vulkan.getDevice().deviceName : "n/a"; - } - - /** - * @author - */ - @Overwrite - public static String getOpenGLVersion() { - return Vulkan.getDevice() != null ? Vulkan.getDevice().driverVersion : "n/a"; - } - - /** - * @author - */ - @Overwrite - public static String getCpuInfo() { - return SystemInfo.cpuInfo; - } -} diff --git a/src/main/java/net/vulkanmod/mixin/debug/KeyboardHandlerM.java b/src/main/java/net/vulkanmod/mixin/debug/KeyboardHandlerM.java index 67330cece..e01a76c91 100644 --- a/src/main/java/net/vulkanmod/mixin/debug/KeyboardHandlerM.java +++ b/src/main/java/net/vulkanmod/mixin/debug/KeyboardHandlerM.java @@ -3,6 +3,7 @@ import com.mojang.blaze3d.platform.InputConstants; import net.minecraft.client.KeyboardHandler; import net.minecraft.client.Minecraft; +import net.minecraft.client.input.KeyEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -12,15 +13,15 @@ @Mixin(KeyboardHandler.class) public abstract class KeyboardHandlerM { - @Shadow protected abstract boolean handleChunkDebugKeys(int i); + @Shadow protected abstract boolean handleChunkDebugKeys(KeyEvent keyEvent); @Shadow private boolean handledDebugKey; - @Inject(method = "keyPress", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/InputConstants;isKeyDown(JI)Z", ordinal = 0, shift = At.Shift.AFTER)) - private void chunkDebug(long window, int key, int scancode, int action, int mods, CallbackInfo ci) { + @Inject(method = "keyPress", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/KeyMapping;set(Lcom/mojang/blaze3d/platform/InputConstants$Key;Z)V", ordinal = 1)) + private void chunkDebug(long l, int i, KeyEvent keyEvent, CallbackInfo ci) { // GLFW key 296 -> F7 // U -> Capture frustum - this.handledDebugKey |= InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 296) - && this.handleChunkDebugKeys(key); + this.handledDebugKey |= InputConstants.isKeyDown(Minecraft.getInstance().getWindow(), 296) + && this.handleChunkDebugKeys(keyEvent); } } diff --git a/src/main/java/net/vulkanmod/mixin/fix/MainMixin.java b/src/main/java/net/vulkanmod/mixin/fix/MainMixin.java new file mode 100644 index 000000000..97ccccdfe --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/fix/MainMixin.java @@ -0,0 +1,18 @@ +package net.vulkanmod.mixin.fix; + +import net.minecraft.client.main.Main; +import org.lwjgl.system.Configuration; +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(Main.class) +public class MainMixin { + + @Inject(method = "main", at=@At("HEAD")) + private static void inj1(String[] strings, CallbackInfo ci) { + // Increase stack size to 256 KB to prevent out of stack error on nvidia driver + Configuration.STACK_SIZE.set(256); + } +} diff --git a/src/main/java/net/vulkanmod/mixin/matrix/Matrix4fM.java b/src/main/java/net/vulkanmod/mixin/matrix/Matrix4fM.java index 071a62fd6..d39d9647b 100644 --- a/src/main/java/net/vulkanmod/mixin/matrix/Matrix4fM.java +++ b/src/main/java/net/vulkanmod/mixin/matrix/Matrix4fM.java @@ -10,6 +10,8 @@ public abstract class Matrix4fM { @Shadow public abstract Matrix4f perspective(float fovy, float aspect, float zNear, float zFar, boolean zZeroToOne); @Shadow public abstract Matrix4f ortho(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne); + @Shadow public abstract Matrix4f setPerspective(float fovy, float aspect, float zNear, float zFar, boolean zZeroToOne); + @Shadow public abstract Matrix4f setOrtho(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne); /** * @author @@ -17,7 +19,8 @@ public abstract class Matrix4fM { */ @Overwrite(remap = false) public Matrix4f setOrtho(float left, float right, float bottom, float top, float zNear, float zFar) { - return new Matrix4f().setOrtho(left, right, bottom, top, zNear, zFar, true); + this.setOrtho(left, right, bottom, top, zNear, zFar, true); + return (Matrix4f)(Object)this; } /** @@ -44,6 +47,7 @@ public Matrix4f perspective(float fovy, float aspect, float zNear, float zFar) { */ @Overwrite(remap = false) public Matrix4f setPerspective(float fovy, float aspect, float zNear, float zFar) { - return new Matrix4f().setPerspective(fovy, aspect, zNear, zFar, true); + this.setPerspective(fovy, aspect, zNear, zFar, true); + return (Matrix4f)(Object)this; } } diff --git a/src/main/java/net/vulkanmod/mixin/matrix/PoseAccessor.java b/src/main/java/net/vulkanmod/mixin/matrix/PoseAccessor.java new file mode 100644 index 000000000..cc2acf61a --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/matrix/PoseAccessor.java @@ -0,0 +1,12 @@ +package net.vulkanmod.mixin.matrix; + +import com.mojang.blaze3d.vertex.PoseStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(PoseStack.Pose.class) +public interface PoseAccessor { + + @Accessor("trustedNormals") + boolean trustedNormals(); +} diff --git a/src/main/java/net/vulkanmod/mixin/profiling/ClientMetricsSamplersProviderMixin.java b/src/main/java/net/vulkanmod/mixin/profiling/ClientMetricsSamplersProviderMixin.java new file mode 100644 index 000000000..d5067ecfa --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/profiling/ClientMetricsSamplersProviderMixin.java @@ -0,0 +1,19 @@ +// In a new file, e.g., ClientMetricsSamplersProviderMixin.java +package net.vulkanmod.mixin.profiling; // Or an appropriate package + +import com.mojang.blaze3d.systems.TimerQuery; +import net.minecraft.client.profiling.ClientMetricsSamplersProvider; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.Optional; + +@Mixin(ClientMetricsSamplersProvider.class) +public class ClientMetricsSamplersProviderMixin { + + @Redirect(method = "registerStaticSamplers", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/TimerQuery;getInstance()Ljava/util/Optional;")) + private Optional preventTimerQuery() { + return Optional.empty(); + } +} \ No newline at end of file diff --git a/src/main/java/net/vulkanmod/mixin/profiling/GameLoadTimeEventM.java b/src/main/java/net/vulkanmod/mixin/profiling/GameLoadTimeEventM.java new file mode 100644 index 000000000..985d36d76 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/profiling/GameLoadTimeEventM.java @@ -0,0 +1,86 @@ +package net.vulkanmod.mixin.profiling; + +import com.google.common.base.Stopwatch; +import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; +import net.minecraft.client.telemetry.TelemetryEventSender; +import net.minecraft.client.telemetry.TelemetryEventType; +import net.minecraft.client.telemetry.TelemetryProperty; +import net.minecraft.client.telemetry.TelemetryPropertyMap; +import net.minecraft.client.telemetry.events.GameLoadTimesEvent; +import org.slf4j.Logger; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Map; +import java.util.OptionalLong; +import java.util.concurrent.TimeUnit; + +@Mixin(GameLoadTimesEvent.class) +public class GameLoadTimeEventM { + + @Shadow @Final private Map, Stopwatch> measurements; + + @Shadow @Final private static Logger LOGGER; + + @Shadow private OptionalLong bootstrapTime; + + public void send(TelemetryEventSender telemetryEventSender) { + Map measurements = new Reference2ReferenceOpenHashMap<>(); + + synchronized (this) { + this.measurements + .forEach( + (telemetryProperty, stopwatch) -> { + if (!stopwatch.isRunning()) { + long l = stopwatch.elapsed(TimeUnit.MILLISECONDS); + measurements.put(telemetryProperty, new GameLoadTimesEvent.Measurement((int)l)); + } else { + LOGGER.warn( + "Measurement {} was discarded since it was still ongoing when the event {} was sent.", + telemetryProperty.id(), + TelemetryEventType.GAME_LOAD_TIMES.id() + ); + } + } + ); + this.bootstrapTime.ifPresent(l -> measurements.put(TelemetryProperty.LOAD_TIME_BOOTSTRAP_MS, new GameLoadTimesEvent.Measurement((int)l))); + this.measurements.clear(); + } + + StringBuilder stringBuilder = new StringBuilder("\n"); + + for (TelemetryProperty property : measurements.keySet()) { + var measurement = measurements.get(property); + + stringBuilder.append("%s: %sms\n".formatted(property.id(), measurement.millis())); + } + + LOGGER.info(stringBuilder.toString()); + +// telemetryEventSender.send( +// TelemetryEventType.GAME_LOAD_TIMES, +// builder -> { +// synchronized (this) { +// this.measurements +// .forEach( +// (telemetryProperty, stopwatch) -> { +// if (!stopwatch.isRunning()) { +// long l = stopwatch.elapsed(TimeUnit.MILLISECONDS); +// builder.put(telemetryProperty, new GameLoadTimesEvent.Measurement((int)l)); +// } else { +// LOGGER.warn( +// "Measurement {} was discarded since it was still ongoing when the event {} was sent.", +// telemetryProperty.id(), +// TelemetryEventType.GAME_LOAD_TIMES.id() +// ); +// } +// } +// ); +// this.bootstrapTime.ifPresent(l -> builder.put(TelemetryProperty.LOAD_TIME_BOOTSTRAP_MS, new GameLoadTimesEvent.Measurement((int)l))); +// this.measurements.clear(); +// } +// } +// ); + } +} diff --git a/src/main/java/net/vulkanmod/mixin/profiling/GuiMixin.java b/src/main/java/net/vulkanmod/mixin/profiling/GuiMixin.java index 1fd1ede71..26563f60a 100644 --- a/src/main/java/net/vulkanmod/mixin/profiling/GuiMixin.java +++ b/src/main/java/net/vulkanmod/mixin/profiling/GuiMixin.java @@ -26,7 +26,7 @@ private void createProfilerOverlay(Minecraft minecraft, CallbackInfo ci) { @Inject(method = "render", at = @At(value = "RETURN")) private void renderProfilerOverlay(GuiGraphics guiGraphics, DeltaTracker deltaTracker, CallbackInfo ci) { - if(ProfilerOverlay.shouldRender && !this.debugOverlay.showDebugScreen()) + if (ProfilerOverlay.shouldRender && !this.debugOverlay.showDebugScreen()) ProfilerOverlay.INSTANCE.render(guiGraphics); } } diff --git a/src/main/java/net/vulkanmod/mixin/profiling/KeyboardHandlerM.java b/src/main/java/net/vulkanmod/mixin/profiling/KeyboardHandlerM.java index 242ce3060..467ec1a73 100644 --- a/src/main/java/net/vulkanmod/mixin/profiling/KeyboardHandlerM.java +++ b/src/main/java/net/vulkanmod/mixin/profiling/KeyboardHandlerM.java @@ -3,6 +3,7 @@ import com.mojang.blaze3d.platform.InputConstants; import net.minecraft.client.KeyboardHandler; import net.minecraft.client.Minecraft; +import net.minecraft.client.input.KeyEvent; import net.vulkanmod.render.profiling.BuildTimeProfiler; import net.vulkanmod.render.profiling.ProfilerOverlay; import org.lwjgl.glfw.GLFW; @@ -16,16 +17,16 @@ public class KeyboardHandlerM { @Inject(method = "keyPress", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/KeyMapping;set(Lcom/mojang/blaze3d/platform/InputConstants$Key;Z)V", - ordinal = 0, shift = At.Shift.AFTER)) - private void injOverlayToggle(long window, int key, int scancode, int action, int mods, CallbackInfo ci) { - if(InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), GLFW.GLFW_KEY_LEFT_ALT)) { - switch (key) { + ordinal = 1, shift = At.Shift.AFTER)) + private void injOverlayToggle(long l, int i, KeyEvent keyEvent, CallbackInfo ci) { + if (InputConstants.isKeyDown(Minecraft.getInstance().getWindow(), GLFW.GLFW_KEY_LEFT_ALT)) { + switch (keyEvent.key()) { case GLFW.GLFW_KEY_F8 -> ProfilerOverlay.toggle(); case GLFW.GLFW_KEY_F10 -> BuildTimeProfiler.startBench(); } } - else if(ProfilerOverlay.shouldRender) { - ProfilerOverlay.onKeyPress(key); + else if (ProfilerOverlay.shouldRender) { + ProfilerOverlay.onKeyPress(keyEvent.key()); } } } diff --git a/src/main/java/net/vulkanmod/mixin/profiling/LevelRendererMixin.java b/src/main/java/net/vulkanmod/mixin/profiling/LevelRendererMixin.java index d1b69098c..b0061a261 100644 --- a/src/main/java/net/vulkanmod/mixin/profiling/LevelRendererMixin.java +++ b/src/main/java/net/vulkanmod/mixin/profiling/LevelRendererMixin.java @@ -1,11 +1,15 @@ package net.vulkanmod.mixin.profiling; -import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.buffers.GpuBufferSlice; +import com.mojang.blaze3d.resource.ResourceHandle; import net.minecraft.client.Camera; +import net.minecraft.client.CloudStatus; import net.minecraft.client.DeltaTracker; -import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.LevelRenderer; -import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.culling.Frustum; +import net.minecraft.client.renderer.state.LevelRenderState; +import net.minecraft.util.profiling.ProfilerFiller; +import net.minecraft.world.phys.Vec3; import net.vulkanmod.render.profiling.Profiler; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Mixin; @@ -16,88 +20,44 @@ @Mixin(LevelRenderer.class) public class LevelRendererMixin { - @Inject(method = "renderClouds", at = @At("HEAD")) - private void pushProfiler(PoseStack poseStack, Matrix4f matrix4f, Matrix4f matrix4f2, float f, double d, double e, double g, CallbackInfo ci) { + @Inject(method = "method_62205", at = @At("HEAD")) + private void pushProfiler(int i, CloudStatus cloudStatus, float f, Vec3 vec3, float g, CallbackInfo ci) { Profiler profiler = Profiler.getMainProfiler(); profiler.push("Clouds"); } - @Inject(method = "renderClouds", at = @At("RETURN")) - private void popProfiler(PoseStack poseStack, Matrix4f matrix4f, Matrix4f matrix4f2, float f, double d, double e, double g, CallbackInfo ci) { + @Inject(method = "method_62205", at = @At("RETURN")) + private void popProfiler(int i, CloudStatus cloudStatus, float f, Vec3 vec3, float g, CallbackInfo ci) { Profiler profiler = Profiler.getMainProfiler(); profiler.pop(); } - @Inject(method = "renderLevel", at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/particle/ParticleEngine;render(Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;F)V", - shift = At.Shift.BEFORE)) - private void pushProfiler3(DeltaTracker deltaTracker, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, Matrix4f matrix4f2, CallbackInfo ci) { + // TODO: fix + @Inject(method = "method_62213", at = @At(value = "HEAD")) + private void pushProfiler3(GpuBufferSlice gpuBufferSlice, ResourceHandle resourceHandle, + ResourceHandle resourceHandle2, CallbackInfo ci) { Profiler profiler = Profiler.getMainProfiler(); profiler.push("Particles"); } - @Inject(method = "renderLevel", at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/particle/ParticleEngine;render(Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;F)V", - shift = At.Shift.AFTER)) - private void popProfiler3(DeltaTracker deltaTracker, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, Matrix4f matrix4f2, CallbackInfo ci) { + @Inject(method = "method_62213", at = @At(value = "RETURN")) + private void popProfiler3(GpuBufferSlice gpuBufferSlice, ResourceHandle resourceHandle, + ResourceHandle resourceHandle2, CallbackInfo ci) { Profiler profiler = Profiler.getMainProfiler(); profiler.pop(); } - @Inject(method = "renderLevel", at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/renderer/LevelRenderer;renderSectionLayer(Lnet/minecraft/client/renderer/RenderType;DDDLorg/joml/Matrix4f;Lorg/joml/Matrix4f;)V", - ordinal = 0, - shift = At.Shift.BEFORE)) - private void profilerTerrain1(DeltaTracker deltaTracker, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, Matrix4f matrix4f2, CallbackInfo ci) { - Profiler profiler = Profiler.getMainProfiler(); - profiler.push("Opaque_terrain"); - } - - @Inject(method = "renderLevel", at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/renderer/LevelRenderer;renderSectionLayer(Lnet/minecraft/client/renderer/RenderType;DDDLorg/joml/Matrix4f;Lorg/joml/Matrix4f;)V", - ordinal = 2, - shift = At.Shift.BEFORE)) - private void profilerTerrain2(DeltaTracker deltaTracker, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, Matrix4f matrix4f2, CallbackInfo ci) { + @Inject(method = "method_62214", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/renderer/LevelRenderer;submitEntities(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/state/LevelRenderState;Lnet/minecraft/client/renderer/SubmitNodeCollector;)V")) + private void profilerTerrain2(GpuBufferSlice gpuBufferSlice, LevelRenderState levelRenderState, + ProfilerFiller profilerFiller, Matrix4f matrix4f, ResourceHandle resourceHandle, + ResourceHandle resourceHandle2, boolean bl, Frustum frustum, + ResourceHandle resourceHandle3, ResourceHandle resourceHandle4, CallbackInfo ci) { Profiler profiler = Profiler.getMainProfiler(); profiler.pop(); profiler.push("entities"); } - @Inject(method = "renderLevel", at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/renderer/LevelRenderer;renderSectionLayer(Lnet/minecraft/client/renderer/RenderType;DDDLorg/joml/Matrix4f;Lorg/joml/Matrix4f;)V", - ordinal = 3, - shift = At.Shift.BEFORE)) - private void profilerTerrain3_0(DeltaTracker deltaTracker, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, Matrix4f matrix4f2, CallbackInfo ci) { - Profiler profiler = Profiler.getMainProfiler(); - profiler.pop(); - profiler.push("Translucent_terrain"); - } - @Inject(method = "renderLevel", at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/renderer/LevelRenderer;renderSectionLayer(Lnet/minecraft/client/renderer/RenderType;DDDLorg/joml/Matrix4f;Lorg/joml/Matrix4f;)V", - ordinal = 5, - shift = At.Shift.BEFORE)) - private void profilerTerrain3_1(DeltaTracker deltaTracker, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, Matrix4f matrix4f2, CallbackInfo ci) { - Profiler profiler = Profiler.getMainProfiler(); - profiler.pop(); - profiler.push("Translucent_terrain"); - } - - @Inject(method = "renderLevel", at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/renderer/LevelRenderer;renderSectionLayer(Lnet/minecraft/client/renderer/RenderType;DDDLorg/joml/Matrix4f;Lorg/joml/Matrix4f;)V", - ordinal = 4, - shift = At.Shift.BEFORE)) - private void profilerTerrain4_0(DeltaTracker deltaTracker, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, Matrix4f matrix4f2, CallbackInfo ci) { - Profiler profiler = Profiler.getMainProfiler(); - profiler.pop(); - } - - @Inject(method = "renderLevel", at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/renderer/LevelRenderer;renderSectionLayer(Lnet/minecraft/client/renderer/RenderType;DDDLorg/joml/Matrix4f;Lorg/joml/Matrix4f;)V", - ordinal = 6, - shift = At.Shift.BEFORE)) - private void profilerTerrain4_1(DeltaTracker deltaTracker, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, Matrix4f matrix4f2, CallbackInfo ci) { - Profiler profiler = Profiler.getMainProfiler(); - profiler.pop(); - } } diff --git a/src/main/java/net/vulkanmod/mixin/profiling/TimerQueryM.java b/src/main/java/net/vulkanmod/mixin/profiling/TimerQueryM.java new file mode 100644 index 000000000..71836fd9f --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/profiling/TimerQueryM.java @@ -0,0 +1,18 @@ +package net.vulkanmod.mixin.profiling; + +import com.mojang.blaze3d.systems.TimerQuery; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; + +@Mixin(TimerQuery.class) +public class TimerQueryM { + + @Overwrite + public void beginProfile() { + } + + @Overwrite + public TimerQuery.FrameProfile endProfile() { + return null; + } +} diff --git a/src/main/java/net/vulkanmod/mixin/render/BufferUploaderM.java b/src/main/java/net/vulkanmod/mixin/render/BufferUploaderM.java deleted file mode 100644 index 232c0a436..000000000 --- a/src/main/java/net/vulkanmod/mixin/render/BufferUploaderM.java +++ /dev/null @@ -1,83 +0,0 @@ -package net.vulkanmod.mixin.render; - -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.BufferUploader; -import com.mojang.blaze3d.vertex.MeshData; -import net.minecraft.client.renderer.ShaderInstance; -import net.vulkanmod.interfaces.ShaderMixed; -import net.vulkanmod.vulkan.Renderer; -import net.vulkanmod.vulkan.VRenderSystem; -import net.vulkanmod.vulkan.shader.GraphicsPipeline; - -import net.vulkanmod.vulkan.shader.Pipeline; -import net.vulkanmod.vulkan.texture.VTextureSelector; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -@Mixin(BufferUploader.class) -public class BufferUploaderM { - - /** - * @author - */ - @Overwrite - public static void reset() {} - - /** - * @author - */ - @Overwrite - public static void drawWithShader(MeshData meshData) { - RenderSystem.assertOnRenderThread(); - - MeshData.DrawState parameters = meshData.drawState(); - - Renderer renderer = Renderer.getInstance(); - - if (parameters.vertexCount() > 0) { - ShaderInstance shaderInstance = RenderSystem.getShader(); - - // Prevent drawing if formats don't match to avoid disturbing visual bugs - if (shaderInstance.getVertexFormat() != parameters.format()) { - meshData.close(); - return; - } - - // Used to update legacy shader uniforms - // TODO it would be faster to allocate a buffer from stack and set all values - shaderInstance.apply(); - - GraphicsPipeline pipeline = ((ShaderMixed)(shaderInstance)).getPipeline(); - - if (pipeline == null) - throw new NullPointerException("Shader %s has no initialized pipeline".formatted(shaderInstance.getName())); - - VRenderSystem.setPrimitiveTopologyGL(parameters.mode().asGLMode); - renderer.bindGraphicsPipeline(pipeline); - VTextureSelector.bindShaderTextures(pipeline); - renderer.uploadAndBindUBOs(pipeline); - Renderer.getDrawer().draw(meshData.vertexBuffer(), parameters.mode(), parameters.format(), parameters.vertexCount()); - } - - meshData.close(); - } - - /** - * @author - */ - @Overwrite - public static void draw(MeshData meshData) { - MeshData.DrawState parameters = meshData.drawState(); - - if (parameters.vertexCount() > 0) { - Renderer renderer = Renderer.getInstance(); - Pipeline pipeline = renderer.getBoundPipeline(); - renderer.uploadAndBindUBOs(pipeline); - - Renderer.getDrawer().draw(meshData.vertexBuffer(), parameters.mode(), parameters.format(), parameters.vertexCount()); - } - - meshData.close(); - } - -} diff --git a/src/main/java/net/vulkanmod/mixin/render/CompositeRenderTypeM.java b/src/main/java/net/vulkanmod/mixin/render/CompositeRenderTypeM.java new file mode 100644 index 000000000..060e440b6 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/CompositeRenderTypeM.java @@ -0,0 +1,127 @@ +package net.vulkanmod.mixin.render; + +import com.mojang.blaze3d.buffers.GpuBuffer; +import com.mojang.blaze3d.buffers.GpuBufferSlice; +import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.blaze3d.pipeline.RenderTarget; +import com.mojang.blaze3d.systems.RenderPass; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.systems.ScissorState; +import com.mojang.blaze3d.textures.GpuTextureView; +import com.mojang.blaze3d.vertex.MeshData; +import com.mojang.blaze3d.vertex.VertexFormat; +import net.minecraft.client.renderer.RenderType; +import net.vulkanmod.render.engine.*; +import net.vulkanmod.vulkan.Renderer; +import net.vulkanmod.vulkan.VRenderSystem; +import net.vulkanmod.vulkan.texture.VTextureSelector; +import org.joml.Vector3f; +import org.joml.Vector4f; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.OptionalDouble; +import java.util.OptionalInt; + +@Mixin(RenderType.CompositeRenderType.class) +public abstract class CompositeRenderTypeM { + + @Shadow @Final private RenderType.CompositeState state; + @Shadow @Final private RenderPipeline renderPipeline; + + // TODO + /** + * @author + * @reason + */ + @Overwrite + public void draw(MeshData meshData) { + ((RenderType.CompositeRenderType)(Object)(this)).setupRenderState(); + GpuBufferSlice gpuBufferSlice = RenderSystem.getDynamicUniforms() + .writeTransform( + RenderSystem.getModelViewMatrix(), + new Vector4f(1.0F, 1.0F, 1.0F, 1.0F), + new Vector3f(), + RenderSystem.getTextureMatrix(), + RenderSystem.getShaderLineWidth() + ); + MeshData var3 = meshData; + + try { + GpuBuffer gpuBuffer = this.renderPipeline.getVertexFormat().uploadImmediateVertexBuffer(meshData.vertexBuffer()); + GpuBuffer gpuBuffer2; + VertexFormat.IndexType indexType; + if (meshData.indexBuffer() == null) { + RenderSystem.AutoStorageIndexBuffer autoStorageIndexBuffer = RenderSystem.getSequentialBuffer(meshData.drawState().mode()); + gpuBuffer2 = autoStorageIndexBuffer.getBuffer(meshData.drawState().indexCount()); + indexType = autoStorageIndexBuffer.type(); + } else { + gpuBuffer2 = this.renderPipeline.getVertexFormat().uploadImmediateIndexBuffer(meshData.indexBuffer()); + indexType = meshData.drawState().indexType(); + } + + RenderTarget renderTarget = ((CompositeStateAccessor)(Object)this.state).getOutputState().getRenderTarget(); + GpuTextureView gpuTextureView = RenderSystem.outputColorTextureOverride != null + ? RenderSystem.outputColorTextureOverride + : renderTarget.getColorTextureView(); + GpuTextureView gpuTextureView2 = renderTarget.useDepth + ? (RenderSystem.outputDepthTextureOverride != null ? RenderSystem.outputDepthTextureOverride : renderTarget.getDepthTextureView()) + : null; + + try (RenderPass renderPass = RenderSystem.getDevice() + .createCommandEncoder() + .createRenderPass(() -> "Immediate draw for " + + ((RenderType.CompositeRenderType) (Object) (this)).getName(), + gpuTextureView, OptionalInt.empty(), gpuTextureView2, OptionalDouble.empty())) { + renderPass.setPipeline(this.renderPipeline); + ScissorState scissorState = RenderSystem.getScissorStateForRenderTypeDraws(); + if (scissorState.enabled()) { + renderPass.enableScissor(scissorState.x(), scissorState.y(), scissorState.width(), scissorState.height()); + } + + RenderSystem.bindDefaultUniforms(renderPass); + renderPass.setUniform("DynamicTransforms", gpuBufferSlice); + renderPass.setVertexBuffer(0, gpuBuffer); + + for (int i = 0; i < 12; i++) { + GpuTextureView gpuTextureView3 = RenderSystem.getShaderTexture(i); + if (gpuTextureView3 != null) { + renderPass.bindSampler("Sampler" + i, gpuTextureView3); + + VkGpuTexture vkGpuTexture = (VkGpuTexture) gpuTextureView3.texture(); + VTextureSelector.bindTexture(i, vkGpuTexture.getVulkanImage()); + } + } + + VRenderSystem.applyModelViewMatrix(RenderSystem.getModelViewMatrix()); + VRenderSystem.calculateMVP(); + + renderPass.setIndexBuffer(gpuBuffer2, indexType); + + VkCommandEncoder commandEncoder = (VkCommandEncoder) RenderSystem.getDevice().createCommandEncoder(); + commandEncoder.trySetup((VkRenderPass) renderPass); + + Renderer.getDrawer().draw(meshData.vertexBuffer(), meshData.indexBuffer(), meshData.drawState().mode(), meshData.drawState().format(), meshData.drawState().vertexCount()); + } + } catch (Throwable var17) { + if (meshData != null) { + try { + var3.close(); + } catch (Throwable var14) { + var17.addSuppressed(var14); + } + } + + throw var17; + } + + if (meshData != null) { + meshData.close(); + } + + ((RenderType.CompositeRenderType)(Object)(this)).clearRenderState(); + } + +} diff --git a/src/main/java/net/vulkanmod/mixin/render/CompositeStateAccessor.java b/src/main/java/net/vulkanmod/mixin/render/CompositeStateAccessor.java new file mode 100644 index 000000000..1f3abc805 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/CompositeStateAccessor.java @@ -0,0 +1,23 @@ +package net.vulkanmod.mixin.render; + +import com.google.common.collect.ImmutableList; +import net.minecraft.client.renderer.RenderStateShard; +import net.minecraft.client.renderer.RenderType; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(RenderType.CompositeState.class) +public interface CompositeStateAccessor { + + @Accessor("textureState") + RenderStateShard.EmptyTextureStateShard getTextureState(); + + @Accessor("outputState") + RenderStateShard.OutputStateShard getOutputState(); + + @Accessor("outlineProperty") + RenderType.OutlineProperty getOutlineProperty(); + + @Accessor("states") + ImmutableList getStates(); +} diff --git a/src/main/java/net/vulkanmod/mixin/render/FogRendererMixin.java b/src/main/java/net/vulkanmod/mixin/render/FogRendererMixin.java new file mode 100644 index 000000000..d8fb71eb8 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/FogRendererMixin.java @@ -0,0 +1,26 @@ +package net.vulkanmod.mixin.render; + +import com.llamalad7.mixinextras.sugar.Local; +import net.minecraft.client.Camera; +import net.minecraft.client.DeltaTracker; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.fog.FogData; +import net.minecraft.client.renderer.fog.FogRenderer; +import net.vulkanmod.vulkan.VRenderSystem; +import org.joml.Vector4f; +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.CallbackInfoReturnable; + +@Mixin(FogRenderer.class) +public class FogRendererMixin { + + @Inject(method = "setupFog", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Mth;clamp(FFF)F")) + private void onSetupFog(Camera camera, int i, boolean bl, DeltaTracker deltaTracker, float f, + ClientLevel clientLevel, CallbackInfoReturnable cir, + @Local FogData fogData, @Local Vector4f fogColor) { + VRenderSystem.fogData = fogData; + VRenderSystem.setShaderFogColor(fogColor.x(), fogColor.y(), fogColor.z(), fogColor.w()); + } +} diff --git a/src/main/java/net/vulkanmod/mixin/render/GameRendererMixin.java b/src/main/java/net/vulkanmod/mixin/render/GameRendererMixin.java index 63cc0fa94..b9c09713d 100644 --- a/src/main/java/net/vulkanmod/mixin/render/GameRendererMixin.java +++ b/src/main/java/net/vulkanmod/mixin/render/GameRendererMixin.java @@ -1,365 +1,12 @@ package net.vulkanmod.mixin.render; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import com.mojang.blaze3d.shaders.Program; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.DefaultVertexFormat; -import com.mojang.blaze3d.vertex.VertexFormat; -import com.mojang.datafixers.util.Pair; -import net.fabricmc.fabric.api.client.rendering.v1.CoreShaderRegistrationCallback; -import net.fabricmc.fabric.impl.client.rendering.FabricShaderProgram; import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.renderer.ShaderInstance; -import net.minecraft.server.packs.resources.ResourceProvider; -import net.vulkanmod.vulkan.memory.MemoryManager; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; @Mixin(GameRenderer.class) public abstract class GameRendererMixin { - @Shadow @Final private Map shaders; - - @Shadow private @Nullable static ShaderInstance positionShader; - @Shadow private @Nullable static ShaderInstance positionColorShader; - @Shadow private @Nullable static ShaderInstance positionTexShader; - @Shadow private @Nullable static ShaderInstance positionTexColorShader; - @Shadow private @Nullable static ShaderInstance particleShader; - @Shadow private @Nullable static ShaderInstance rendertypeSolidShader; - @Shadow private @Nullable static ShaderInstance rendertypeCutoutMippedShader; - @Shadow private @Nullable static ShaderInstance rendertypeCutoutShader; - @Shadow private @Nullable static ShaderInstance rendertypeTranslucentShader; - @Shadow private @Nullable static ShaderInstance rendertypeTranslucentMovingBlockShader; - @Shadow private @Nullable static ShaderInstance rendertypeArmorCutoutNoCullShader; - @Shadow private @Nullable static ShaderInstance rendertypeEntitySolidShader; - @Shadow private @Nullable static ShaderInstance rendertypeEntityCutoutShader; - @Shadow private @Nullable static ShaderInstance rendertypeEntityCutoutNoCullShader; - @Shadow private @Nullable static ShaderInstance rendertypeEntityCutoutNoCullZOffsetShader; - @Shadow private @Nullable static ShaderInstance rendertypeItemEntityTranslucentCullShader; - @Shadow private @Nullable static ShaderInstance rendertypeEntityTranslucentCullShader; - @Shadow private @Nullable static ShaderInstance rendertypeEntityTranslucentShader; - @Shadow private @Nullable static ShaderInstance rendertypeEntityTranslucentEmissiveShader; - @Shadow private @Nullable static ShaderInstance rendertypeEntitySmoothCutoutShader; - @Shadow private @Nullable static ShaderInstance rendertypeBeaconBeamShader; - @Shadow private @Nullable static ShaderInstance rendertypeEntityDecalShader; - @Shadow private @Nullable static ShaderInstance rendertypeEntityNoOutlineShader; - @Shadow private @Nullable static ShaderInstance rendertypeEntityShadowShader; - @Shadow private @Nullable static ShaderInstance rendertypeEntityAlphaShader; - @Shadow private @Nullable static ShaderInstance rendertypeEyesShader; - @Shadow private @Nullable static ShaderInstance rendertypeEnergySwirlShader; - @Shadow private @Nullable static ShaderInstance rendertypeLeashShader; - @Shadow private @Nullable static ShaderInstance rendertypeWaterMaskShader; - @Shadow private @Nullable static ShaderInstance rendertypeOutlineShader; - @Shadow private @Nullable static ShaderInstance rendertypeArmorGlintShader; - @Shadow private @Nullable static ShaderInstance rendertypeArmorEntityGlintShader; - @Shadow private @Nullable static ShaderInstance rendertypeGlintTranslucentShader; - @Shadow private @Nullable static ShaderInstance rendertypeGlintShader; - @Shadow private @Nullable static ShaderInstance rendertypeGlintDirectShader; - @Shadow private @Nullable static ShaderInstance rendertypeEntityGlintShader; - @Shadow private @Nullable static ShaderInstance rendertypeEntityGlintDirectShader; - @Shadow private @Nullable static ShaderInstance rendertypeTextShader; - @Shadow private @Nullable static ShaderInstance rendertypeTextIntensityShader; - @Shadow private @Nullable static ShaderInstance rendertypeTextSeeThroughShader; - @Shadow private @Nullable static ShaderInstance rendertypeTextIntensitySeeThroughShader; - @Shadow private @Nullable static ShaderInstance rendertypeLightningShader; - @Shadow private @Nullable static ShaderInstance rendertypeTripwireShader; - @Shadow private @Nullable static ShaderInstance rendertypeEndPortalShader; - @Shadow private @Nullable static ShaderInstance rendertypeEndGatewayShader; - @Shadow private @Nullable static ShaderInstance rendertypeLinesShader; - @Shadow private @Nullable static ShaderInstance rendertypeCrumblingShader; - @Shadow private static @Nullable ShaderInstance rendertypeBreezeWindShader; - @Shadow private static @Nullable ShaderInstance rendertypeCloudsShader; - - @Shadow private static @Nullable ShaderInstance rendertypeTextBackgroundShader; - @Shadow private static @Nullable ShaderInstance rendertypeTextBackgroundSeeThroughShader; - @Shadow private static @Nullable ShaderInstance rendertypeGuiShader; - @Shadow private static @Nullable ShaderInstance rendertypeGuiOverlayShader; - @Shadow private static @Nullable ShaderInstance rendertypeGuiTextHighlightShader; - @Shadow private static @Nullable ShaderInstance rendertypeGuiGhostRecipeOverlayShader; - - @Shadow private @Nullable static ShaderInstance positionColorLightmapShader; - @Shadow private @Nullable static ShaderInstance positionColorTexLightmapShader; - - @Shadow public ShaderInstance blitShader; - - @Shadow protected abstract ShaderInstance preloadShader(ResourceProvider resourceProvider, String string, VertexFormat vertexFormat); - - @Shadow public abstract float getRenderDistance(); - - @Shadow protected abstract void loadBlurEffect(ResourceProvider resourceProvider); - - @Inject(method = "reloadShaders", at = @At("HEAD"), cancellable = true) - public void reloadShaders(ResourceProvider provider, CallbackInfo ci) { - RenderSystem.assertOnRenderThread(); - - List>> pairs = Lists.newArrayListWithCapacity(this.shaders.size()); - - try { - pairs.add( - Pair.of(new ShaderInstance(provider, "particle", DefaultVertexFormat.PARTICLE), - (shaderInstance) -> particleShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "position", DefaultVertexFormat.POSITION), - (shaderInstance) -> positionShader = shaderInstance)); - - ShaderInstance positionColor = new ShaderInstance(provider, "position_color", DefaultVertexFormat.POSITION_COLOR); - pairs.add( - Pair.of( - positionColor, - (shaderInstance) -> positionColorShader = shaderInstance)); - - // These aren't used -// pairs.add( -// Pair.of(new ShaderInstance(provider, "position_color_lightmap", DefaultVertexFormat.POSITION_COLOR_LIGHTMAP), -// (shaderInstance) -> positionColorLightmapShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "position_color_tex_lightmap", DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP), - (shaderInstance) -> positionColorTexLightmapShader = shaderInstance)); - - pairs.add( - Pair.of(new ShaderInstance(provider, "position_tex", DefaultVertexFormat.POSITION_TEX), - (shaderInstance) -> positionTexShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "position_tex_color", DefaultVertexFormat.POSITION_TEX_COLOR), - (shaderInstance) -> positionTexColorShader = shaderInstance)); -// pairs.add( -// Pair.of(new ShaderInstance(provider, "position_tex_lightmap_color", DefaultVertexFormat.POSITION_TEX_LIGHTMAP_COLOR), -// (shaderInstance) -> positionTexLightmapColorShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_solid", DefaultVertexFormat.BLOCK), - (shaderInstance) -> rendertypeSolidShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_cutout_mipped", DefaultVertexFormat.BLOCK), - (shaderInstance) -> rendertypeCutoutMippedShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_cutout", DefaultVertexFormat.BLOCK), - (shaderInstance) -> rendertypeCutoutShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_translucent", DefaultVertexFormat.BLOCK), - (shaderInstance) -> rendertypeTranslucentShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_translucent_moving_block", DefaultVertexFormat.BLOCK), - (shaderInstance) -> rendertypeTranslucentMovingBlockShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_armor_cutout_no_cull", DefaultVertexFormat.NEW_ENTITY), - (shaderInstance) -> rendertypeArmorCutoutNoCullShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_entity_solid", DefaultVertexFormat.NEW_ENTITY), - (shaderInstance) -> rendertypeEntitySolidShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_entity_cutout", DefaultVertexFormat.NEW_ENTITY), - (shaderInstance) -> rendertypeEntityCutoutShader = shaderInstance)); - - // No diff in these shaders - ShaderInstance entity_no_cull = new ShaderInstance(provider, "rendertype_entity_cutout_no_cull", DefaultVertexFormat.NEW_ENTITY); - pairs.add( - Pair.of(entity_no_cull, - (shaderInstance) -> rendertypeEntityCutoutNoCullShader = shaderInstance)); - pairs.add( - Pair.of(entity_no_cull, - (shaderInstance) -> rendertypeEntityCutoutNoCullZOffsetShader = shaderInstance)); - - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_item_entity_translucent_cull", DefaultVertexFormat.NEW_ENTITY), - (shaderInstance) -> rendertypeItemEntityTranslucentCullShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_entity_translucent_cull", DefaultVertexFormat.NEW_ENTITY), - (shaderInstance) -> rendertypeEntityTranslucentCullShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_entity_translucent", DefaultVertexFormat.NEW_ENTITY), - (shaderInstance) -> rendertypeEntityTranslucentShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_entity_translucent_emissive", DefaultVertexFormat.NEW_ENTITY), - (shaderInstance) -> rendertypeEntityTranslucentEmissiveShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_entity_smooth_cutout", DefaultVertexFormat.NEW_ENTITY), - (shaderInstance) -> rendertypeEntitySmoothCutoutShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_beacon_beam", DefaultVertexFormat.BLOCK), - (shaderInstance) -> rendertypeBeaconBeamShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_entity_decal", DefaultVertexFormat.NEW_ENTITY), - (shaderInstance) -> rendertypeEntityDecalShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_entity_no_outline", DefaultVertexFormat.NEW_ENTITY), - (shaderInstance) -> rendertypeEntityNoOutlineShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_entity_shadow", DefaultVertexFormat.NEW_ENTITY), - (shaderInstance) -> rendertypeEntityShadowShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_entity_alpha", DefaultVertexFormat.NEW_ENTITY), - (shaderInstance) -> rendertypeEntityAlphaShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_eyes", DefaultVertexFormat.NEW_ENTITY), - (shaderInstance) -> rendertypeEyesShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_energy_swirl", DefaultVertexFormat.NEW_ENTITY), - (shaderInstance) -> rendertypeEnergySwirlShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_leash", DefaultVertexFormat.POSITION_COLOR_LIGHTMAP), - (shaderInstance) -> rendertypeLeashShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_water_mask", DefaultVertexFormat.POSITION), - (shaderInstance) -> rendertypeWaterMaskShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_outline", DefaultVertexFormat.POSITION_TEX_COLOR), - (shaderInstance) -> rendertypeOutlineShader = shaderInstance)); -// pairs.add(Pair.of(new ShaderInstance(provider, "rendertype_armor_glint", DefaultVertexFormat.POSITION_TEX), (shaderInstance) -> { -// rendertypeArmorGlintShader = shaderInstance; -// })); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_armor_entity_glint", DefaultVertexFormat.POSITION_TEX), - (shaderInstance) -> rendertypeArmorEntityGlintShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_glint_translucent", DefaultVertexFormat.POSITION_TEX), - (shaderInstance) -> rendertypeGlintTranslucentShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_glint", DefaultVertexFormat.POSITION_TEX), - (shaderInstance) -> rendertypeGlintShader = shaderInstance)); -// pairs.add(Pair.of(new ShaderInstance(provider, "rendertype_glint_direct", DefaultVertexFormat.POSITION_TEX), (shaderInstance) -> { -// rendertypeGlintDirectShader = shaderInstance; -// })); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_entity_glint", DefaultVertexFormat.POSITION_TEX), - (shaderInstance) -> rendertypeEntityGlintShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_entity_glint_direct", DefaultVertexFormat.POSITION_TEX), - (shaderInstance) -> rendertypeEntityGlintDirectShader = shaderInstance)); - - //Text - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_text", DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP), - (shaderInstance) -> rendertypeTextShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_text_background", DefaultVertexFormat.POSITION_COLOR_LIGHTMAP), - (shaderInstance) -> rendertypeTextBackgroundShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_text_intensity", DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP), - (shaderInstance) -> rendertypeTextIntensityShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_text_see_through", DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP), - (shaderInstance) -> rendertypeTextSeeThroughShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_text_background_see_through", DefaultVertexFormat.POSITION_COLOR_LIGHTMAP), - (shaderInstance) -> rendertypeTextBackgroundSeeThroughShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_text_intensity_see_through", DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP), - (shaderInstance) -> rendertypeTextIntensitySeeThroughShader = shaderInstance)); - - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_lightning", DefaultVertexFormat.POSITION_COLOR), - (shaderInstance) -> rendertypeLightningShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_tripwire", DefaultVertexFormat.BLOCK), - (shaderInstance) -> rendertypeTripwireShader = shaderInstance)); - ShaderInstance endPortalShader = new ShaderInstance(provider, "rendertype_end_portal", DefaultVertexFormat.POSITION); - pairs.add( - Pair.of(endPortalShader, - (shaderInstance) -> rendertypeEndPortalShader = shaderInstance)); - pairs.add( - Pair.of(endPortalShader, - (shaderInstance) -> rendertypeEndGatewayShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_clouds", DefaultVertexFormat.POSITION_TEX_COLOR_NORMAL), - (shaderInstance) -> rendertypeCloudsShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_lines", DefaultVertexFormat.POSITION_COLOR_NORMAL), - (shaderInstance) -> rendertypeLinesShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_crumbling", DefaultVertexFormat.BLOCK), - (shaderInstance) -> rendertypeCrumblingShader = shaderInstance)); - - pairs.add( - Pair.of(positionColor, - (shaderInstance) -> rendertypeGuiShader = shaderInstance)); - pairs.add( - Pair.of(positionColor, - (shaderInstance) -> rendertypeGuiOverlayShader = shaderInstance)); - pairs.add( - Pair.of(positionColor, - (shaderInstance) -> rendertypeGuiTextHighlightShader = shaderInstance)); - pairs.add( - Pair.of(positionColor, - (shaderInstance) -> rendertypeGuiGhostRecipeOverlayShader = shaderInstance)); - pairs.add( - Pair.of(new ShaderInstance(provider, "rendertype_energy_swirl", DefaultVertexFormat.NEW_ENTITY), - (shaderInstance) -> rendertypeBreezeWindShader = shaderInstance)); - - // FRAPI shader loading - CoreShaderRegistrationCallback.RegistrationContext context = (id, vertexFormat, loadCallback) -> { - ShaderInstance program = new FabricShaderProgram(provider, id, vertexFormat); - pairs.add(Pair.of(program, loadCallback)); - }; - CoreShaderRegistrationCallback.EVENT.invoker().registerShaders(context); - - this.loadBlurEffect(provider); - } catch (IOException ioexception) { - pairs.forEach((pair) -> pair.getFirst().close()); - throw new RuntimeException("could not reload shaders", ioexception); - } - - this.shutdownShaders(); - pairs.forEach((pair) -> { - ShaderInstance shaderinstance = pair.getFirst(); - this.shaders.put(shaderinstance.getName(), shaderinstance); - pair.getSecond().accept(shaderinstance); - }); - - ci.cancel(); - } - - /** - * @author - * @reason - */ - @Overwrite - private void shutdownShaders() { - RenderSystem.assertOnRenderThread(); - - final var clearList = ImmutableList.copyOf(this.shaders.values()); - MemoryManager.getInstance().addFrameOp(() -> clearList.forEach((ShaderInstance::close))); - - this.shaders.clear(); - } - - /** - * @author - * @reason - */ - @Overwrite - public void preloadUiShader(ResourceProvider resourceProvider) { - if (this.blitShader != null) { - throw new RuntimeException("Blit shader already preloaded"); - } else { - try { - this.blitShader = new ShaderInstance(resourceProvider, "blit_screen", DefaultVertexFormat.POSITION_TEX); - } catch (IOException var3) { - throw new RuntimeException("could not preload blit shader", var3); - } - - positionShader = this.preloadShader(resourceProvider, "position", DefaultVertexFormat.POSITION); - positionColorShader = this.preloadShader(resourceProvider, "position_color", DefaultVertexFormat.POSITION_COLOR); - positionTexShader = this.preloadShader(resourceProvider, "position_tex", DefaultVertexFormat.POSITION_TEX); - positionTexColorShader = this.preloadShader(resourceProvider, "position_tex_color", DefaultVertexFormat.POSITION_TEX_COLOR); - rendertypeTextShader = this.preloadShader(resourceProvider, "rendertype_text", DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP); - - rendertypeGuiShader = positionColorShader; - rendertypeGuiOverlayShader = positionColorShader; - } - } - /** * @author * @reason diff --git a/src/main/java/net/vulkanmod/mixin/render/GlProgramManagerMixin.java b/src/main/java/net/vulkanmod/mixin/render/GlProgramManagerMixin.java deleted file mode 100644 index 7c6fea9e8..000000000 --- a/src/main/java/net/vulkanmod/mixin/render/GlProgramManagerMixin.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.vulkanmod.mixin.render; - -import com.mojang.blaze3d.shaders.ProgramManager; -import com.mojang.blaze3d.shaders.Shader; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.io.IOException; - -@Mixin(ProgramManager.class) -public class GlProgramManagerMixin { - - @Inject(method = "createProgram", at = @At("HEAD"), cancellable = true) - private static void createProgram(CallbackInfoReturnable cir) throws IOException { - cir.setReturnValue(-1); - } - - @Inject(method = "linkShader", at = @At("HEAD"), cancellable = true) - private static void linkProgram(Shader shader, CallbackInfo ci) throws IOException { - ci.cancel(); - } -} diff --git a/src/main/java/net/vulkanmod/mixin/render/GlStateManagerM.java b/src/main/java/net/vulkanmod/mixin/render/GlStateManagerM.java index 59fcef1d3..3f17f536e 100644 --- a/src/main/java/net/vulkanmod/mixin/render/GlStateManagerM.java +++ b/src/main/java/net/vulkanmod/mixin/render/GlStateManagerM.java @@ -1,31 +1,34 @@ package net.vulkanmod.mixin.render; -import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.opengl.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; -import net.vulkanmod.gl.GlBuffer; -import net.vulkanmod.gl.GlFramebuffer; -import net.vulkanmod.gl.GlRenderbuffer; -import net.vulkanmod.gl.GlTexture; +import com.mojang.jtracy.Plot; +import net.vulkanmod.gl.*; import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.VRenderSystem; import org.jetbrains.annotations.Nullable; -import org.lwjgl.opengl.GL20; -import org.lwjgl.system.MemoryUtil; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.Shadow; import java.nio.ByteBuffer; -import java.nio.IntBuffer; @Mixin(GlStateManager.class) public class GlStateManagerM { + @Shadow @Final private static Plot PLOT_BUFFERS; + + @Shadow private static int numBuffers; + /** * @author */ @Overwrite(remap = false) public static void _bindTexture(int i) { - GlTexture.bindTexture(i); + VkGlTexture.bindTexture(i); } /** @@ -46,16 +49,6 @@ public static void _enableBlend() { VRenderSystem.enableBlend(); } - /** - * @author - */ - @Overwrite(remap = false) - public static void _blendFunc(int i, int j) { - RenderSystem.assertOnRenderThread(); - VRenderSystem.blendFunc(i, j); - - } - /** * @author */ @@ -99,8 +92,8 @@ public static void _disableCull() { /** * @author */ - @Overwrite(remap = false) - public static void _viewport(int x, int y, int width, int height) { + @Redirect(method = "_viewport", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glViewport(IIII)V"), remap = false) + private static void _viewport(int x, int y, int width, int height) { Renderer.setViewport(x, y, width, height); } @@ -125,8 +118,9 @@ public static int _getError() { * @author */ @Overwrite(remap = false) - public static void _texImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, @Nullable IntBuffer pixels) { - GlTexture.texImage2D(target, level, internalFormat, width, height, border, format, type, pixels != null ? MemoryUtil.memByteBuffer(pixels) : null); + public static void _texImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, @Nullable ByteBuffer pixels) { + RenderSystem.assertOnRenderThread(); + VkGlTexture.texImage2D(target, level, internalFormat, width, height, border, format, type, pixels); } /** @@ -134,7 +128,8 @@ public static void _texImage2D(int target, int level, int internalFormat, int wi */ @Overwrite(remap = false) public static void _texSubImage2D(int target, int level, int offsetX, int offsetY, int width, int height, int format, int type, long pixels) { - + RenderSystem.assertOnRenderThread(); + VkGlTexture.texSubImage2D(target, level, offsetX, offsetY, width, height, format, type, pixels); } /** @@ -142,7 +137,7 @@ public static void _texSubImage2D(int target, int level, int offsetX, int offset */ @Overwrite(remap = false) public static void _activeTexture(int i) { - GlTexture.activeTexture(i); + VkGlTexture.activeTexture(i); } /** @@ -150,15 +145,7 @@ public static void _activeTexture(int i) { */ @Overwrite(remap = false) public static void _texParameter(int i, int j, int k) { - GlTexture.texParameteri(i, j, k); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void _texParameter(int i, int j, float k) { - //TODO + VkGlTexture.texParameteri(i, j, k); } /** @@ -166,7 +153,7 @@ public static void _texParameter(int i, int j, float k) { */ @Overwrite(remap = false) public static int _getTexLevelParameter(int i, int j, int k) { - return GlTexture.getTexLevelParameter(i, j, k); + return VkGlTexture.getTexLevelParameter(i, j, k); } /** @@ -175,6 +162,8 @@ public static int _getTexLevelParameter(int i, int j, int k) { @Overwrite(remap = false) public static void _pixelStore(int pname, int param) { //Used during upload to set copy offsets + RenderSystem.assertOnRenderThread(); + VkGlTexture.pixelStoreI(pname, param); } /** @@ -182,8 +171,8 @@ public static void _pixelStore(int pname, int param) { */ @Overwrite(remap = false) public static int _genTexture() { - RenderSystem.assertOnRenderThreadOrInit(); - return GlTexture.genTextureId(); + RenderSystem.assertOnRenderThread(); + return VkGlTexture.genTextureId(); } /** @@ -191,8 +180,8 @@ public static int _genTexture() { */ @Overwrite(remap = false) public static void _deleteTexture(int i) { - RenderSystem.assertOnRenderThreadOrInit(); - GlTexture.glDeleteTextures(i); + RenderSystem.assertOnRenderThread(); + VkGlTexture.glDeleteTextures(i); } /** @@ -209,7 +198,7 @@ public static void _colorMask(boolean red, boolean green, boolean blue, boolean */ @Overwrite(remap = false) public static void _depthFunc(int i) { - RenderSystem.assertOnRenderThreadOrInit(); + RenderSystem.assertOnRenderThread(); VRenderSystem.depthFunc(i); } @@ -217,38 +206,80 @@ public static void _depthFunc(int i) { * @author */ @Overwrite(remap = false) - public static void _clearColor(float f, float g, float h, float i) { - RenderSystem.assertOnRenderThreadOrInit(); - VRenderSystem.setClearColor(f, g, h, i); + public static void _polygonMode(int face, int mode) { + RenderSystem.assertOnRenderThread(); + VRenderSystem.setPolygonModeGL(mode); + } + + /** + * @author + */ + @Overwrite(remap = false) + public static void _enablePolygonOffset() { + RenderSystem.assertOnRenderThread(); + VRenderSystem.enablePolygonOffset(); } /** * @author */ @Overwrite(remap = false) - public static void _clearDepth(double d) {} + public static void _disablePolygonOffset() { + RenderSystem.assertOnRenderThread(); + VRenderSystem.disablePolygonOffset(); + } /** * @author */ @Overwrite(remap = false) - public static void _clear(int mask, boolean bl) { - RenderSystem.assertOnRenderThreadOrInit(); - VRenderSystem.clear(mask); + public static void _polygonOffset(float f, float g) { + RenderSystem.assertOnRenderThread(); + VRenderSystem.polygonOffset(f, g); + } + + /** + * @author + */ + @Overwrite(remap = false) + public static void _enableColorLogicOp() { + RenderSystem.assertOnRenderThread(); + VRenderSystem.enableColorLogicOp(); } /** * @author */ @Overwrite(remap = false) - public static void _glUseProgram(int i) {} + public static void _disableColorLogicOp() { + RenderSystem.assertOnRenderThread(); + VRenderSystem.disableColorLogicOp(); + } + + /** + * @author + */ + @Overwrite(remap = false) + public static void _logicOp(int i) { + RenderSystem.assertOnRenderThread(); + VRenderSystem.logicOp(i); + } + + /** + * @author + */ + @Overwrite(remap = false) + public static void _clear(int mask) { + RenderSystem.assertOnRenderThread(); + VRenderSystem.clear(mask); + } /** * @author */ @Overwrite(remap = false) public static void _disableDepthTest() { - RenderSystem.assertOnRenderThreadOrInit(); + RenderSystem.assertOnRenderThread(); VRenderSystem.disableDepthTest(); } @@ -257,7 +288,7 @@ public static void _disableDepthTest() { */ @Overwrite(remap = false) public static void _enableDepthTest() { - RenderSystem.assertOnRenderThreadOrInit(); + RenderSystem.assertOnRenderThread(); VRenderSystem.enableDepthTest(); } @@ -276,140 +307,156 @@ public static void _depthMask(boolean bl) { */ @Overwrite(remap = false) public static int glGenFramebuffers() { - RenderSystem.assertOnRenderThreadOrInit(); - return GlFramebuffer.genFramebufferId(); + RenderSystem.assertOnRenderThread(); + return VkGlFramebuffer.genFramebufferId(); } /** * @author */ @Overwrite(remap = false) - public static int glGenRenderbuffers() { - RenderSystem.assertOnRenderThreadOrInit(); - return GlRenderbuffer.genId(); + public static void _glBindFramebuffer(int i, int j) { + RenderSystem.assertOnRenderThread(); + VkGlFramebuffer.bindFramebuffer(i, j); } /** * @author */ @Overwrite(remap = false) - public static void _glBindFramebuffer(int i, int j) { - RenderSystem.assertOnRenderThreadOrInit(); - GlFramebuffer.bindFramebuffer(i, j); + public static void _glFramebufferTexture2D(int i, int j, int k, int l, int m) { + RenderSystem.assertOnRenderThread(); + VkGlFramebuffer.framebufferTexture2D(i, j, k, l, m); } /** * @author */ @Overwrite(remap = false) - public static void _glFramebufferTexture2D(int i, int j, int k, int l, int m) { - RenderSystem.assertOnRenderThreadOrInit(); - GlFramebuffer.framebufferTexture2D(i, j, k, l, m); + public static int _glGenBuffers() { + RenderSystem.assertOnRenderThread(); + + numBuffers++; + PLOT_BUFFERS.setValue(numBuffers); + + return VkGlBuffer.glGenBuffers(); } /** * @author */ @Overwrite(remap = false) - public static void _glBindRenderbuffer(int i, int j) { - RenderSystem.assertOnRenderThreadOrInit(); - GlRenderbuffer.bindRenderbuffer(i, j); + public static void _glBindBuffer(int i, int j) { + RenderSystem.assertOnRenderThread(); + VkGlBuffer.glBindBuffer(i, j); } /** * @author */ @Overwrite(remap = false) - public static void _glFramebufferRenderbuffer(int i, int j, int k, int l) { - RenderSystem.assertOnRenderThreadOrInit(); - GlFramebuffer.framebufferRenderbuffer(i, j, k, l); + public static void _glBufferData(int i, ByteBuffer byteBuffer, int j) { + RenderSystem.assertOnRenderThread(); + VkGlBuffer.glBufferData(i, byteBuffer, j); } /** * @author */ @Overwrite(remap = false) - public static void _glRenderbufferStorage(int i, int j, int k, int l) { - RenderSystem.assertOnRenderThreadOrInit(); - GlRenderbuffer.renderbufferStorage(i, j, k, l); + public static void _glBufferData(int i, long l, int j) { + RenderSystem.assertOnRenderThread(); + VkGlBuffer.glBufferData(i, l, j); } /** * @author */ @Overwrite(remap = false) - public static int glCheckFramebufferStatus(int i) { - RenderSystem.assertOnRenderThreadOrInit(); - return GlFramebuffer.glCheckFramebufferStatus(i); + public static void _glUnmapBuffer(int i) { + RenderSystem.assertOnRenderThread(); + VkGlBuffer.glUnmapBuffer(i); } /** * @author */ @Overwrite(remap = false) - public static int _glGenBuffers() { - RenderSystem.assertOnRenderThreadOrInit(); - return GlBuffer.glGenBuffers(); + public static void _glDeleteBuffers(int i) { + RenderSystem.assertOnRenderThread(); + VkGlBuffer.glDeleteBuffers(i); } /** * @author */ @Overwrite(remap = false) - public static void _glBindBuffer(int i, int j) { - RenderSystem.assertOnRenderThreadOrInit(); - GlBuffer.glBindBuffer(i, j); + public static void glDeleteShader(int i) { + RenderSystem.assertOnRenderThread(); + VkGlShader.glDeleteShader(i); } /** * @author */ @Overwrite(remap = false) - public static void _glBufferData(int i, ByteBuffer byteBuffer, int j) { - RenderSystem.assertOnRenderThreadOrInit(); - GlBuffer.glBufferData(i, byteBuffer, j); + public static int glCreateShader(int i) { + RenderSystem.assertOnRenderThread(); + return VkGlShader.glCreateShader(i); } /** * @author */ @Overwrite(remap = false) - public static void _glBufferData(int i, long l, int j) { - RenderSystem.assertOnRenderThreadOrInit(); - GlBuffer.glBufferData(i, l, j); + public static void glShaderSource(int i, String string) { + RenderSystem.assertOnRenderThread(); + VkGlShader.glShaderSource(i, string); } /** * @author */ @Overwrite(remap = false) - @Nullable - public static ByteBuffer _glMapBuffer(int i, int j) { - RenderSystem.assertOnRenderThreadOrInit(); - return GlBuffer.glMapBuffer(i, j); + public static void glCompileShader(int i) { + RenderSystem.assertOnRenderThread(); + VkGlShader.glCompileShader(i); } /** * @author */ @Overwrite(remap = false) - public static void _glUnmapBuffer(int i) { - RenderSystem.assertOnRenderThreadOrInit(); - GlBuffer.glUnmapBuffer(i); + public static int glGetShaderi(int i, int j) { + RenderSystem.assertOnRenderThread(); + return VkGlShader.glGetShaderi(i, j); } /** * @author */ @Overwrite(remap = false) - public static void _glDeleteBuffers(int i) { - RenderSystem.assertOnRenderThread(); - GlBuffer.glDeleteBuffers(i); + public static void _glUseProgram(int i) { +// RenderSystem.assertOnRenderThread(); +// GL20.glUseProgram(i); + } + + /** + * @author + */ + @Overwrite(remap = false) + public static int glCreateProgram() { +// RenderSystem.assertOnRenderThread(); +// return GL20.glCreateProgram(); + return 0; } /** * @author */ @Overwrite(remap = false) - public static void _disableVertexAttribArray(int i) {} + public static void glDeleteProgram(int i) { +// RenderSystem.assertOnRenderThread(); +// GL20.glDeleteProgram(i); + } } diff --git a/src/main/java/net/vulkanmod/mixin/render/GuiRendererMixin.java b/src/main/java/net/vulkanmod/mixin/render/GuiRendererMixin.java new file mode 100644 index 000000000..09e25216e --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/GuiRendererMixin.java @@ -0,0 +1,74 @@ +package net.vulkanmod.mixin.render; + +import com.mojang.blaze3d.buffers.GpuBuffer; +import com.mojang.blaze3d.systems.RenderPass; +import com.mojang.blaze3d.textures.GpuTextureView; +import com.mojang.blaze3d.vertex.VertexFormat; +import net.minecraft.client.gui.render.GuiRenderer; +import net.minecraft.client.gui.render.TextureSetup; +import net.minecraft.client.gui.render.state.BlitRenderState; +import net.minecraft.client.gui.render.state.GuiItemRenderState; +import net.minecraft.client.gui.render.state.GuiRenderState; +import net.minecraft.client.renderer.RenderPipelines; +import net.vulkanmod.render.engine.VkRenderPass; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(GuiRenderer.class) +public abstract class GuiRendererMixin { + + @Shadow @Final private GuiRenderState renderState; + @Shadow private @Nullable GpuTextureView itemsAtlasView; + + @Overwrite + private void submitBlitFromItemAtlas(GuiItemRenderState guiItemRenderState, float u, float v, int size, int atlasSize) { + v = 1.0f - v; + float u1 = u + (float)size / atlasSize; + float v1 = v + (float)(size) / atlasSize; + this.renderState + .submitBlitToCurrentLayer( + new BlitRenderState( + RenderPipelines.GUI_TEXTURED_PREMULTIPLIED_ALPHA, + TextureSetup.singleTexture(this.itemsAtlasView), + guiItemRenderState.pose(), + guiItemRenderState.x(), + guiItemRenderState.y(), + guiItemRenderState.x() + 16, + guiItemRenderState.y() + 16, + u, + u1, + v, + v1, + -1, + guiItemRenderState.scissorArea(), + null + ) + ); + } + + @Redirect(method = "executeDraw", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderPass;setIndexBuffer(Lcom/mojang/blaze3d/buffers/GpuBuffer;Lcom/mojang/blaze3d/vertex/VertexFormat$IndexType;)V")) + private void removeIndexBuffer(RenderPass instance, GpuBuffer gpuBuffer, VertexFormat.IndexType indexType) { + // This draw method forces quad index buffer, not allowing other draw modes + // Not binding it here will allow for a proper index selection in lower level methods + } + + @Redirect(method = "executeDraw", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderPass;drawIndexed(IIII)V")) + private void useVertexCount(RenderPass renderPass, int baseVertex, int firstIndex, int indexCount, int instanceCount) { + // For the same reason here we need to use vertexCount instead of indexCount + + VkRenderPass vkRenderPass = (VkRenderPass) renderPass; + if (vkRenderPass.getPipeline().getVertexFormatMode() != VertexFormat.Mode.TRIANGLES) { + int vertexCount = indexCount * 2 / 3; + renderPass.drawIndexed(baseVertex, 0, vertexCount, 1); + } + else { + renderPass.drawIndexed(baseVertex, 0, indexCount, 1); + } + } + +} diff --git a/src/main/java/net/vulkanmod/mixin/render/LevelRendererMixin.java b/src/main/java/net/vulkanmod/mixin/render/LevelRendererMixin.java deleted file mode 100644 index f397ee81f..000000000 --- a/src/main/java/net/vulkanmod/mixin/render/LevelRendererMixin.java +++ /dev/null @@ -1,56 +0,0 @@ -package net.vulkanmod.mixin.render; - -import com.google.gson.JsonSyntaxException; -import com.mojang.blaze3d.pipeline.RenderTarget; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.LevelRenderer; -import net.minecraft.client.renderer.PostChain; -import net.minecraft.resources.ResourceLocation; -import org.jetbrains.annotations.Nullable; -import org.slf4j.Logger; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.Redirect; - -import java.io.IOException; - -@Mixin(LevelRenderer.class) -public abstract class LevelRendererMixin { - - @Shadow private @Nullable PostChain entityEffect; - - @Shadow @Final private Minecraft minecraft; - - @Shadow @Nullable private RenderTarget entityTarget; - - @Shadow @Final private static Logger LOGGER; - -// /** -// * @author -// */ -// @Overwrite -// public void initOutline() { -// if (this.entityEffect != null) { -// this.entityEffect.close(); -// } -// -//// ResourceLocation resourceLocation = new ResourceLocation("shaders/post/entity_outline.json"); -//// -//// try { -//// this.entityEffect = new PostChain(this.minecraft.getTextureManager(), this.minecraft.getResourceManager(), this.minecraft.getMainRenderTarget(), resourceLocation); -//// this.entityEffect.resize(this.minecraft.getWindow().getWidth(), this.minecraft.getWindow().getHeight()); -//// this.entityTarget = this.entityEffect.getTempTarget("final"); -//// } catch (IOException var3) { -//// LOGGER.warn("Failed to load shader: {}", resourceLocation, var3); -//// this.entityEffect = null; -//// this.entityTarget = null; -//// } catch (JsonSyntaxException var4) { -//// LOGGER.warn("Failed to parse shader: {}", resourceLocation, var4); -//// this.entityEffect = null; -//// this.entityTarget = null; -//// } -// } - -} \ No newline at end of file diff --git a/src/main/java/net/vulkanmod/mixin/render/MinecraftMixin.java b/src/main/java/net/vulkanmod/mixin/render/MinecraftMixin.java index 85c22cfef..d39d1cd18 100644 --- a/src/main/java/net/vulkanmod/mixin/render/MinecraftMixin.java +++ b/src/main/java/net/vulkanmod/mixin/render/MinecraftMixin.java @@ -1,15 +1,14 @@ package net.vulkanmod.mixin.render; import com.mojang.blaze3d.pipeline.RenderTarget; -import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.TimerQuery; -import net.minecraft.Util; import net.minecraft.client.GraphicsStatus; import net.minecraft.client.Minecraft; import net.minecraft.client.Options; import net.minecraft.client.main.GameConfig; +import net.minecraft.util.profiling.ProfilerFiller; import net.vulkanmod.Initializer; -import net.vulkanmod.render.texture.SpriteUtil; +import net.vulkanmod.render.texture.SpriteUpdateUtil; import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.Vulkan; import org.objectweb.asm.Opcodes; @@ -35,63 +34,18 @@ public class MinecraftMixin { private void forceGraphicsMode(GameConfig gameConfig, CallbackInfo ci) { var graphicsModeOption = this.options.graphicsMode(); - if(graphicsModeOption.get() == GraphicsStatus.FABULOUS) { + if (graphicsModeOption.get() == GraphicsStatus.FABULOUS) { Initializer.LOGGER.error("Fabulous graphics mode not supported, forcing Fancy"); graphicsModeOption.set(GraphicsStatus.FANCY); } } - @Inject(method = "runTick", at = @At(value = "HEAD")) - private void resetBuffers(boolean bl, CallbackInfo ci) { - Renderer.getInstance().preInitFrame(); - } - - //Main target (framebuffer) ops - @Redirect(method = "runTick", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;clear(IZ)V")) - private void beginRender(int i, boolean bl) { - RenderSystem.clear(i, bl); - Renderer.getInstance().beginFrame(); - } - - @Inject(method = "runTick", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/Window;updateDisplay()V", shift = At.Shift.BEFORE)) - private void submitRender(boolean tick, CallbackInfo ci) { - Renderer.getInstance().endFrame(); - } - - @Redirect(method = "runTick", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/pipeline/RenderTarget;bindWrite(Z)V")) - private void redirectMainTarget1(RenderTarget instance, boolean bl) { - Renderer.getInstance().getMainPass().mainTargetBindWrite(); - } - - @Redirect(method = "runTick", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/pipeline/RenderTarget;unbindWrite()V")) - private void redirectMainTarget2(RenderTarget instance) { - Renderer.getInstance().getMainPass().mainTargetUnbindWrite(); - } - - @Redirect(method = "runTick", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/pipeline/RenderTarget;blitToScreen(II)V")) - private void removeBlit(RenderTarget instance, int i, int j) { - } - - - @Redirect(method = "runTick", at = @At(value = "INVOKE", target = "Ljava/lang/Thread;yield()V")) - private void removeThreadYield() { - } - - @Inject(method = "getFramerateLimit", at = @At("HEAD"), cancellable = true) - private void limitWhenMinimized(CallbackInfoReturnable cir) { - if(this.noRender) cir.setReturnValue(10); - } - - @Redirect(method = "runTick", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/TimerQuery;getInstance()Ljava/util/Optional;")) - private Optional removeTimer() { - return Optional.empty(); - } - @Inject(method = "runTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;tick()V"), locals = LocalCapture.CAPTURE_FAILHARD) - private void redirectResourceTick(boolean bl, CallbackInfo ci, Runnable runnable, int i, int j) { + private void redirectResourceTick(boolean bl, CallbackInfo ci, int i, ProfilerFiller profilerFiller, int j) { int n = Math.min(10, i) - 1; - SpriteUtil.setDoUpload(j == n); + boolean doUpload = j == n; + SpriteUpdateUtil.setDoUpload(doUpload); } @Inject(method = "close", at = @At(value = "HEAD")) @@ -103,12 +57,6 @@ public void close(CallbackInfo ci) { @Inject(method = "close", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/VirtualScreen;close()V")) public void close2(CallbackInfo ci) { Vulkan.cleanUp(); - Util.shutdownExecutors(); - } - - @Redirect(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;emergencySave()V")) - private void skipEmergencySave(Minecraft instance) { - } @Inject(method = "resizeDisplay", at = @At("HEAD")) @@ -116,8 +64,8 @@ public void onResolutionChanged(CallbackInfo ci) { Renderer.scheduleSwapChainUpdate(); } - //Fixes crash when minimizing window before setScreen is called + // Fixes crash when minimizing window before setScreen is called @Redirect(method = "setScreen", at = @At(value = "FIELD", target = "Lnet/minecraft/client/Minecraft;noRender:Z", opcode = Opcodes.PUTFIELD)) - private void keepVar(Minecraft instance, boolean value) { } + private void keepVar(Minecraft instance, boolean value) {} } diff --git a/src/main/java/net/vulkanmod/mixin/render/PictureInPictureRendererM.java b/src/main/java/net/vulkanmod/mixin/render/PictureInPictureRendererM.java new file mode 100644 index 000000000..6ed06dc33 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/PictureInPictureRendererM.java @@ -0,0 +1,42 @@ +package net.vulkanmod.mixin.render; + +import com.mojang.blaze3d.textures.GpuTextureView; +import net.minecraft.client.gui.render.TextureSetup; +import net.minecraft.client.gui.render.pip.PictureInPictureRenderer; +import net.minecraft.client.gui.render.state.BlitRenderState; +import net.minecraft.client.gui.render.state.GuiRenderState; +import net.minecraft.client.gui.render.state.pip.PictureInPictureRenderState; +import net.minecraft.client.renderer.RenderPipelines; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(PictureInPictureRenderer.class) +public class PictureInPictureRendererM { + + @Shadow + private @Nullable GpuTextureView textureView; + + @Overwrite + public void blitTexture(T pictureInPictureRenderState, GuiRenderState guiRenderState) { + guiRenderState.submitBlitToCurrentLayer( + new BlitRenderState( + RenderPipelines.GUI_TEXTURED_PREMULTIPLIED_ALPHA, + TextureSetup.singleTexture(this.textureView), + pictureInPictureRenderState.pose(), + pictureInPictureRenderState.x0(), + pictureInPictureRenderState.y0(), + pictureInPictureRenderState.x1(), + pictureInPictureRenderState.y1(), + 0.0F, + 1.0F, + 0.0F, + 1.0F, + -1, + pictureInPictureRenderState.scissorArea(), + null + ) + ); + } +} diff --git a/src/main/java/net/vulkanmod/mixin/render/RenderSystemMixin.java b/src/main/java/net/vulkanmod/mixin/render/RenderSystemMixin.java index 4a431ca1c..74ef4eb5b 100644 --- a/src/main/java/net/vulkanmod/mixin/render/RenderSystemMixin.java +++ b/src/main/java/net/vulkanmod/mixin/render/RenderSystemMixin.java @@ -1,458 +1,63 @@ package net.vulkanmod.mixin.render; -import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.shaders.ShaderType; +import com.mojang.blaze3d.systems.GpuDevice; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.VertexSorting; -import net.vulkanmod.gl.GlTexture; +import com.mojang.blaze3d.vertex.*; +import net.minecraft.client.renderer.DynamicUniforms; +import net.minecraft.resources.ResourceLocation; +import net.vulkanmod.render.engine.VkGpuDevice; import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.VRenderSystem; import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; -import org.joml.Matrix4fStack; -import org.joml.Vector3f; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import java.util.function.Consumer; +import java.util.function.BiFunction; import static com.mojang.blaze3d.systems.RenderSystem.*; @Mixin(RenderSystem.class) public abstract class RenderSystemMixin { - - @Shadow private static Matrix4f projectionMatrix; - @Shadow private static Matrix4f savedProjectionMatrix; - @Shadow @Final private static Matrix4fStack modelViewStack; - @Shadow private static Matrix4f modelViewMatrix; @Shadow private static Matrix4f textureMatrix; - @Shadow @Final private static int[] shaderTextures; - @Shadow @Final private static float[] shaderColor; - @Shadow @Final private static Vector3f[] shaderLightDirections; + @Shadow private static @Nullable Thread renderThread; - @Shadow @Final private static float[] shaderFogColor; + @Shadow private static @Nullable GpuDevice DEVICE; + @Shadow private static @Nullable DynamicUniforms dynamicUniforms; - @Shadow private static @Nullable Thread renderThread; + @Shadow private static String apiDescription; @Shadow - public static void assertOnRenderThread() { - } + public static void assertOnRenderThread() {} - /** - * @author - */ @Overwrite(remap = false) - public static void initRenderer(int debugVerbosity, boolean debugSync) { - VRenderSystem.initRenderer(); - + public static void initRenderer(long l, int i, boolean bl, BiFunction shaderSource, boolean bl2) { renderThread.setPriority(Thread.NORM_PRIORITY + 2); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void setupDefaultState(int x, int y, int width, int height) { } - - /** - * @author - */ - @Overwrite(remap = false) - public static void enableColorLogicOp() { - assertOnRenderThread(); - VRenderSystem.enableColorLogicOp(); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void disableColorLogicOp() { - assertOnRenderThread(); - VRenderSystem.disableColorLogicOp(); - } - - /** - * @author - */ - @Overwrite - public static void logicOp(GlStateManager.LogicOp op) { - assertOnRenderThread(); - VRenderSystem.logicOp(op); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void activeTexture(int texture) { - GlTexture.activeTexture(texture); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void glGenBuffers(Consumer consumer) {} - - /** - * @author - */ - @Overwrite(remap = false) - public static void glGenVertexArrays(Consumer consumer) {} - - /** - * @author - */ - @Overwrite(remap = false) - public static int maxSupportedTextureSize() { - return VRenderSystem.maxSupportedTextureSize(); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void clear(int mask, boolean getError) { - VRenderSystem.clear(mask); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void clearColor(float r, float g, float b, float a) { - VRenderSystem.setClearColor(r, g, b, a); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void clearDepth(double d) { - VRenderSystem.clearDepth(d); - } - - @Redirect(method = "flipFrame", at = @At(value = "INVOKE", target = "Lorg/lwjgl/glfw/GLFW;glfwSwapBuffers(J)V"), remap = false) - private static void removeSwapBuffers(long window) { - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void viewport(int x, int y, int width, int height) { - Renderer.setViewport(x, y, width, height); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void enableScissor(int x, int y, int width, int height) { - Renderer.setScissor(x, y, width, height); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void disableScissor() { - Renderer.resetScissor(); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void disableDepthTest() { - assertOnRenderThread(); - //GlStateManager._disableDepthTest(); - VRenderSystem.disableDepthTest(); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void enableDepthTest() { - assertOnRenderThreadOrInit(); - VRenderSystem.enableDepthTest(); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void depthFunc(int i) { - assertOnRenderThread(); - VRenderSystem.depthFunc(i); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void depthMask(boolean b) { - assertOnRenderThread(); - VRenderSystem.depthMask(b); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void colorMask(boolean red, boolean green, boolean blue, boolean alpha) { - VRenderSystem.colorMask(red, green, blue, alpha); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void blendEquation(int i) { - assertOnRenderThread(); - //TODO - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void enableBlend() { - VRenderSystem.enableBlend(); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void disableBlend() { - VRenderSystem.disableBlend(); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void blendFunc(GlStateManager.SourceFactor sourceFactor, GlStateManager.DestFactor destFactor) { - VRenderSystem.blendFunc(sourceFactor, destFactor); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void blendFunc(int srcFactor, int dstFactor) { - VRenderSystem.blendFunc(srcFactor, dstFactor); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void blendFuncSeparate(GlStateManager.SourceFactor p_69417_, GlStateManager.DestFactor p_69418_, GlStateManager.SourceFactor p_69419_, GlStateManager.DestFactor p_69420_) { - VRenderSystem.blendFuncSeparate(p_69417_, p_69418_, p_69419_, p_69420_); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void blendFuncSeparate(int srcFactorRGB, int dstFactorRGB, int srcFactorAlpha, int dstFactorAlpha) { - VRenderSystem.blendFuncSeparate(srcFactorRGB, dstFactorRGB, srcFactorAlpha, dstFactorAlpha); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void enableCull() { - assertOnRenderThread(); - VRenderSystem.enableCull(); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void disableCull() { - assertOnRenderThread(); - VRenderSystem.disableCull(); - } - /** - * @author - */ - @Overwrite(remap = false) - public static void polygonMode(final int i, final int j) { - assertOnRenderThread(); - VRenderSystem.setPolygonModeGL(i); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void enablePolygonOffset() { - assertOnRenderThread(); - VRenderSystem.enablePolygonOffset(); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void disablePolygonOffset() { - assertOnRenderThread(); - VRenderSystem.disablePolygonOffset(); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void polygonOffset(float p_69864_, float p_69865_) { - assertOnRenderThread(); - VRenderSystem.polygonOffset(p_69864_, p_69865_); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void setShaderLights(Vector3f dir0, Vector3f dir1) { - shaderLightDirections[0] = dir0; - shaderLightDirections[1] = dir1; - - VRenderSystem.lightDirection0.buffer.putFloat(0, dir0.x()); - VRenderSystem.lightDirection0.buffer.putFloat(4, dir0.y()); - VRenderSystem.lightDirection0.buffer.putFloat(8, dir0.z()); - - VRenderSystem.lightDirection1.buffer.putFloat(0, dir1.x()); - VRenderSystem.lightDirection1.buffer.putFloat(4, dir1.y()); - VRenderSystem.lightDirection1.buffer.putFloat(8, dir1.z()); - } - - /** - * @author - */ - @Overwrite(remap = false) - private static void _setShaderColor(float r, float g, float b, float a) { - shaderColor[0] = r; - shaderColor[1] = g; - shaderColor[2] = b; - shaderColor[3] = a; - - VRenderSystem.setShaderColor(r, g, b, a); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void setShaderFogColor(float f, float g, float h, float i) { - shaderFogColor[0] = f; - shaderFogColor[1] = g; - shaderFogColor[2] = h; - shaderFogColor[3] = i; - - VRenderSystem.setShaderFogColor(f, g, h, i); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void setProjectionMatrix(Matrix4f projectionMatrix, VertexSorting vertexSorting) { - Matrix4f matrix4f = new Matrix4f(projectionMatrix); - if (!isOnRenderThread()) { - recordRenderCall(() -> { - RenderSystemMixin.projectionMatrix = matrix4f; + VRenderSystem.initRenderer(); - VRenderSystem.applyProjectionMatrix(matrix4f); - VRenderSystem.calculateMVP(); - }); - } else { - RenderSystemMixin.projectionMatrix = matrix4f; + DEVICE = new VkGpuDevice(l, i, bl, shaderSource, bl2); + apiDescription = getDevice().getImplementationInformation(); - VRenderSystem.applyProjectionMatrix(matrix4f); - VRenderSystem.calculateMVP(); - } + Renderer.initRenderer(); + dynamicUniforms = new DynamicUniforms(); } - /** - * @author - */ @Overwrite(remap = false) public static void setTextureMatrix(Matrix4f matrix4f) { - Matrix4f matrix4f2 = new Matrix4f(matrix4f); - if (!RenderSystem.isOnRenderThread()) { - RenderSystem.recordRenderCall(() -> { - textureMatrix = matrix4f2; - VRenderSystem.setTextureMatrix(matrix4f); - }); - } else { - textureMatrix = matrix4f2; - VRenderSystem.setTextureMatrix(matrix4f); - } + assertOnRenderThread(); + textureMatrix.set(matrix4f); + VRenderSystem.setTextureMatrix(matrix4f); } - /** - * @author - */ @Overwrite(remap = false) public static void resetTextureMatrix() { - if (!RenderSystem.isOnRenderThread()) { - RenderSystem.recordRenderCall(() -> textureMatrix.identity()); - } else { - textureMatrix.identity(); - VRenderSystem.setTextureMatrix(textureMatrix); - } - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void applyModelViewMatrix() { - Matrix4f matrix4f = new Matrix4f(modelViewStack); - if (!isOnRenderThread()) { - recordRenderCall(() -> { - modelViewMatrix = matrix4f; - //Vulkan - VRenderSystem.applyModelViewMatrix(matrix4f); - VRenderSystem.calculateMVP(); - }); - } else { - modelViewMatrix = matrix4f; - - VRenderSystem.applyModelViewMatrix(matrix4f); - VRenderSystem.calculateMVP(); - } - - } - - /** - * @author - */ - @Overwrite(remap = false) - private static void _restoreProjectionMatrix() { - projectionMatrix = savedProjectionMatrix; - - VRenderSystem.applyProjectionMatrix(projectionMatrix); - VRenderSystem.calculateMVP(); + assertOnRenderThread(); + textureMatrix.identity(); + VRenderSystem.setTextureMatrix(textureMatrix); } - /** - * @author - */ - @Overwrite(remap = false) - public static void texParameter(int target, int pname, int param) { - GlTexture.texParameteri(target, pname, param); - } } diff --git a/src/main/java/net/vulkanmod/mixin/render/RenderTypeM.java b/src/main/java/net/vulkanmod/mixin/render/RenderTypeM.java index adae96e46..2c65c4307 100644 --- a/src/main/java/net/vulkanmod/mixin/render/RenderTypeM.java +++ b/src/main/java/net/vulkanmod/mixin/render/RenderTypeM.java @@ -1,6 +1,5 @@ package net.vulkanmod.mixin.render; -import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.client.renderer.RenderType; import net.vulkanmod.interfaces.ExtendedRenderType; import net.vulkanmod.render.vertex.TerrainRenderType; @@ -12,9 +11,10 @@ @Mixin(RenderType.class) public class RenderTypeM implements ExtendedRenderType { TerrainRenderType terrainRenderType; - + @Inject(method = "", at = @At("RETURN")) - private void inj(String string, VertexFormat vertexFormat, VertexFormat.Mode mode, int i, boolean bl, boolean bl2, Runnable runnable, Runnable runnable2, CallbackInfo ci) { + private void inj(String string, int i, boolean bl, boolean bl2, Runnable runnable, Runnable runnable2, + CallbackInfo ci) { terrainRenderType = switch (string) { case "solid" -> TerrainRenderType.SOLID; case "cutout" -> TerrainRenderType.CUTOUT; @@ -24,7 +24,7 @@ private void inj(String string, VertexFormat vertexFormat, VertexFormat.Mode mod default -> null; }; } - + @Override public TerrainRenderType getTerrainRenderType() { return terrainRenderType; diff --git a/src/main/java/net/vulkanmod/mixin/render/ShaderInstanceM.java b/src/main/java/net/vulkanmod/mixin/render/ShaderInstanceM.java deleted file mode 100644 index ec2fa3f1e..000000000 --- a/src/main/java/net/vulkanmod/mixin/render/ShaderInstanceM.java +++ /dev/null @@ -1,246 +0,0 @@ -package net.vulkanmod.mixin.render; - -import com.mojang.blaze3d.platform.Window; -import com.mojang.blaze3d.shaders.Program; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.VertexFormat; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.ShaderInstance; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.Resource; -import net.minecraft.server.packs.resources.ResourceProvider; -import net.vulkanmod.Initializer; -import net.vulkanmod.interfaces.ShaderMixed; -import net.vulkanmod.vulkan.shader.GraphicsPipeline; -import net.vulkanmod.vulkan.shader.Pipeline; -import net.vulkanmod.vulkan.shader.descriptor.UBO; -import net.vulkanmod.vulkan.shader.layout.Uniform; -import net.vulkanmod.vulkan.shader.parser.GlslConverter; -import net.vulkanmod.vulkan.util.MappedBuffer; -import org.apache.commons.io.IOUtils; -import org.jetbrains.annotations.Nullable; -import org.lwjgl.system.MemoryUtil; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.Map; -import java.util.function.Supplier; - -@Mixin(ShaderInstance.class) -public class ShaderInstanceM implements ShaderMixed { - - @Shadow @Final private Map uniformMap; - @Shadow @Final private String name; - - @Shadow @Final @Nullable public com.mojang.blaze3d.shaders.Uniform MODEL_VIEW_MATRIX; - @Shadow @Final @Nullable public com.mojang.blaze3d.shaders.Uniform PROJECTION_MATRIX; - @Shadow @Final @Nullable public com.mojang.blaze3d.shaders.Uniform COLOR_MODULATOR; - @Shadow @Final @Nullable public com.mojang.blaze3d.shaders.Uniform LINE_WIDTH; - - @Shadow @Final @Nullable public com.mojang.blaze3d.shaders.Uniform GLINT_ALPHA; - @Shadow @Final @Nullable public com.mojang.blaze3d.shaders.Uniform FOG_START; - @Shadow @Final @Nullable public com.mojang.blaze3d.shaders.Uniform FOG_END; - @Shadow @Final @Nullable public com.mojang.blaze3d.shaders.Uniform FOG_COLOR; - @Shadow @Final @Nullable public com.mojang.blaze3d.shaders.Uniform FOG_SHAPE; - @Shadow @Final @Nullable public com.mojang.blaze3d.shaders.Uniform TEXTURE_MATRIX; - @Shadow @Final @Nullable public com.mojang.blaze3d.shaders.Uniform GAME_TIME; - @Shadow @Final @Nullable public com.mojang.blaze3d.shaders.Uniform SCREEN_SIZE; - - private String vsPath; - private String fsName; - - private GraphicsPipeline pipeline; - boolean isLegacy = false; - - - public GraphicsPipeline getPipeline() { - return pipeline; - } - - @Inject(method = "", at = @At("RETURN")) - private void create(ResourceProvider resourceProvider, String name, VertexFormat format, CallbackInfo ci) { - - try { - if (Pipeline.class.getResourceAsStream(String.format("/assets/vulkanmod/shaders/minecraft/core/%s/%s.json", name, name)) == null) { - createLegacyShader(resourceProvider, format); - return; - } - - String path = String.format("minecraft/core/%s/%s", name, name); - Pipeline.Builder pipelineBuilder = new Pipeline.Builder(format, path); - pipelineBuilder.parseBindingsJSON(); - pipelineBuilder.compileShaders(); - this.pipeline = pipelineBuilder.createGraphicsPipeline(); - } catch (Exception e) { - System.out.printf("Error on shader %s creation\n", name); - e.printStackTrace(); - throw e; - } - } - - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ShaderInstance;getOrCreate(Lnet/minecraft/server/packs/resources/ResourceProvider;Lcom/mojang/blaze3d/shaders/Program$Type;Ljava/lang/String;)Lcom/mojang/blaze3d/shaders/Program;")) - private Program loadNames(ResourceProvider resourceProvider, Program.Type type, String name) { - String path; - if (this.name.contains(String.valueOf(ResourceLocation.NAMESPACE_SEPARATOR))) { - ResourceLocation location = ResourceLocation.tryParse(name); - path = location.withPath("shaders/core/%s".formatted(location.getPath())).toString(); - } else { - path = "shaders/core/%s".formatted(name); - } - - switch (type) { - case VERTEX -> this.vsPath = path; - case FRAGMENT -> this.fsName = path; - } - - return null; - } - - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/shaders/Uniform;glBindAttribLocation(IILjava/lang/CharSequence;)V")) - private void bindAttr(int program, int index, CharSequence name) {} - - /** - * @author - */ - @Overwrite - public void close() { - if (this.pipeline != null) - this.pipeline.cleanUp(); - } - - /** - * @author - */ - @Overwrite - public void apply() { - if (!this.isLegacy) - return; - - if (this.MODEL_VIEW_MATRIX != null) { - this.MODEL_VIEW_MATRIX.set(RenderSystem.getModelViewMatrix()); - } - - if (this.PROJECTION_MATRIX != null) { - this.PROJECTION_MATRIX.set(RenderSystem.getProjectionMatrix()); - } - - if (this.COLOR_MODULATOR != null) { - this.COLOR_MODULATOR.set(RenderSystem.getShaderColor()); - } - - if (this.GLINT_ALPHA != null) { - this.GLINT_ALPHA.set(RenderSystem.getShaderGlintAlpha()); - } - - if (this.FOG_START != null) { - this.FOG_START.set(RenderSystem.getShaderFogStart()); - } - - if (this.FOG_END != null) { - this.FOG_END.set(RenderSystem.getShaderFogEnd()); - } - - if (this.FOG_COLOR != null) { - this.FOG_COLOR.set(RenderSystem.getShaderFogColor()); - } - - if (this.FOG_SHAPE != null) { - this.FOG_SHAPE.set(RenderSystem.getShaderFogShape().getIndex()); - } - - if (this.TEXTURE_MATRIX != null) { - this.TEXTURE_MATRIX.set(RenderSystem.getTextureMatrix()); - } - - if (this.GAME_TIME != null) { - this.GAME_TIME.set(RenderSystem.getShaderGameTime()); - } - - if (this.SCREEN_SIZE != null) { - Window window = Minecraft.getInstance().getWindow(); - this.SCREEN_SIZE.set((float) window.getWidth(), (float) window.getHeight()); - } - - if (this.LINE_WIDTH != null) { - this.LINE_WIDTH.set(RenderSystem.getShaderLineWidth()); - } - } - - /** - * @author - */ - @Overwrite - public void clear() {} - - private void setUniformSuppliers(UBO ubo) { - - for (Uniform vUniform : ubo.getUniforms()) { - com.mojang.blaze3d.shaders.Uniform uniform = this.uniformMap.get(vUniform.getName()); - - if (uniform == null) { - Initializer.LOGGER.error(String.format("Error: field %s not present in uniform map", vUniform.getName())); - continue; - } - - Supplier supplier; - ByteBuffer byteBuffer; - - if (uniform.getType() <= 3) { - byteBuffer = MemoryUtil.memByteBuffer(uniform.getIntBuffer()); - } else if (uniform.getType() <= 10) { - byteBuffer = MemoryUtil.memByteBuffer(uniform.getFloatBuffer()); - } else { - throw new RuntimeException("out of bounds value for uniform " + uniform); - } - - - MappedBuffer mappedBuffer = MappedBuffer.createFromBuffer(byteBuffer); - supplier = () -> mappedBuffer; - - vUniform.setSupplier(supplier); - } - - } - - private void createLegacyShader(ResourceProvider resourceProvider, VertexFormat format) { - try { - String vertPath = this.vsPath + ".vsh"; - Resource resource = resourceProvider.getResourceOrThrow(ResourceLocation.tryParse(vertPath)); - InputStream inputStream = resource.open(); - String vshSrc = IOUtils.toString(inputStream, StandardCharsets.UTF_8); - - String fragPath = this.fsName + ".fsh"; - resource = resourceProvider.getResourceOrThrow(ResourceLocation.tryParse(fragPath)); - inputStream = resource.open(); - String fshSrc = IOUtils.toString(inputStream, StandardCharsets.UTF_8); - - GlslConverter converter = new GlslConverter(); - Pipeline.Builder builder = new Pipeline.Builder(format, this.name); - - converter.process(vshSrc, fshSrc); - UBO ubo = converter.getUBO(); - this.setUniformSuppliers(ubo); - - builder.setUniforms(Collections.singletonList(ubo), converter.getSamplerList()); - builder.compileShaders(this.name, converter.getVshConverted(), converter.getFshConverted()); - - this.pipeline = builder.createGraphicsPipeline(); - this.isLegacy = true; - - } catch (Exception e) { - Initializer.LOGGER.error("Error on shader {} conversion/compilation", this.name); - e.printStackTrace(); - } - } -} - diff --git a/src/main/java/net/vulkanmod/mixin/render/biome/BiomeManagerM.java b/src/main/java/net/vulkanmod/mixin/render/biome/BiomeManagerM.java new file mode 100644 index 000000000..7ec047b32 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/biome/BiomeManagerM.java @@ -0,0 +1,18 @@ +package net.vulkanmod.mixin.render.biome; + +import net.minecraft.world.level.biome.BiomeManager; +import net.vulkanmod.interfaces.biome.BiomeManagerExtended; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(BiomeManager.class) +public class BiomeManagerM implements BiomeManagerExtended { + + @Shadow @Final private long biomeZoomSeed; + + @Override + public long getBiomeZoomSeed() { + return this.biomeZoomSeed; + } +} diff --git a/src/main/java/net/vulkanmod/mixin/render/block/BakedQuadM.java b/src/main/java/net/vulkanmod/mixin/render/block/BakedQuadM.java index 9c315f1be..2d07ba780 100644 --- a/src/main/java/net/vulkanmod/mixin/render/block/BakedQuadM.java +++ b/src/main/java/net/vulkanmod/mixin/render/block/BakedQuadM.java @@ -3,7 +3,9 @@ import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.core.Direction; -import net.vulkanmod.render.model.quad.QuadView; +import net.vulkanmod.render.chunk.build.frapi.helper.NormalHelper; +import net.vulkanmod.render.chunk.cull.QuadFacing; +import net.vulkanmod.render.model.quad.ModelQuadView; import net.vulkanmod.render.model.quad.ModelQuadFlags; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -15,16 +17,23 @@ import static net.vulkanmod.render.model.quad.ModelQuad.VERTEX_SIZE; @Mixin(BakedQuad.class) -public class BakedQuadM implements QuadView { +public class BakedQuadM implements ModelQuadView { @Shadow @Final protected int[] vertices; @Shadow @Final protected Direction direction; @Shadow @Final protected int tintIndex; + private int flags; + private int normal; + private QuadFacing facing; @Inject(method = "", at = @At("RETURN")) - private void onInit(int[] vertices, int tintIndex, Direction direction, TextureAtlasSprite textureAtlasSprite, boolean shade, CallbackInfo ci) { - this.flags = ModelQuadFlags.getQuadFlags(vertices, direction); + private void onInit(int[] vertices, int tintIndex, Direction face, TextureAtlasSprite textureAtlasSprite, boolean shade, int lightEmission, CallbackInfo ci) { + this.flags = ModelQuadFlags.getQuadFlags(this, face); + + int packedNormal = NormalHelper.computePackedNormal(this); + this.normal = packedNormal; + this.facing = QuadFacing.fromNormal(packedNormal); } @Override @@ -67,11 +76,26 @@ public int getColorIndex() { return this.tintIndex; } + @Override + public Direction lightFace() { + return this.direction; + } + @Override public Direction getFacingDirection() { return this.direction; } + @Override + public QuadFacing getQuadFacing() { + return this.facing; + } + + @Override + public int getNormal() { + return this.normal; + } + @Override public boolean isTinted() { return this.tintIndex != -1; diff --git a/src/main/java/net/vulkanmod/mixin/render/clouds/LevelRendererM.java b/src/main/java/net/vulkanmod/mixin/render/clouds/LevelRendererM.java new file mode 100644 index 000000000..10231841c --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/clouds/LevelRendererM.java @@ -0,0 +1,67 @@ +package net.vulkanmod.mixin.render.clouds; + +import com.mojang.blaze3d.framegraph.FrameGraphBuilder; +import com.mojang.blaze3d.framegraph.FramePass; +import net.minecraft.client.CloudStatus; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.*; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.world.phys.Vec3; +import net.vulkanmod.render.profiling.Profiler; +import net.vulkanmod.render.sky.CloudRenderer; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(LevelRenderer.class) +public abstract class LevelRendererM { + + @Shadow private int ticks; + @Shadow private @Nullable ClientLevel level; + @Shadow @Final private LevelTargetBundle targets; + + @Unique private CloudRenderer cloudRenderer; + + @Inject(method = "addCloudsPass", at = @At("HEAD"), cancellable = true) + public void addCloudsPass(FrameGraphBuilder frameGraphBuilder, CloudStatus cloudStatus, Vec3 camPos, float partialTicks, int i, float g, CallbackInfo ci) { + if (this.cloudRenderer == null) { + this.cloudRenderer = new CloudRenderer(); + } + + FramePass framePass = frameGraphBuilder.addPass("clouds"); + if (this.targets.clouds != null) { + this.targets.clouds = framePass.readsAndWrites(this.targets.clouds); + } else { + this.targets.main = framePass.readsAndWrites(this.targets.main); + } + + framePass.executes(() -> { + Profiler profiler = Profiler.getMainProfiler(); + profiler.push("Clouds"); + + this.cloudRenderer.renderClouds(this.level, this.ticks, partialTicks, + camPos.x(), camPos.y(), camPos.z()); + + profiler.pop(); + }); + + ci.cancel(); + } + + @Inject(method = "allChanged", at = @At("RETURN")) + private void onAllChanged(CallbackInfo ci) { + if (this.cloudRenderer != null) { + this.cloudRenderer.resetBuffer(); + } + } + + @Inject(method = "onResourceManagerReload", at = @At("RETURN")) + private void onReload(ResourceManager resourceManager, CallbackInfo ci) { + if (this.cloudRenderer != null) { + this.cloudRenderer.loadTexture(); + } + } + +} diff --git a/src/main/java/net/vulkanmod/mixin/render/color/BlockColorsM.java b/src/main/java/net/vulkanmod/mixin/render/color/BlockColorsM.java new file mode 100644 index 000000000..b3480e5c9 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/color/BlockColorsM.java @@ -0,0 +1,29 @@ +package net.vulkanmod.mixin.render.color; + +import net.minecraft.client.color.block.BlockColor; +import net.minecraft.client.color.block.BlockColors; +import net.minecraft.world.level.block.Block; +import net.vulkanmod.interfaces.color.BlockColorsExtended; +import net.vulkanmod.render.chunk.build.color.BlockColorRegistry; +import org.spongepowered.asm.mixin.Mixin; +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.CallbackInfo; + +@Mixin(BlockColors.class) +public class BlockColorsM implements BlockColorsExtended { + + @Unique + private BlockColorRegistry colorResolvers = new BlockColorRegistry(); + + @Inject(method = "register", at = @At("RETURN")) + private void onRegister(BlockColor blockColor, Block[] blocks, CallbackInfo ci) { + this.colorResolvers.register(blockColor, blocks); + } + + @Override + public BlockColorRegistry getColorResolverMap() { + return this.colorResolvers; + } +} diff --git a/src/main/java/net/vulkanmod/mixin/render/entity/LevelRendererM.java b/src/main/java/net/vulkanmod/mixin/render/entity/LevelRendererM.java index 30b9f3194..2fda4e46d 100644 --- a/src/main/java/net/vulkanmod/mixin/render/entity/LevelRendererM.java +++ b/src/main/java/net/vulkanmod/mixin/render/entity/LevelRendererM.java @@ -1,5 +1,7 @@ package net.vulkanmod.mixin.render.entity; +import com.mojang.blaze3d.buffers.GpuBufferSlice; +import com.mojang.blaze3d.resource.GraphicsResourceAllocator; import com.mojang.blaze3d.vertex.PoseStack; import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; @@ -18,87 +20,87 @@ import net.vulkanmod.Initializer; import net.vulkanmod.render.chunk.WorldRenderer; import org.joml.Matrix4f; +import org.joml.Vector4f; import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.List; import java.util.Map; @Mixin(LevelRenderer.class) public class LevelRendererM { - @Shadow @Final private EntityRenderDispatcher entityRenderDispatcher; - @Shadow @Final private Minecraft minecraft; - - @Unique private Object2ReferenceOpenHashMap, ObjectArrayList>> bufferSourceMap = new Object2ReferenceOpenHashMap<>(); - @Unique boolean managed; - - @Inject(method = "renderLevel", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/renderer/LevelRenderer;setupRender(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/culling/Frustum;ZZ)V", - shift = At.Shift.AFTER) - ) - private void clearMap(DeltaTracker deltaTracker, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, Matrix4f matrix4f2, CallbackInfo ci) { - for (var bufferSource : this.bufferSourceMap.keySet()) { - var entityMap = this.bufferSourceMap.get(bufferSource); - entityMap.clear(); - } - - this.managed = true; - } - - /** - * @author - * @reason - */ - @Overwrite - private void renderEntity(Entity entity, double d, double e, double f, float partialTicks, PoseStack poseStack, MultiBufferSource multiBufferSource) { - if (!Initializer.CONFIG.entityCulling || !this.managed) { - double h = Mth.lerp(partialTicks, entity.xOld, entity.getX()); - double i = Mth.lerp(partialTicks, entity.yOld, entity.getY()); - double j = Mth.lerp(partialTicks, entity.zOld, entity.getZ()); - float k = Mth.lerp(partialTicks, entity.yRotO, entity.getYRot()); - this.entityRenderDispatcher.render(entity, h - d, i - e, j - f, k, partialTicks, poseStack, multiBufferSource, this.entityRenderDispatcher.getPackedLightCoords(entity, partialTicks)); - return; - } - - var entityClass = entity.getClass(); - - var entityMap = this.bufferSourceMap.computeIfAbsent(multiBufferSource, bufferSource -> new Object2ReferenceOpenHashMap<>()); - var list = entityMap.computeIfAbsent(entityClass, k -> new ObjectArrayList<>()); - list.add(entity); - } - - @Inject(method = "renderLevel", at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;endLastBatch()V", - shift = At.Shift.AFTER, ordinal = 0) - ) - private void renderEntities(DeltaTracker deltaTracker, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, Matrix4f matrix4f2, CallbackInfo ci) { - if (!Initializer.CONFIG.entityCulling) - return; - - Vec3 cameraPos = WorldRenderer.getCameraPos(); - TickRateManager tickRateManager = this.minecraft.level.tickRateManager(); - - PoseStack poseStack = new PoseStack(); - - for (var bufferSource : this.bufferSourceMap.keySet()) { - var entityMap = this.bufferSourceMap.get(bufferSource); - - for (var list : entityMap.values()) { - for (Entity entity : list) { - float partialTicks = deltaTracker.getGameTimeDeltaPartialTick(!tickRateManager.isEntityFrozen(entity)); - - double h = Mth.lerp(partialTicks, entity.xOld, entity.getX()); - double i = Mth.lerp(partialTicks, entity.yOld, entity.getY()); - double j = Mth.lerp(partialTicks, entity.zOld, entity.getZ()); - float k = Mth.lerp(partialTicks, entity.yRotO, entity.getYRot()); - this.entityRenderDispatcher.render(entity, h - cameraPos.x, i - cameraPos.y, j - cameraPos.z, k, partialTicks, poseStack, bufferSource, this.entityRenderDispatcher.getPackedLightCoords(entity, partialTicks)); - } - } - } - - this.managed = false; - } + // TODO +// @Shadow @Final private EntityRenderDispatcher entityRenderDispatcher; +// @Shadow @Final private Minecraft minecraft; +// +// @Unique private Object2ReferenceOpenHashMap, ObjectArrayList>> bufferSourceMap = new Object2ReferenceOpenHashMap<>(); +// @Unique boolean managed; +// +// @Inject(method = "renderLevel", +// at = @At(value = "INVOKE", +// target = "Lnet/minecraft/client/renderer/LevelRenderer;setupRender(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/culling/Frustum;ZZ)V", +// shift = At.Shift.AFTER) +// ) +// private void clearMap(GraphicsResourceAllocator graphicsResourceAllocator, DeltaTracker deltaTracker, boolean bl, +// Camera camera, Matrix4f matrix4f, Matrix4f matrix4f2, Matrix4f matrix4f3, +// GpuBufferSlice gpuBufferSlice, Vector4f vector4f, boolean bl2, CallbackInfo ci) { +// for (var bufferSource : this.bufferSourceMap.keySet()) { +// var entityMap = this.bufferSourceMap.get(bufferSource); +// entityMap.clear(); +// } +// +// this.managed = true; +// } +// +// /** +// * @author +// * @reason +// */ +// @Overwrite +// private void renderEntity(Entity entity, double d, double e, double f, float partialTicks, PoseStack poseStack, MultiBufferSource multiBufferSource) { +// if (!Initializer.CONFIG.entityCulling || !this.managed) { +// double h = Mth.lerp(partialTicks, entity.xOld, entity.getX()); +// double i = Mth.lerp(partialTicks, entity.yOld, entity.getY()); +// double j = Mth.lerp(partialTicks, entity.zOld, entity.getZ()); +// this.entityRenderDispatcher.render(entity, h - d, i - e, j - f, partialTicks, poseStack, multiBufferSource, this.entityRenderDispatcher.getPackedLightCoords(entity, partialTicks)); +// return; +// } +// +// var entityClass = entity.getClass(); +// +// var entityMap = this.bufferSourceMap.computeIfAbsent(multiBufferSource, bufferSource -> new Object2ReferenceOpenHashMap<>()); +// var list = entityMap.computeIfAbsent(entityClass, k -> new ObjectArrayList<>()); +// list.add(entity); +// } +// +// @Inject(method = "renderEntities", at = @At("RETURN")) +// private void renderEntities(PoseStack poseStack, MultiBufferSource.BufferSource bufferSource1, Camera camera, DeltaTracker deltaTracker, List entityList, CallbackInfo ci) { +// if (!Initializer.CONFIG.entityCulling) +// return; +// +// Vec3 cameraPos = WorldRenderer.getCameraPos(); +// TickRateManager tickRateManager = this.minecraft.level.tickRateManager(); +// +//// PoseStack poseStack = new PoseStack(); +// +// for (var bufferSource : this.bufferSourceMap.keySet()) { +// var entityMap = this.bufferSourceMap.get(bufferSource); +// +// for (var list : entityMap.values()) { +// for (Entity entity : list) { +// float partialTicks = deltaTracker.getGameTimeDeltaPartialTick(!tickRateManager.isEntityFrozen(entity)); +// +// double h = Mth.lerp(partialTicks, entity.xOld, entity.getX()); +// double i = Mth.lerp(partialTicks, entity.yOld, entity.getY()); +// double j = Mth.lerp(partialTicks, entity.zOld, entity.getZ()); +// this.entityRenderDispatcher.render(entity, h - cameraPos.x, i - cameraPos.y, j - cameraPos.z, partialTicks, poseStack, bufferSource, this.entityRenderDispatcher.getPackedLightCoords(entity, partialTicks)); +// } +// } +// } +// +// this.managed = false; +// } } diff --git a/src/main/java/net/vulkanmod/mixin/render/entity/model/ModelPartCubeM.java b/src/main/java/net/vulkanmod/mixin/render/entity/model/ModelPartCubeM.java index fdc8fe213..a8be49c77 100644 --- a/src/main/java/net/vulkanmod/mixin/render/entity/model/ModelPartCubeM.java +++ b/src/main/java/net/vulkanmod/mixin/render/entity/model/ModelPartCubeM.java @@ -5,6 +5,7 @@ import net.vulkanmod.interfaces.ModelPartCubeMixed; import net.vulkanmod.render.model.CubeModel; import org.spongepowered.asm.mixin.Mixin; +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.CallbackInfo; @@ -13,14 +14,12 @@ @Mixin(ModelPart.Cube.class) public class ModelPartCubeM implements ModelPartCubeMixed { - - CubeModel cube; + @Unique CubeModel cube; @Inject(method = "", at = @At(value = "FIELD", target = "Lnet/minecraft/client/model/geom/ModelPart$Cube;polygons:[Lnet/minecraft/client/model/geom/ModelPart$Polygon;", ordinal = 0, shift = At.Shift.AFTER)) private void getVertices(int i, int j, float f, float g, float h, float k, float l, float m, float n, float o, float p, boolean bl, float q, float r, Set set, CallbackInfo ci) { - //TODO check if set is needed CubeModel cube = new CubeModel(); cube.setVertices(i, j, f, g, h, k, l, m, n, o, p, bl, q, r, set); this.cube = cube; diff --git a/src/main/java/net/vulkanmod/mixin/render/entity/model/ModelPartM.java b/src/main/java/net/vulkanmod/mixin/render/entity/model/ModelPartM.java index 7ad232bbc..514dc0681 100644 --- a/src/main/java/net/vulkanmod/mixin/render/entity/model/ModelPartM.java +++ b/src/main/java/net/vulkanmod/mixin/render/entity/model/ModelPartM.java @@ -6,7 +6,7 @@ import net.vulkanmod.interfaces.ExtendedVertexBuilder; import net.vulkanmod.interfaces.ModelPartCubeMixed; import net.vulkanmod.render.model.CubeModel; -import net.vulkanmod.render.vertex.VertexUtil; +import net.vulkanmod.render.vertex.format.I32_SNorm; import net.vulkanmod.vulkan.util.ColorUtil; import org.joml.Matrix3f; import org.joml.Matrix4f; @@ -22,7 +22,7 @@ public abstract class ModelPartM { @Shadow @Final private List cubes; - Vector3f normal = new Vector3f(); + @Unique Vector3f normal = new Vector3f(); @Inject(method = "compile", at = @At("HEAD"), cancellable = true) private void injCompile(PoseStack.Pose pose, VertexConsumer vertexConsumer, int light, int overlay, int color, CallbackInfo ci) { @@ -37,28 +37,33 @@ public void renderCubes(PoseStack.Pose pose, VertexConsumer vertexConsumer, int ExtendedVertexBuilder vertexBuilder = ExtendedVertexBuilder.of(vertexConsumer); - if (vertexBuilder != null && vertexBuilder.canUseFastVertex()) { + boolean useFastFormat = vertexBuilder != null && vertexBuilder.canUseFastVertex(); + + if (useFastFormat) { color = ColorUtil.RGBA.fromArgb32(color); for (ModelPart.Cube cube : this.cubes) { ModelPartCubeMixed cubeMixed = (ModelPartCubeMixed)(cube); CubeModel cubeModel = cubeMixed.getCubeModel(); - ModelPart.Polygon[] polygons = cubeModel.getPolygons(); + CubeModel.Polygon[] polygons = cubeModel.getPolygons(); cubeModel.transformVertices(matrix4f); - for (ModelPart.Polygon polygon : polygons) { - matrix3f.transform(this.normal.set(polygon.normal)); + for (CubeModel.Polygon polygon : polygons) { + matrix3f.transform(this.normal.set(polygon.normal())); this.normal.normalize(); - int packedNormal = VertexUtil.packNormal(normal.x(), normal.y(), normal.z()); + int packedNormal = I32_SNorm.packNormal(normal.x(), normal.y(), normal.z()); - ModelPart.Vertex[] vertices = polygon.vertices; + CubeModel.Vertex[] vertices = polygon.vertices(); - for (ModelPart.Vertex vertex : vertices) { - Vector3f pos = vertex.pos; - vertexBuilder.vertex(pos.x(), pos.y(), pos.z(), color, vertex.u, vertex.v, overlay, light, packedNormal); + for (CubeModel.Vertex vertex : vertices) { + Vector3f pos = vertex.pos(); + vertexBuilder.vertex(pos.x(), pos.y(), pos.z(), + color, + vertex.u(), vertex.v(), + overlay, light, packedNormal); } } } @@ -68,20 +73,23 @@ public void renderCubes(PoseStack.Pose pose, VertexConsumer vertexConsumer, int ModelPartCubeMixed cubeMixed = (ModelPartCubeMixed)(cube); CubeModel cubeModel = cubeMixed.getCubeModel(); - ModelPart.Polygon[] polygons = cubeModel.getPolygons(); + CubeModel.Polygon[] polygons = cubeModel.getPolygons(); cubeModel.transformVertices(matrix4f); - for (ModelPart.Polygon polygon : polygons) { - matrix3f.transform(this.normal.set(polygon.normal)); + for (CubeModel.Polygon polygon : polygons) { + matrix3f.transform(this.normal.set(polygon.normal())); this.normal.normalize(); - ModelPart.Vertex[] vertices = polygon.vertices; + CubeModel.Vertex[] vertices = polygon.vertices(); - for (ModelPart.Vertex vertex : vertices) { - Vector3f pos = vertex.pos; - vertexConsumer.addVertex(pos.x(), pos.y(), pos.z(), color, vertex.u, vertex.v, overlay, light, - normal.x(), normal.y(), normal.z()); + for (CubeModel.Vertex vertex : vertices) { + Vector3f pos = vertex.pos(); + vertexConsumer.addVertex(pos.x(), pos.y(), pos.z(), + color, + vertex.u(), vertex.v(), + overlay, light, + normal.x(), normal.y(), normal.z()); } } } diff --git a/src/main/java/net/vulkanmod/mixin/render/frame/MinecraftMixin.java b/src/main/java/net/vulkanmod/mixin/render/frame/MinecraftMixin.java new file mode 100644 index 000000000..a53035f3d --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/frame/MinecraftMixin.java @@ -0,0 +1,41 @@ +package net.vulkanmod.mixin.render.frame; + +import com.mojang.blaze3d.pipeline.RenderTarget; +import com.mojang.blaze3d.systems.CommandEncoder; +import com.mojang.blaze3d.textures.GpuTexture; +import net.minecraft.client.Minecraft; +import net.vulkanmod.render.texture.ImageUploadHelper; +import net.vulkanmod.vulkan.Renderer; +import org.lwjgl.opengl.GL11; +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.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Minecraft.class) +public class MinecraftMixin { + + @Inject(method = "runTick", at = @At(value = "HEAD")) + private void beginFrame(boolean bl, CallbackInfo ci) { + Renderer.getInstance().beginFrame(); + Renderer.clearAttachments(GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_COLOR_BUFFER_BIT); + } + + @Redirect(method = "runTick", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/CommandEncoder;clearColorAndDepthTextures(Lcom/mojang/blaze3d/textures/GpuTexture;ILcom/mojang/blaze3d/textures/GpuTexture;D)V")) + private void redirectClear(CommandEncoder instance, GpuTexture gpuTexture, int i, GpuTexture gpuTexture2, double v) { + // Remove framebuffer clear as it's not needed + + ImageUploadHelper.INSTANCE.submitCommands(); + } + + @Redirect(method = "runTick", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/pipeline/RenderTarget;blitToScreen()V")) + private void removeBlit(RenderTarget instance) { + } + + + @Redirect(method = "runTick", at = @At(value = "INVOKE", target = "Ljava/lang/Thread;yield()V")) + private void removeThreadYield() { + } + +} diff --git a/src/main/java/net/vulkanmod/mixin/render/frame/RenderSystemMixin.java b/src/main/java/net/vulkanmod/mixin/render/frame/RenderSystemMixin.java new file mode 100644 index 000000000..f4ca167b9 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/frame/RenderSystemMixin.java @@ -0,0 +1,16 @@ +package net.vulkanmod.mixin.render.frame; + +import com.mojang.blaze3d.systems.RenderSystem; +import net.vulkanmod.vulkan.Renderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(RenderSystem.class) +public class RenderSystemMixin { + + @Redirect(method = "flipFrame", at = @At(value = "INVOKE", target = "Lorg/lwjgl/glfw/GLFW;glfwSwapBuffers(J)V"), remap = false) + private static void endFrame(long window) { + Renderer.getInstance().endFrame(); + } +} diff --git a/src/main/java/net/vulkanmod/mixin/render/frapi/BatchingRenderCommandQueueM.java b/src/main/java/net/vulkanmod/mixin/render/frapi/BatchingRenderCommandQueueM.java new file mode 100644 index 000000000..84906672a --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/frapi/BatchingRenderCommandQueueM.java @@ -0,0 +1,45 @@ +package net.vulkanmod.mixin.render.frapi; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.fabricmc.fabric.api.renderer.v1.mesh.MeshView; +import net.minecraft.client.renderer.OrderedSubmitNodeCollector; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.SubmitNodeCollection; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.minecraft.world.item.ItemDisplayContext; +import net.vulkanmod.render.chunk.build.frapi.accessor.AccessBatchingRenderCommandQueue; +import net.vulkanmod.render.chunk.build.frapi.accessor.AccessRenderCommandQueue; +import net.vulkanmod.render.chunk.build.frapi.render.MeshItemCommand; +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.CallbackInfo; + +import java.util.ArrayList; +import java.util.List; + +@Mixin(SubmitNodeCollection.class) +abstract class BatchingRenderCommandQueueM implements OrderedSubmitNodeCollector, AccessRenderCommandQueue, AccessBatchingRenderCommandQueue { + @Shadow private boolean wasUsed; + + @Unique private final List meshItemCommands = new ArrayList<>(); + + @Inject(method = "clear()V", at = @At("RETURN")) + public void clear(CallbackInfo ci) { + meshItemCommands.clear(); + } + + @Override + public void submitItem(PoseStack matrices, ItemDisplayContext displayContext, int light, int overlay, int outlineColors, int[] tintLayers, List quads, RenderType renderLayer, ItemStackRenderState.FoilType glintType, MeshView mesh) { + wasUsed = true; + meshItemCommands.add(new MeshItemCommand(matrices.last().copy(), displayContext, light, overlay, outlineColors, tintLayers, quads, renderLayer, glintType, mesh)); + } + + @Override + public List getMeshItemCommands() { + return meshItemCommands; + } +} diff --git a/src/main/java/net/vulkanmod/mixin/render/frapi/BlockModelRendererM.java b/src/main/java/net/vulkanmod/mixin/render/frapi/BlockModelRendererM.java new file mode 100644 index 000000000..9816ac903 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/frapi/BlockModelRendererM.java @@ -0,0 +1,20 @@ +package net.vulkanmod.mixin.render.frapi; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.fabricmc.fabric.api.renderer.v1.render.FabricBlockModelRenderer; +import net.minecraft.client.renderer.block.ModelBlockRenderer; +import net.minecraft.client.renderer.block.model.BlockStateModel; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.EmptyBlockAndTintGetter; +import net.minecraft.world.level.block.Blocks; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; + +@Mixin(ModelBlockRenderer.class) +abstract class BlockModelRendererM { + @Overwrite + public static void renderModel(PoseStack.Pose entry, VertexConsumer vertexConsumer, BlockStateModel model, float red, float green, float blue, int light, int overlay) { + FabricBlockModelRenderer.render(entry, layer -> vertexConsumer, model, red, green, blue, light, overlay, EmptyBlockAndTintGetter.INSTANCE, BlockPos.ZERO, Blocks.AIR.defaultBlockState()); + } +} diff --git a/src/main/java/net/vulkanmod/mixin/render/frapi/BlockRenderDispatcherAccessor.java b/src/main/java/net/vulkanmod/mixin/render/frapi/BlockRenderDispatcherAccessor.java new file mode 100644 index 000000000..3ded98367 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/frapi/BlockRenderDispatcherAccessor.java @@ -0,0 +1,19 @@ +package net.vulkanmod.mixin.render.frapi; + +import java.util.function.Supplier; + +import net.minecraft.client.renderer.SpecialBlockModelRenderer; +import net.minecraft.client.renderer.block.BlockRenderDispatcher; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.client.color.block.BlockColors; + +@Mixin(BlockRenderDispatcher.class) +public interface BlockRenderDispatcherAccessor { + @Accessor("specialBlockModelRenderer") + Supplier getBlockEntityModelsGetter(); + + @Accessor("blockColors") + BlockColors getBlockColors(); +} diff --git a/src/main/java/net/vulkanmod/mixin/render/frapi/BlockRenderManagerM.java b/src/main/java/net/vulkanmod/mixin/render/frapi/BlockRenderManagerM.java new file mode 100644 index 000000000..cc100aa94 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/frapi/BlockRenderManagerM.java @@ -0,0 +1,42 @@ +package net.vulkanmod.mixin.render.frapi; + +import com.llamalad7.mixinextras.sugar.Local; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.fabricmc.fabric.api.renderer.v1.render.FabricBlockModelRenderer; +import net.fabricmc.fabric.api.renderer.v1.render.RenderLayerHelper; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.block.BlockRenderDispatcher; +import net.minecraft.client.renderer.block.ModelBlockRenderer; +import net.minecraft.client.renderer.block.model.BlockStateModel; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.EmptyBlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(BlockRenderDispatcher.class) +abstract class BlockRenderManagerM { + + @Shadow + @Final + private ModelBlockRenderer modelRenderer; + + @Inject(method = "renderBreakingTexture", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/client/renderer/block/BlockModelShaper;getBlockModel(Lnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/client/renderer/block/model/BlockStateModel;", shift = At.Shift.AFTER), cancellable = true) + private void afterGetModel(BlockState blockState, BlockPos blockPos, BlockAndTintGetter world, PoseStack matrixStack, VertexConsumer vertexConsumer, CallbackInfo ci, @Local BlockStateModel model) { + modelRenderer.render(world, model, blockState, blockPos, matrixStack, layer -> vertexConsumer, true, blockState.getSeed(blockPos), OverlayTexture.NO_OVERLAY); + ci.cancel(); + } + + @Redirect(method = "renderSingleBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/block/ModelBlockRenderer;renderModel(Lcom/mojang/blaze3d/vertex/PoseStack$Pose;Lcom/mojang/blaze3d/vertex/VertexConsumer;Lnet/minecraft/client/renderer/block/model/BlockStateModel;FFFII)V")) + private void renderProxy(PoseStack.Pose entry, VertexConsumer vertexConsumer, BlockStateModel model, float red, float green, float blue, int light, int overlay, BlockState state, PoseStack matrices, MultiBufferSource vertexConsumers, int light1, int overlay1) { + FabricBlockModelRenderer.render(entry, RenderLayerHelper.entityDelegate(vertexConsumers), model, red, green, blue, light, overlay, EmptyBlockAndTintGetter.INSTANCE, BlockPos.ZERO, state); + } +} diff --git a/src/main/java/net/vulkanmod/mixin/render/frapi/ItemFeatureRendererM.java b/src/main/java/net/vulkanmod/mixin/render/frapi/ItemFeatureRendererM.java new file mode 100644 index 000000000..778b5c308 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/frapi/ItemFeatureRendererM.java @@ -0,0 +1,43 @@ +package net.vulkanmod.mixin.render.frapi; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.OutlineBufferSource; +import net.minecraft.client.renderer.SubmitNodeCollection; +import net.minecraft.client.renderer.feature.ItemFeatureRenderer; +import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.vulkanmod.render.chunk.build.frapi.accessor.AccessBatchingRenderCommandQueue; +import net.vulkanmod.render.chunk.build.frapi.render.ItemRenderContext; +import net.vulkanmod.render.chunk.build.frapi.render.MeshItemCommand; +import org.spongepowered.asm.mixin.Final; +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.CallbackInfo; + +@Mixin(ItemFeatureRenderer.class) +public class ItemFeatureRendererM { + + @Shadow @Final private PoseStack poseStack; + + @Unique private final ItemRenderContext itemRenderContext = new ItemRenderContext(); + + @Inject(method = "render", at = @At("RETURN")) + private void onReturnRender(SubmitNodeCollection queue, MultiBufferSource.BufferSource vertexConsumers, OutlineBufferSource outlineVertexConsumers, CallbackInfo ci) { + for (MeshItemCommand itemCommand : ((AccessBatchingRenderCommandQueue) queue).getMeshItemCommands()) { + poseStack.pushPose(); + poseStack.last().set(itemCommand.positionMatrix()); + + itemRenderContext.renderModel(itemCommand.displayContext(), poseStack, vertexConsumers, itemCommand.lightCoords(), itemCommand.overlayCoords(), itemCommand.tintLayers(), itemCommand.quads(), itemCommand.mesh(), itemCommand.renderLayer(), itemCommand.glintType(), false); + + if (itemCommand.outlineColor() != 0) { + outlineVertexConsumers.setColor(itemCommand.outlineColor()); + itemRenderContext.renderModel(itemCommand.displayContext(), poseStack, outlineVertexConsumers, itemCommand.lightCoords(), itemCommand.overlayCoords(), itemCommand.tintLayers(), itemCommand.quads(), itemCommand.mesh(), itemCommand.renderLayer(), ItemStackRenderState.FoilType.NONE, true); + } + + poseStack.popPose(); + } + } +} diff --git a/src/main/java/net/vulkanmod/mixin/render/frapi/ItemRenderStateLayerRenderStateM.java b/src/main/java/net/vulkanmod/mixin/render/frapi/ItemRenderStateLayerRenderStateM.java new file mode 100644 index 000000000..7c61babc2 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/frapi/ItemRenderStateLayerRenderStateM.java @@ -0,0 +1,46 @@ +package net.vulkanmod.mixin.render.frapi; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.fabricmc.fabric.api.renderer.v1.render.FabricLayerRenderState; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.SubmitNodeCollector; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.minecraft.world.item.ItemDisplayContext; +import net.vulkanmod.render.chunk.build.frapi.accessor.AccessLayerRenderState; +import net.vulkanmod.render.chunk.build.frapi.accessor.AccessRenderCommandQueue; +import net.vulkanmod.render.chunk.build.frapi.mesh.MutableMeshImpl; +import org.spongepowered.asm.mixin.Mixin; +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.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; + +@Mixin(value = ItemStackRenderState.LayerRenderState.class) +abstract class ItemRenderStateLayerRenderStateM implements FabricLayerRenderState, AccessLayerRenderState { + @Unique + private final MutableMeshImpl mutableMesh = new MutableMeshImpl(); + + @Inject(method = "clear()V", at = @At("RETURN")) + private void onReturnClear(CallbackInfo ci) { + mutableMesh.clear(); + } + + @Redirect(method = "submit", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitItem(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/world/item/ItemDisplayContext;III[ILjava/util/List;Lnet/minecraft/client/renderer/RenderType;Lnet/minecraft/client/renderer/item/ItemStackRenderState$FoilType;)V")) + private void submitItemProxy(SubmitNodeCollector commandQueue, PoseStack matrices, ItemDisplayContext displayContext, int light, int overlay, int outlineColor, int[] tints, List quads, RenderType layer, ItemStackRenderState.FoilType glint) { + if (mutableMesh.size() > 0 && commandQueue instanceof AccessRenderCommandQueue access) { + // We don't have to copy the mesh here because vanilla doesn't copy the tint array or quad list either. + access.submitItem(matrices, displayContext, light, overlay, outlineColor, tints, quads, layer, glint, mutableMesh); + } else { + commandQueue.submitItem(matrices, displayContext, light, overlay, outlineColor, tints, quads, layer, glint); + } + } + + @Override + public MutableMeshImpl getMutableMesh() { + return mutableMesh; + } +} diff --git a/src/main/java/net/vulkanmod/mixin/render/frapi/ItemRenderStateM.java b/src/main/java/net/vulkanmod/mixin/render/frapi/ItemRenderStateM.java new file mode 100644 index 000000000..7f6b1584f --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/frapi/ItemRenderStateM.java @@ -0,0 +1,38 @@ +package net.vulkanmod.mixin.render.frapi; + +import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; +import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.vulkanmod.render.chunk.build.frapi.accessor.AccessLayerRenderState; +import net.vulkanmod.render.chunk.build.frapi.mesh.MutableMeshImpl; +import net.vulkanmod.render.chunk.build.frapi.render.QuadToPosPipe; +import org.joml.Matrix4f; +import org.joml.Vector3f; +import org.joml.Vector3fc; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.function.Consumer; + +@Mixin(ItemStackRenderState.class) +abstract class ItemRenderStateM { + @Inject(method = "visitExtents", at = @At(value = "NEW", target = "()Lcom/mojang/blaze3d/vertex/PoseStack$Pose;")) + private void afterInitVecLoad(Consumer posConsumer, CallbackInfo ci, @Local Vector3f vec, @Share("pipe") LocalRef pipeRef) { + pipeRef.set(new QuadToPosPipe(posConsumer, vec)); + } + + @Inject(method = "visitExtents", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack$Pose;setIdentity()V", shift = At.Shift.BEFORE)) + private void afterLayerLoad(Consumer posConsumer, CallbackInfo ci, @Local(ordinal = 0) Vector3f vec, @Local ItemStackRenderState.LayerRenderState layer, @Local Matrix4f matrix, @Share("pipe") LocalRef pipeRef) { + MutableMeshImpl mutableMesh = ((AccessLayerRenderState) layer).getMutableMesh(); + + if (mutableMesh.size() > 0) { + QuadToPosPipe pipe = pipeRef.get(); + pipe.matrix = matrix; + // Use the mutable version here as it does not use a ThreadLocal or cursor stack + mutableMesh.forEachMutable(pipe); + } + } +} diff --git a/src/main/java/net/vulkanmod/mixin/render/frapi/ItemRendererAccessor.java b/src/main/java/net/vulkanmod/mixin/render/frapi/ItemRendererAccessor.java new file mode 100644 index 000000000..06ca19723 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/frapi/ItemRendererAccessor.java @@ -0,0 +1,17 @@ +package net.vulkanmod.mixin.render.frapi; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.ItemRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(ItemRenderer.class) +public interface ItemRendererAccessor { + @Invoker("getSpecialFoilBuffer") + static VertexConsumer getSpecialFoilBuffer(MultiBufferSource provider, RenderType layer, PoseStack.Pose entry) { + throw new AssertionError(); + } +} diff --git a/src/main/java/net/vulkanmod/mixin/render/frapi/OrderedRenderCommandQueueImplM.java b/src/main/java/net/vulkanmod/mixin/render/frapi/OrderedRenderCommandQueueImplM.java new file mode 100644 index 000000000..17a372de2 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/frapi/OrderedRenderCommandQueueImplM.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.vulkanmod.mixin.render.frapi; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.fabricmc.fabric.api.renderer.v1.mesh.MeshView; + +import net.minecraft.client.renderer.OrderedSubmitNodeCollector; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.SubmitNodeCollector; +import net.minecraft.client.renderer.SubmitNodeStorage; + +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.minecraft.world.item.ItemDisplayContext; +import net.vulkanmod.render.chunk.build.frapi.accessor.AccessRenderCommandQueue; +import org.spongepowered.asm.mixin.Mixin; + +import java.util.List; + +@Mixin(SubmitNodeStorage.class) +abstract class OrderedRenderCommandQueueImplM implements SubmitNodeCollector, AccessRenderCommandQueue { + @Override + public void submitItem(PoseStack matrices, ItemDisplayContext displayContext, int light, int overlay, int outlineColors, int[] tintLayers, List quads, RenderType renderLayer, ItemStackRenderState.FoilType glintType, MeshView mesh) { + OrderedSubmitNodeCollector queue = order(0); + + if (queue instanceof AccessRenderCommandQueue access) { + access.submitItem(matrices, displayContext, light, overlay, outlineColors, tintLayers, quads, renderLayer, glintType, mesh); + } else { + queue.submitItem(matrices, displayContext, light, overlay, outlineColors, tintLayers, quads, renderLayer, glintType); + } + } +} diff --git a/src/main/java/net/vulkanmod/mixin/render/particle/QuadParticleGroupM.java b/src/main/java/net/vulkanmod/mixin/render/particle/QuadParticleGroupM.java new file mode 100644 index 000000000..807c85b93 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/particle/QuadParticleGroupM.java @@ -0,0 +1,25 @@ +package net.vulkanmod.mixin.render.particle; + +import net.minecraft.client.particle.QuadParticleGroup; +import net.minecraft.client.renderer.culling.Frustum; +import net.vulkanmod.render.chunk.RenderSection; +import net.vulkanmod.render.chunk.WorldRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(QuadParticleGroup.class) +public class QuadParticleGroupM { + + @Redirect(method = "extractRenderState", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/culling/Frustum;pointInFrustum(DDD)Z")) + private boolean particleWithinSections(Frustum instance, double x, double y, double z) { + return !cull(WorldRenderer.getInstance(), x, y, z) && instance.pointInFrustum(x,y, z); + } + + @Unique + private static boolean cull(WorldRenderer worldRenderer, double x, double y, double z) { + RenderSection section = worldRenderer.getSectionGrid().getSectionAtBlockPos((int) x, (int) y, (int) z); + return section != null && section.getLastFrame() != worldRenderer.getLastFrame(); + } +} diff --git a/src/main/java/net/vulkanmod/mixin/render/particle/QuadParticleRenderStateM.java b/src/main/java/net/vulkanmod/mixin/render/particle/QuadParticleRenderStateM.java new file mode 100644 index 000000000..b893f0835 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/particle/QuadParticleRenderStateM.java @@ -0,0 +1,45 @@ +package net.vulkanmod.mixin.render.particle; + +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.renderer.state.QuadParticleRenderState; +import net.vulkanmod.interfaces.ExtendedVertexBuilder; +import net.vulkanmod.vulkan.util.ColorUtil; +import org.joml.Quaternionf; +import org.joml.Vector3f; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(QuadParticleRenderState.class) +public class QuadParticleRenderStateM { + + @Unique private final Quaternionf quaternionf = new Quaternionf(); + @Unique private final Vector3f vector3f = new Vector3f(); + + @Overwrite + public void renderRotatedQuad( + VertexConsumer vertexConsumer, float x, float y, float z, float xr, float yr, float zr, float wr, float m, float u0, float u1, float v0, float v1, int color, int light + ) { + quaternionf.set(xr, yr, zr, wr); + + ExtendedVertexBuilder vertexBuilder = (ExtendedVertexBuilder)vertexConsumer; + + color = ColorUtil.BGRAtoRGBA(color); + + this.renderVertex(vertexBuilder, quaternionf, x, y, z, 1.0F, -1.0F, m, u1, v1, color, light); + this.renderVertex(vertexBuilder, quaternionf, x, y, z, 1.0F, 1.0F, m, u1, v0, color, light); + this.renderVertex(vertexBuilder, quaternionf, x, y, z, -1.0F, 1.0F, m, u0, v0, color, light); + this.renderVertex(vertexBuilder, quaternionf, x, y, z, -1.0F, -1.0F, m, u0, v1, color, light); + } + + private void renderVertex( + ExtendedVertexBuilder vertexConsumer, Quaternionf quaternionf, float x, float y, float z, float i, float j, float k, float u, float v, int color, int light + ) { + vector3f.set(i, j, 0.0f) + .rotate(quaternionf) + .mul(k) + .add(x, y, z); + + vertexConsumer.vertex(vector3f.x(), vector3f.y(), vector3f.z(), u, v, color, light); + } +} diff --git a/src/main/java/net/vulkanmod/mixin/render/particle/SingleQuadParticleM.java b/src/main/java/net/vulkanmod/mixin/render/particle/SingleQuadParticleM.java deleted file mode 100644 index 9ffe1077f..000000000 --- a/src/main/java/net/vulkanmod/mixin/render/particle/SingleQuadParticleM.java +++ /dev/null @@ -1,106 +0,0 @@ -package net.vulkanmod.mixin.render.particle; - -import com.mojang.blaze3d.vertex.VertexConsumer; -import net.minecraft.client.Camera; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.particle.ParticleRenderType; -import net.minecraft.client.particle.SingleQuadParticle; -import net.minecraft.client.renderer.LevelRenderer; -import net.minecraft.core.BlockPos; -import net.minecraft.util.Mth; -import net.minecraft.world.phys.Vec3; -import net.vulkanmod.interfaces.ExtendedVertexBuilder; -import net.vulkanmod.render.chunk.RenderSection; -import net.vulkanmod.render.chunk.WorldRenderer; -import net.vulkanmod.vulkan.VRenderSystem; -import net.vulkanmod.vulkan.util.ColorUtil; -import org.joml.Quaternionf; -import org.joml.Vector3f; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(SingleQuadParticle.class) -public abstract class SingleQuadParticleM extends Particle { - - @Shadow protected float quadSize; - - @Shadow protected abstract float getU0(); - @Shadow protected abstract float getU1(); - @Shadow protected abstract float getV0(); - @Shadow protected abstract float getV1(); - - @Shadow public abstract float getQuadSize(float f); - - protected SingleQuadParticleM(ClientLevel clientLevel, double d, double e, double f, double g, double h, double i) { - super(clientLevel, d, e, f, g, h, i); - this.quadSize = 0.1F * (this.random.nextFloat() * 0.5F + 0.5F) * 2.0F; - } - - /** - * @author - * @reason - */ - @Overwrite - public void render(VertexConsumer vertexConsumer, Camera camera, float f) { - double lx = (Mth.lerp(f, this.xo, this.x)); - double ly = (Mth.lerp(f, this.yo, this.y)); - double lz = (Mth.lerp(f, this.zo, this.z)); - - if(cull(WorldRenderer.getInstance(), (float) lx, (float) ly, (float) lz)) - return; - - Vec3 vec3 = camera.getPosition(); - float offsetX = (float) (lx - vec3.x()); - float offsetY = (float) (ly - vec3.y()); - float offsetZ = (float) (lz - vec3.z()); - - Quaternionf quaternionf; - if (this.roll != 0.0F) { - quaternionf = new Quaternionf(camera.rotation()); - quaternionf.rotateZ(Mth.lerp(f, this.oRoll, this.roll)); - } else { - quaternionf = camera.rotation(); - } - - Vector3f[] vector3fs = new Vector3f[]{new Vector3f(-1.0F, -1.0F, 0.0F), new Vector3f(-1.0F, 1.0F, 0.0F), new Vector3f(1.0F, 1.0F, 0.0F), new Vector3f(1.0F, -1.0F, 0.0F)}; - float j = this.getQuadSize(f); - - for(int k = 0; k < 4; ++k) { - Vector3f vector3f = vector3fs[k]; - vector3f.rotate(quaternionf); - vector3f.mul(j); - vector3f.add(offsetX, offsetY, offsetZ); - } - - float u0 = this.getU0(); - float u1 = this.getU1(); - float v0 = this.getV0(); - float v1 = this.getV1(); - int light = this.getLightColor(f); - - ExtendedVertexBuilder vertexBuilder = (ExtendedVertexBuilder)vertexConsumer; - int packedColor = ColorUtil.RGBA.pack(this.rCol, this.gCol, this.bCol, this.alpha); - - vertexBuilder.vertex(vector3fs[1].x(), vector3fs[1].y(), vector3fs[1].z(), u1, v0, packedColor, light); - vertexBuilder.vertex(vector3fs[0].x(), vector3fs[0].y(), vector3fs[0].z(), u1, v1, packedColor, light); - vertexBuilder.vertex(vector3fs[3].x(), vector3fs[3].y(), vector3fs[3].z(), u0, v1, packedColor, light); - vertexBuilder.vertex(vector3fs[2].x(), vector3fs[2].y(), vector3fs[2].z(), u0, v0, packedColor, light); - } - - protected int getLightColor(float f) { - BlockPos blockPos = BlockPos.containing(this.x, this.y, this.z); - return this.level.hasChunkAt(blockPos) ? LevelRenderer.getLightColor(this.level, blockPos) : 0; - } - - private boolean cull(WorldRenderer worldRenderer, float x, float y, float z) { - RenderSection section = worldRenderer.getSectionGrid().getSectionAtBlockPos((int) x, (int) y, (int) z); - return section != null && section.getLastFrame() != worldRenderer.getLastFrame(); - } - - @Override - public ParticleRenderType getRenderType() { - return null; - } -} diff --git a/src/main/java/net/vulkanmod/mixin/render/shader/RenderPipelineM.java b/src/main/java/net/vulkanmod/mixin/render/shader/RenderPipelineM.java new file mode 100644 index 000000000..9bfea846a --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/shader/RenderPipelineM.java @@ -0,0 +1,35 @@ +package net.vulkanmod.mixin.render.shader; + +import com.mojang.blaze3d.pipeline.RenderPipeline; +import net.vulkanmod.interfaces.shader.ExtendedRenderPipeline; +import net.vulkanmod.render.engine.EGlProgram; +import net.vulkanmod.vulkan.shader.GraphicsPipeline; +import net.vulkanmod.vulkan.shader.Pipeline; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(RenderPipeline.class) +public abstract class RenderPipelineM implements ExtendedRenderPipeline { + @Unique GraphicsPipeline pipeline; + @Unique EGlProgram eGlProgram; + + @Override + public void setPipeline(GraphicsPipeline pipeline) { + this.pipeline = pipeline; + } + + @Override + public void setProgram(EGlProgram program) { + this.eGlProgram = program; + } + + @Override + public EGlProgram getProgram() { + return this.eGlProgram; + } + + @Override + public GraphicsPipeline getPipeline() { + return this.pipeline; + } +} diff --git a/src/main/java/net/vulkanmod/mixin/render/shader/ShaderManagerM.java b/src/main/java/net/vulkanmod/mixin/render/shader/ShaderManagerM.java new file mode 100644 index 000000000..4294266e7 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/render/shader/ShaderManagerM.java @@ -0,0 +1,32 @@ +package net.vulkanmod.mixin.render.shader; + +import com.llamalad7.mixinextras.sugar.Local; +import com.mojang.blaze3d.pipeline.CompiledRenderPipeline; +import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.blaze3d.systems.GpuDevice; +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.renderer.RenderPipelines; +import net.minecraft.client.renderer.ShaderManager; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.util.profiling.ProfilerFiller; +import net.vulkanmod.render.shader.CustomRenderPipelines; +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(ShaderManager.class) +public class ShaderManagerM { + + @Inject(method = "apply(Lnet/minecraft/client/renderer/ShaderManager$Configs;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V", + at = @At(value = "INVOKE", target = "Ljava/util/List;isEmpty()Z")) + private void onApply(ShaderManager.Configs configs, ResourceManager resourceManager, ProfilerFiller profilerFiller, + CallbackInfo ci, @Local ShaderManager.CompilationCache compilationCache) { + GpuDevice gpuDevice = RenderSystem.getDevice(); + var pipelines = CustomRenderPipelines.pipelines; + + for (RenderPipeline renderPipeline : pipelines) { + CompiledRenderPipeline compiledRenderPipeline = gpuDevice.precompilePipeline(renderPipeline, compilationCache::getShaderSource); + } + } +} diff --git a/src/main/java/net/vulkanmod/mixin/render/target/MainTargetMixin.java b/src/main/java/net/vulkanmod/mixin/render/target/MainTargetMixin.java index ff10c3d45..356500b53 100644 --- a/src/main/java/net/vulkanmod/mixin/render/target/MainTargetMixin.java +++ b/src/main/java/net/vulkanmod/mixin/render/target/MainTargetMixin.java @@ -2,9 +2,9 @@ import com.mojang.blaze3d.pipeline.MainTarget; import com.mojang.blaze3d.pipeline.RenderTarget; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.textures.*; import net.vulkanmod.vulkan.Renderer; -import net.vulkanmod.vulkan.Vulkan; -import net.vulkanmod.vulkan.framebuffer.SwapChain; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; @@ -12,7 +12,7 @@ public class MainTargetMixin extends RenderTarget { public MainTargetMixin(boolean useDepth) { - super(useDepth); + super("Main", useDepth); } /** @@ -21,24 +21,54 @@ public MainTargetMixin(boolean useDepth) { */ @Overwrite private void createFrameBuffer(int width, int height) { - this.viewWidth = width; - this.viewHeight = height; this.width = width; this.height = height; } @Override - public void bindWrite(boolean updateScissor) { - Renderer.getInstance().getMainPass().rebindMainTarget(); + public void createBuffers(int i, int j) { + RenderSystem.assertOnRenderThread(); + int k = RenderSystem.getDevice().getMaxTextureSize(); + if (i > 0 && i <= k && j > 0 && j <= k) { + this.width = i; + this.height = j; + if (this.useDepth) { + this.depthTexture = RenderSystem.getDevice().createTexture(() -> this.label + " / Depth", 15, TextureFormat.DEPTH32, i, j, 1, 1); + this.depthTexture.setTextureFilter(FilterMode.NEAREST, false); + this.depthTexture.setAddressMode(AddressMode.CLAMP_TO_EDGE); + } + + this.colorTexture = RenderSystem.getDevice().createTexture(() -> this.label + " / Color", 15, TextureFormat.RGBA8, i, j, 1, 1); + this.colorTexture.setAddressMode(AddressMode.CLAMP_TO_EDGE); + this.setFilterMode(FilterMode.NEAREST, true); + } else { + throw new IllegalArgumentException("Window " + i + "x" + j + " size out of bounds (max. size: " + k + ")"); + } + } + + private void setFilterMode(FilterMode filterMode, boolean bl) { + if (this.colorTexture == null) { + throw new IllegalStateException("Can't change filter mode, color texture doesn't exist yet"); + } else { + if (bl || filterMode != this.filterMode) { + this.filterMode = filterMode; + this.colorTexture.setTextureFilter(filterMode, false); + } + } + } + + @Override + public GpuTexture getColorTexture() { + return Renderer.getInstance().getMainPass().getColorAttachment(); } @Override - public void bindRead() { - Renderer.getInstance().getMainPass().bindAsTexture(); + public GpuTextureView getColorTextureView() { + return Renderer.getInstance().getMainPass().getColorAttachmentView(); } @Override - public int getColorTextureId() { - return Renderer.getInstance().getMainPass().getColorAttachmentGlId(); + public GpuTexture getDepthTexture() { + return Renderer.getInstance().getMainPass().getDepthAttachment(); } } diff --git a/src/main/java/net/vulkanmod/mixin/render/target/RenderTargetMixin.java b/src/main/java/net/vulkanmod/mixin/render/target/RenderTargetMixin.java index 9dd3134b4..310d64158 100644 --- a/src/main/java/net/vulkanmod/mixin/render/target/RenderTargetMixin.java +++ b/src/main/java/net/vulkanmod/mixin/render/target/RenderTargetMixin.java @@ -1,167 +1,57 @@ package net.vulkanmod.mixin.render.target; import com.mojang.blaze3d.pipeline.RenderTarget; -import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderPass; import com.mojang.blaze3d.systems.RenderSystem; -import net.vulkanmod.gl.GlFramebuffer; -import net.vulkanmod.gl.GlTexture; -import net.vulkanmod.interfaces.ExtendedRenderTarget; -import net.vulkanmod.vulkan.Renderer; -import net.vulkanmod.vulkan.framebuffer.Framebuffer; -import net.vulkanmod.vulkan.framebuffer.RenderPass; -import net.vulkanmod.vulkan.texture.VTextureSelector; -import net.vulkanmod.vulkan.util.DrawUtil; -import org.lwjgl.opengl.GL30; -import org.lwjgl.system.MemoryStack; +import com.mojang.blaze3d.textures.GpuTexture; +import com.mojang.blaze3d.textures.GpuTextureView; +import net.minecraft.client.renderer.RenderPipelines; +import net.vulkanmod.render.engine.VkFbo; +import net.vulkanmod.render.engine.VkGpuTexture; +import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.*; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.OptionalInt; @Mixin(RenderTarget.class) -public abstract class RenderTargetMixin implements ExtendedRenderTarget { +public abstract class RenderTargetMixin { - @Shadow public int viewWidth; - @Shadow public int viewHeight; @Shadow public int width; @Shadow public int height; - @Shadow protected int depthBufferId; - @Shadow protected int colorTextureId; - @Shadow public int frameBufferId; - - @Shadow @Final private float[] clearChannels; - @Shadow @Final public boolean useDepth; - - boolean needClear = false; - boolean bound = false; - - /** - * @author - */ - @Overwrite - public void clear(boolean getError) { - RenderSystem.assertOnRenderThreadOrInit(); - - if(!Renderer.isRecording()) - return; - - // If the framebuffer is not bound postpone clear - GlFramebuffer glFramebuffer = GlFramebuffer.getFramebuffer(this.frameBufferId); - if(!bound || GlFramebuffer.getBoundFramebuffer() != glFramebuffer) { - needClear = true; - return; - } - - GlStateManager._clearColor(this.clearChannels[0], this.clearChannels[1], this.clearChannels[2], this.clearChannels[3]); - int i = 16384; - if (this.useDepth) { - GlStateManager._clearDepth(1.0); - i |= 256; - } - - GlStateManager._clear(i, getError); - needClear = false; - } + @Shadow @Nullable protected GpuTexture colorTexture; + @Shadow @Nullable protected GpuTexture depthTexture; + @Shadow @Nullable protected GpuTextureView colorTextureView; - /** - * @author - */ @Overwrite - public void bindRead() { + public void blitAndBlendToTexture(GpuTextureView gpuTextureView) { RenderSystem.assertOnRenderThread(); - applyClear(); - - GlTexture.bindTexture(this.colorTextureId); - - try (MemoryStack stack = MemoryStack.stackPush()) { - GlTexture.getBoundTexture().getVulkanImage() - .readOnlyLayout(stack, Renderer.getCommandBuffer()); - } - } - - /** - * @author - */ - @Overwrite - public void unbindRead() { - RenderSystem.assertOnRenderThreadOrInit(); - GlTexture.bindTexture(0); - } - - /** - * @author - */ - @Overwrite - private void _bindWrite(boolean bl) { - RenderSystem.assertOnRenderThreadOrInit(); - - GlFramebuffer.bindFramebuffer(GL30.GL_FRAMEBUFFER, this.frameBufferId); - if (bl) { - GlStateManager._viewport(0, 0, this.viewWidth, this.viewHeight); - } - - this.bound = true; - if (needClear) - clear(false); - } - - /** - * @author - */ - @Overwrite - public void unbindWrite() { - if (!RenderSystem.isOnRenderThread()) { - RenderSystem.recordRenderCall(() -> { - GlStateManager._glBindFramebuffer(36160, 0); - this.bound = false; - }); - } else { - GlStateManager._glBindFramebuffer(36160, 0); - this.bound = false; + VkFbo fbo = ((VkGpuTexture) this.colorTexture).getFbo(this.depthTexture); + if (fbo.needsClear()) { + return; } - } - @Inject(method = "_blitToScreen", at = @At("HEAD"), cancellable = true) - private void _blitToScreen(int width, int height, boolean disableBlend, CallbackInfo ci) { - // If the target needs clear it means it has not been used, thus we can skip blit - if (!this.needClear) { - Framebuffer framebuffer = GlFramebuffer.getFramebuffer(this.frameBufferId).getFramebuffer(); - VTextureSelector.bindTexture(0, framebuffer.getColorAttachment()); - - DrawUtil.blitToScreen(); + try (RenderPass renderPass = RenderSystem.getDevice() + .createCommandEncoder() + .createRenderPass(() -> "Blit render target", gpuTextureView, OptionalInt.empty())) { + renderPass.setPipeline(RenderPipelines.ENTITY_OUTLINE_BLIT); + RenderSystem.bindDefaultUniforms(renderPass); + renderPass.bindSampler("InSampler", this.colorTextureView); + renderPass.draw(0, 3); } - - ci.cancel(); } - @Inject(method = "getColorTextureId", at = @At("HEAD")) - private void injClear(CallbackInfoReturnable cir) { - applyClear(); - } - - @Override - public boolean isBound() { - return bound; - } - - @Override - public RenderPass getRenderPass() { - return GlFramebuffer.getFramebuffer(this.frameBufferId).getRenderPass(); - } - - @Unique - private void applyClear() { - if (this.needClear) { - GlFramebuffer currentFramebuffer = GlFramebuffer.getBoundFramebuffer(); - - this._bindWrite(false); - - if (currentFramebuffer != null) { - GlFramebuffer.beginRendering(currentFramebuffer); - } - } - } +// @Inject(method = "getColorTextureView", at = @At("HEAD")) +// private void injClear(CallbackInfoReturnable cir) { +// applyClear(); +// } +// +// @Unique +// private void applyClear() { +// VkFbo fbo = ((VkGpuTexture) this.colorTexture).getFbo(this.depthTexture); +// if (fbo.needsClear()) { +// fbo.bind(); +// } +// } } diff --git a/src/main/java/net/vulkanmod/mixin/render/vertex/BufferBuilderM.java b/src/main/java/net/vulkanmod/mixin/render/vertex/BufferBuilderM.java index 4f7335a4c..9bb93a893 100644 --- a/src/main/java/net/vulkanmod/mixin/render/vertex/BufferBuilderM.java +++ b/src/main/java/net/vulkanmod/mixin/render/vertex/BufferBuilderM.java @@ -1,13 +1,16 @@ package net.vulkanmod.mixin.render.vertex; import com.mojang.blaze3d.vertex.*; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.core.Vec3i; import net.vulkanmod.interfaces.ExtendedVertexBuilder; -import net.vulkanmod.render.vertex.VertexUtil; +import net.vulkanmod.mixin.matrix.PoseAccessor; +import net.vulkanmod.render.util.MathUtil; +import net.vulkanmod.render.vertex.format.I32_SNorm; +import net.vulkanmod.vulkan.util.ColorUtil; +import org.joml.Matrix4f; import org.lwjgl.system.MemoryUtil; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.*; @Mixin(BufferBuilder.class) public abstract class BufferBuilderM @@ -143,11 +146,65 @@ public void addVertex(float x, float y, float z, int color, float u, float v, in MemoryUtil.memPutInt(ptr + i, light); - int temp = VertexUtil.packNormal(normalX, normalY, normalZ); + int temp = I32_SNorm.packNormal(normalX, normalY, normalZ); MemoryUtil.memPutInt(ptr + i + 4, temp); } else { VertexConsumer.super.addVertex(x, y, z, color, u, v, overlay, light, normalX, normalY, normalZ); } } + @Override + public void putBulkData(PoseStack.Pose matrixEntry, BakedQuad quad, float[] brightness, float red, float green, + float blue, float alpha, int[] lights, int overlay, boolean useQuadColorData) { + putQuadData(matrixEntry, quad, brightness, red, green, blue, alpha, lights, overlay, useQuadColorData); + } + + @SuppressWarnings("UnreachableCode") + @Unique + private void putQuadData(PoseStack.Pose matrixEntry, BakedQuad quad, float[] brightness, float red, float green, float blue, float alpha, int[] lights, int overlay, boolean useQuadColorData) { + int[] quadData = quad.vertices(); + Vec3i vec3i = quad.direction().getUnitVec3i(); + Matrix4f matrix4f = matrixEntry.pose(); + + boolean trustedNormals = ((PoseAccessor)(Object)matrixEntry).trustedNormals(); + int normal = MathUtil.packTransformedNorm(matrixEntry.normal(), trustedNormals, vec3i.getX(), vec3i.getY(), vec3i.getZ()); + + for (int k = 0; k < 4; ++k) { + float r, g, b; + + float quadR, quadG, quadB; + + int i = k * 8; + float x = Float.intBitsToFloat(quadData[i]); + float y = Float.intBitsToFloat(quadData[i + 1]); + float z = Float.intBitsToFloat(quadData[i + 2]); + + float tx = MathUtil.transformX(matrix4f, x, y, z); + float ty = MathUtil.transformY(matrix4f, x, y, z); + float tz = MathUtil.transformZ(matrix4f, x, y, z); + + if (useQuadColorData) { + int color = quadData[i + 3]; + quadR = ColorUtil.RGBA.unpackR(color); + quadG = ColorUtil.RGBA.unpackG(color); + quadB = ColorUtil.RGBA.unpackB(color); + r = quadR * brightness[k] * red; + g = quadG * brightness[k] * green; + b = quadB * brightness[k] * blue; + } else { + r = brightness[k] * red; + g = brightness[k] * green; + b = brightness[k] * blue; + } + + int color = ColorUtil.RGBA.pack(r, g, b, alpha); + + int light = lights[k]; + float u = Float.intBitsToFloat(quadData[i + 4]); + float v = Float.intBitsToFloat(quadData[i + 5]); + + this.vertex(tx, ty, tz, color, u, v, overlay, light, normal); + } + } + } diff --git a/src/main/java/net/vulkanmod/mixin/render/vertex/FaceBakeryM.java b/src/main/java/net/vulkanmod/mixin/render/vertex/FaceBakeryM.java deleted file mode 100644 index b3262bb89..000000000 --- a/src/main/java/net/vulkanmod/mixin/render/vertex/FaceBakeryM.java +++ /dev/null @@ -1,80 +0,0 @@ -package net.vulkanmod.mixin.render.vertex; - -import com.mojang.math.*; -import net.minecraft.client.renderer.FaceInfo; -import net.minecraft.client.renderer.block.model.BlockFaceUV; -import net.minecraft.client.renderer.block.model.FaceBakery; -import net.minecraft.core.BlockMath; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; -import org.joml.Matrix3f; -import org.joml.Matrix4f; -import org.joml.Vector3f; -import org.joml.Vector4f; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -@Mixin(FaceBakery.class) -public class FaceBakeryM { - - private static final float DIV = 1.0f / 16.0f; - private static final double DIV_2 = 1.0 / 90.0; - - /** - * @author - */ - @Overwrite - private float[] setupShape(Vector3f vector3f, Vector3f vector3f2) { - float[] fs = new float[Direction.values().length]; - fs[FaceInfo.Constants.MIN_X] = vector3f.x() * DIV; - fs[FaceInfo.Constants.MIN_Y] = vector3f.y() * DIV; - fs[FaceInfo.Constants.MIN_Z] = vector3f.z() * DIV; - fs[FaceInfo.Constants.MAX_X] = vector3f2.x() * DIV; - fs[FaceInfo.Constants.MAX_Y] = vector3f2.y() * DIV; - fs[FaceInfo.Constants.MAX_Z] = vector3f2.z() * DIV; - return fs; - } - - /** - * @author - */ - @Overwrite - public static BlockFaceUV recomputeUVs(BlockFaceUV blockFaceUV, Direction direction, Transformation transformation) { - Matrix4f matrix4f = BlockMath.getUVLockTransform(transformation, direction).getMatrix(); - float f = blockFaceUV.getU(blockFaceUV.getReverseIndex(0)); - float g = blockFaceUV.getV(blockFaceUV.getReverseIndex(0)); - Vector4f vector4f = matrix4f.transform(new Vector4f(f * DIV, g * DIV, 0.0F, 1.0F)); - float h = 16.0F * vector4f.x(); - float i = 16.0F * vector4f.y(); - float j = blockFaceUV.getU(blockFaceUV.getReverseIndex(2)); - float k = blockFaceUV.getV(blockFaceUV.getReverseIndex(2)); - Vector4f vector4f2 = matrix4f.transform(new Vector4f(j * DIV, k * DIV, 0.0F, 1.0F)); - float l = 16.0F * vector4f2.x(); - float m = 16.0F * vector4f2.y(); - float n; - float o; - if (Math.signum(j - f) == Math.signum(l - h)) { - n = h; - o = l; - } else { - n = l; - o = h; - } - - float p; - float q; - if (Math.signum(k - g) == Math.signum(m - i)) { - p = i; - q = m; - } else { - p = m; - q = i; - } - - float r = (float)Math.toRadians(blockFaceUV.rotation); - Matrix3f matrix3f = new Matrix3f(matrix4f); - Vector3f vector3f = matrix3f.transform(new Vector3f(Mth.cos(r), Mth.sin(r), 0.0F)); - int s = Math.floorMod(-((int)Math.round(Math.toDegrees(Math.atan2(vector3f.y(), vector3f.x())) * DIV_2)) * 90, 360); - return new BlockFaceUV(new float[]{n, p, o, q}, s); - } -} diff --git a/src/main/java/net/vulkanmod/mixin/render/vertex/VertexBufferM.java b/src/main/java/net/vulkanmod/mixin/render/vertex/VertexBufferM.java deleted file mode 100644 index e9da55500..000000000 --- a/src/main/java/net/vulkanmod/mixin/render/vertex/VertexBufferM.java +++ /dev/null @@ -1,87 +0,0 @@ -package net.vulkanmod.mixin.render.vertex; - -import com.mojang.blaze3d.vertex.ByteBufferBuilder; -import com.mojang.blaze3d.vertex.MeshData; -import com.mojang.blaze3d.vertex.VertexBuffer; -import net.minecraft.client.renderer.ShaderInstance; -import net.vulkanmod.render.VBO; -import org.joml.Matrix4f; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(VertexBuffer.class) -public class VertexBufferM { - - private VBO vbo; - - @Inject(method = "", at = @At("RETURN")) - private void constructor(VertexBuffer.Usage usage, CallbackInfo ci) { - vbo = new VBO(); - } - - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_glGenBuffers()I")) - private int doNothing() { - return 0; - } - - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_glGenVertexArrays()I")) - private int doNothing2() { - return 0; - } - - /** - * @author - */ - @Overwrite - public void bind() {} - - /** - * @author - */ - @Overwrite - public static void unbind() {} - - /** - * @author - */ - @Overwrite - public void upload(MeshData meshData) { - vbo.upload(meshData); - } - - /** - * @author - */ - @Overwrite - public void uploadIndexBuffer(ByteBufferBuilder.Result result) { - vbo.uploadIndexBuffer(result.byteBuffer()); - } - - /** - * @author - */ - @Overwrite - public void drawWithShader(Matrix4f viewMatrix, Matrix4f projectionMatrix, ShaderInstance shader) { - vbo.drawWithShader(viewMatrix, projectionMatrix, shader); - } - - /** - * @author - */ - @Overwrite - public void draw() { - vbo.draw(); - } - - /** - * @author - */ - @Overwrite - public void close() { - vbo.close(); - } -} diff --git a/src/main/java/net/vulkanmod/mixin/render/vertex/VertexConsumerM.java b/src/main/java/net/vulkanmod/mixin/render/vertex/VertexConsumerM.java deleted file mode 100644 index c3ec70b34..000000000 --- a/src/main/java/net/vulkanmod/mixin/render/vertex/VertexConsumerM.java +++ /dev/null @@ -1,71 +0,0 @@ -package net.vulkanmod.mixin.render.vertex; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import net.minecraft.client.renderer.block.model.BakedQuad; -import net.minecraft.core.Vec3i; -import net.vulkanmod.render.vertex.VertexUtil; -import net.vulkanmod.vulkan.util.ColorUtil; -import org.joml.Matrix4f; -import org.joml.Vector3f; -import org.joml.Vector4f; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(VertexConsumer.class) -public interface VertexConsumerM { - - - @Shadow void addVertex(float f, float g, float h, int i, float j, float k, int l, int m, float n, float o, float p); - - /** - * @author - */ - @Overwrite - default void putBulkData(PoseStack.Pose matrixEntry, BakedQuad quad, float[] brightness, float red, float green, float blue, float alpha, int[] lights, int overlay, boolean useQuadColorData) { - int[] js = quad.getVertices(); - Vec3i vec3i = quad.getDirection().getNormal(); - Vector3f normal = new Vector3f(vec3i.getX(), vec3i.getY(), vec3i.getZ()); - Matrix4f matrix4f = matrixEntry.pose(); - normal.mul(matrixEntry.normal()); - - int j = js.length / 8; - - for (int k = 0; k < j; ++k) { - float r, g, b; - - float quadR, quadG, quadB; - - int i = k * 8; - float x = Float.intBitsToFloat(js[i]); - float y = Float.intBitsToFloat(js[i + 1]); - float z = Float.intBitsToFloat(js[i + 2]); - - if (useQuadColorData) { - quadR = ColorUtil.RGBA.unpackR(js[i + 3]); - quadG = ColorUtil.RGBA.unpackG(js[i + 3]); - quadB = ColorUtil.RGBA.unpackB(js[i + 3]); - r = quadR * brightness[k] * red; - g = quadG * brightness[k] * green; - b = quadB * brightness[k] * blue; - } else { - r = brightness[k] * red; - g = brightness[k] * green; - b = brightness[k] * blue; - } - - int color = ColorUtil.RGBA.pack(r, g, b, alpha); - - int light = lights[k]; - float u = Float.intBitsToFloat(js[i + 4]); - float v = Float.intBitsToFloat(js[i + 5]); - - Vector4f vector4f = new Vector4f(x, y, z, 1.0f); - vector4f.mul(matrix4f); - - this.addVertex(vector4f.x(), vector4f.y(), vector4f.z(), color, u, v, overlay, light, normal.x(), normal.y(), normal.z()); - } - - } -} diff --git a/src/main/java/net/vulkanmod/mixin/screen/ScreenM.java b/src/main/java/net/vulkanmod/mixin/screen/ScreenM.java index e41785636..49043c5d8 100644 --- a/src/main/java/net/vulkanmod/mixin/screen/ScreenM.java +++ b/src/main/java/net/vulkanmod/mixin/screen/ScreenM.java @@ -11,7 +11,7 @@ public class ScreenM { @Inject(method = "renderBlurredBackground", at = @At("RETURN")) - private void clearDepth(float f, CallbackInfo ci) { + private void clearDepth(CallbackInfo ci) { // Workaround to fix hardcoded z value on PostPass blit shader, // that conflicts with Vulkan depth range [0.0, 1.0] Renderer.clearAttachments(256); diff --git a/src/main/java/net/vulkanmod/mixin/texture/MAbstractTexture.java b/src/main/java/net/vulkanmod/mixin/texture/MAbstractTexture.java deleted file mode 100644 index 634ce1af3..000000000 --- a/src/main/java/net/vulkanmod/mixin/texture/MAbstractTexture.java +++ /dev/null @@ -1,50 +0,0 @@ -package net.vulkanmod.mixin.texture; - -import com.mojang.blaze3d.systems.RenderSystem; -import net.minecraft.client.renderer.texture.AbstractTexture; -import net.vulkanmod.gl.GlTexture; -import net.vulkanmod.vulkan.texture.VulkanImage; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(AbstractTexture.class) -public abstract class MAbstractTexture { - @Shadow protected boolean blur; - @Shadow protected boolean mipmap; - - @Shadow protected int id; - - /** - * @author - */ - @Overwrite - public void bind() { - if (!RenderSystem.isOnRenderThreadOrInit()) { - RenderSystem.recordRenderCall(this::bindTexture); - } else { - this.bindTexture(); - } - } - - /** - * @author - */ - @Overwrite - public void setFilter(boolean blur, boolean mipmap) { - if (blur != this.blur || mipmap != this.mipmap) { - this.blur = blur; - this.mipmap = mipmap; - - GlTexture glTexture = GlTexture.getTexture(this.id); - VulkanImage vulkanImage = glTexture.getVulkanImage(); - - if (vulkanImage != null) - vulkanImage.updateTextureSampler(this.blur, false, this.mipmap); - } - } - - private void bindTexture() { - GlTexture.bindTexture(this.id); - } -} diff --git a/src/main/java/net/vulkanmod/mixin/texture/MSpriteContents.java b/src/main/java/net/vulkanmod/mixin/texture/MSpriteContents.java deleted file mode 100644 index 8148c95f6..000000000 --- a/src/main/java/net/vulkanmod/mixin/texture/MSpriteContents.java +++ /dev/null @@ -1,22 +0,0 @@ -package net.vulkanmod.mixin.texture; - -import com.mojang.blaze3d.platform.NativeImage; -import net.minecraft.client.renderer.texture.SpriteContents; -import net.vulkanmod.render.texture.SpriteUtil; -import net.vulkanmod.vulkan.texture.VTextureSelector; -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(SpriteContents.class) -public class MSpriteContents { - - @Inject(method = "upload", at = @At("HEAD"), cancellable = true) - private void checkUpload(int i, int j, int k, int l, NativeImage[] nativeImages, CallbackInfo ci) { - if(!SpriteUtil.shouldUpload()) - ci.cancel(); - - SpriteUtil.addTransitionedLayout(VTextureSelector.getBoundTexture(0)); - } -} diff --git a/src/main/java/net/vulkanmod/mixin/texture/MTextureUtil.java b/src/main/java/net/vulkanmod/mixin/texture/MTextureUtil.java deleted file mode 100644 index 395c3cdc1..000000000 --- a/src/main/java/net/vulkanmod/mixin/texture/MTextureUtil.java +++ /dev/null @@ -1,58 +0,0 @@ -package net.vulkanmod.mixin.texture; - -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.platform.NativeImage; -import com.mojang.blaze3d.platform.TextureUtil; -import com.mojang.blaze3d.systems.RenderSystem; -import net.vulkanmod.gl.GlTexture; -import net.vulkanmod.vulkan.texture.VTextureSelector; -import net.vulkanmod.vulkan.texture.VulkanImage; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL30; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -@Mixin(TextureUtil.class) -public class MTextureUtil { - - /** - * @author - */ - @Overwrite(remap = false) - public static int generateTextureId() { - RenderSystem.assertOnRenderThreadOrInit(); - return GlTexture.genTextureId(); - } - - /** - * @author - */ - @Overwrite(remap = false) - public static void prepareImage(NativeImage.InternalGlFormat internalGlFormat, int id, int mipLevels, int width, int height) { - RenderSystem.assertOnRenderThreadOrInit(); - GlTexture.bindTexture(id); - GlTexture glTexture = GlTexture.getBoundTexture(); - VulkanImage image = glTexture.getVulkanImage(); - - if (mipLevels > 0) { - GlStateManager._texParameter(GL11.GL_TEXTURE_2D, GL30.GL_TEXTURE_MAX_LEVEL, mipLevels); - GlStateManager._texParameter(GL11.GL_TEXTURE_2D, GL30.GL_TEXTURE_MIN_LOD, 0); - GlStateManager._texParameter(GL11.GL_TEXTURE_2D, GL30.GL_TEXTURE_MAX_LOD, mipLevels); - GlStateManager._texParameter(GL11.GL_TEXTURE_2D, GL30.GL_TEXTURE_LOD_BIAS, 0.0F); - } - - if (image == null || image.mipLevels != mipLevels || image.width != width || image.height != height) { - if (image != null) - image.free(); - - image = new VulkanImage.Builder(width, height) - .setMipLevels(mipLevels + 1) - .setLinearFiltering(false) - .setClamp(false) - .createVulkanImage(); - - glTexture.setVulkanImage(image); - VTextureSelector.bindTexture(image); - } - } -} diff --git a/src/main/java/net/vulkanmod/mixin/texture/image/MNativeImage.java b/src/main/java/net/vulkanmod/mixin/texture/image/MNativeImage.java deleted file mode 100644 index cc4537bcd..000000000 --- a/src/main/java/net/vulkanmod/mixin/texture/image/MNativeImage.java +++ /dev/null @@ -1,104 +0,0 @@ -package net.vulkanmod.mixin.texture.image; - -import com.mojang.blaze3d.platform.NativeImage; -import com.mojang.blaze3d.systems.RenderSystem; -import net.vulkanmod.vulkan.Vulkan; -import net.vulkanmod.vulkan.texture.ImageUtil; -import net.vulkanmod.vulkan.texture.VTextureSelector; -import net.vulkanmod.vulkan.texture.VulkanImage; -import net.vulkanmod.vulkan.util.ColorUtil; -import org.lwjgl.system.MemoryUtil; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.nio.ByteBuffer; -import java.util.Locale; - -@Mixin(NativeImage.class) -public abstract class MNativeImage { - - @Shadow private long pixels; - @Shadow private long size; - - @Shadow public abstract void close(); - - - @Shadow @Final private NativeImage.Format format; - - @Shadow public abstract int getWidth(); - - @Shadow @Final private int width; - @Shadow @Final private int height; - - @Shadow public abstract int getHeight(); - - @Shadow public abstract void setPixelRGBA(int i, int j, int k); - - @Shadow public abstract int getPixelRGBA(int i, int j); - - @Shadow protected abstract void checkAllocated(); - - private ByteBuffer buffer; - - @Inject(method = "(Lcom/mojang/blaze3d/platform/NativeImage$Format;IIZ)V", at = @At("RETURN")) - private void constr(NativeImage.Format format, int width, int height, boolean useStb, CallbackInfo ci) { - if(this.pixels != 0) { - buffer = MemoryUtil.memByteBuffer(this.pixels, (int)this.size); - } - } - - @Inject(method = "(Lcom/mojang/blaze3d/platform/NativeImage$Format;IIZJ)V", at = @At("RETURN")) - private void constr(NativeImage.Format format, int width, int height, boolean useStb, long pixels, CallbackInfo ci) { - if(this.pixels != 0) { - buffer = MemoryUtil.memByteBuffer(this.pixels, (int)this.size); - } - } - - /** - * @author - */ - @Overwrite - private void _upload(int level, int xOffset, int yOffset, int unpackSkipPixels, int unpackSkipRows, int widthIn, int heightIn, boolean blur, boolean clamp, boolean mipmap, boolean autoClose) { - RenderSystem.assertOnRenderThreadOrInit(); - - VTextureSelector.uploadSubTexture(level, widthIn, heightIn, xOffset, yOffset, unpackSkipRows, unpackSkipPixels, this.getWidth(), this.buffer); - - if (autoClose) { - this.close(); - } - } - - /** - * @author - */ - @Overwrite - public void downloadTexture(int level, boolean removeAlpha) { - RenderSystem.assertOnRenderThread(); - - ImageUtil.downloadTexture(VTextureSelector.getBoundTexture(0), this.pixels); - - if (removeAlpha && this.format.hasAlpha()) { - if (this.format != NativeImage.Format.RGBA) { - throw new IllegalArgumentException(String.format(Locale.ROOT, "getPixelRGBA only works on RGBA images; have %s", this.format)); - } - - for (long l = 0; l < this.width * this.height * 4L; l+=4) { - int v = MemoryUtil.memGetInt(this.pixels + l); - - //TODO - if(Vulkan.getSwapChain().isBGRAformat) - v = ColorUtil.BGRAtoRGBA(v); - - v = v | 255 << this.format.alphaOffset(); - MemoryUtil.memPutInt(this.pixels + l, v); - } - } - - } - -} diff --git a/src/main/java/net/vulkanmod/mixin/texture/update/MLightTexture.java b/src/main/java/net/vulkanmod/mixin/texture/update/MLightTexture.java new file mode 100644 index 000000000..6cd861797 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/texture/update/MLightTexture.java @@ -0,0 +1,247 @@ +package net.vulkanmod.mixin.texture.update; + +import com.mojang.blaze3d.platform.NativeImage; +import com.mojang.blaze3d.systems.CommandEncoder; +import com.mojang.blaze3d.systems.GpuDevice; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.textures.GpuTextureView; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.texture.DynamicTexture; +import net.minecraft.util.Mth; +import net.minecraft.util.profiling.Profiler; +import net.minecraft.util.profiling.ProfilerFiller; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.LivingEntity; +import net.vulkanmod.gl.VkGlTexture; +import net.vulkanmod.mixin.texture.image.NativeImageAccessor; +import net.vulkanmod.render.engine.VkGpuTexture; +import net.vulkanmod.render.texture.ImageUploadHelper; +import net.vulkanmod.vulkan.queue.CommandPool; +import org.joml.Vector3f; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.system.MemoryUtil; +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(LightTexture.class) +public class MLightTexture { + @Unique private static final Vector3f END_FLASH_SKY_LIGHT_COLOR = new Vector3f(0.9F, 0.5F, 1.0F); + + @Shadow @Final private Minecraft minecraft; + @Shadow @Final private GameRenderer renderer; + + @Shadow private boolean updateLightTexture; + @Shadow private float blockLightRedFlicker; + + @Unique private DynamicTexture lightTexture; + @Unique private GpuTextureView textureView; + @Unique private NativeImage lightPixels; + + private Vector3f[] tempVecs; + +// @Inject(method = "", at = @At("RETURN")) +// private void onInit(GameRenderer gameRenderer, Minecraft minecraft, CallbackInfo ci) { +// initLightMap(); +// +// this.tempVecs = new Vector3f[]{new Vector3f(), new Vector3f(), new Vector3f()}; +// } +// +// private void initLightMap() { +// GpuDevice gpuDevice = RenderSystem.getDevice(); +// this.lightTexture = new DynamicTexture("Light Texture", 16, 16, false); +// this.textureView = gpuDevice.createTextureView(this.lightTexture.getTexture()); +// this.lightPixels = this.lightTexture.getPixels(); +// +// for(int i = 0; i < 16; ++i) { +// for(int j = 0; j < 16; ++j) { +// this.lightPixels.setPixel(j, i, 0xFFFFFFFF); +// } +// } +// +// this.lightTexture.upload(); +// } +// +// /** +// * @author +// * @reason +// */ +// @Overwrite +// public void turnOnLightLayer() { +// RenderSystem.setShaderTexture(2, this.textureView); +// } + + // TODO +// @SuppressWarnings("UnreachableCode") +// @Inject(method = "updateLightTexture", at = @At("HEAD"), cancellable = true) +// public void updateLightTexture(float partialTicks, CallbackInfo ci) { +// if (this.updateLightTexture) { +// this.updateLightTexture = false; +// +// ProfilerFiller profilerFiller = Profiler.get(); +// profilerFiller.push("lightTex"); +// +// // TODO: Other mods might be changing lightmap behaviour, we can't be aware of that here +// +// ClientLevel clientLevel = this.minecraft.level; +// if (clientLevel != null) { +// float skyDarken = clientLevel.getSkyDarken(1.0F); +// float skyFlashTime; +// if (clientLevel.getSkyFlashTime() > 0) { +// skyFlashTime = 1.0F; +// } else { +// skyFlashTime = skyDarken * 0.95F + 0.05F; +// } +// +// float darknessEffectScale = this.minecraft.options.darknessEffectScale().get().floatValue(); +// float darknessGamma = this.getDarknessGamma(partialTicks) * darknessEffectScale; +// float darknessScale = this.calculateDarknessScale(this.minecraft.player, darknessGamma, partialTicks) * darknessEffectScale; +// float waterVision = this.minecraft.player.getWaterVision(); +// float nightVisionFactor; +// if (this.minecraft.player.hasEffect(MobEffects.NIGHT_VISION)) { +// nightVisionFactor = GameRenderer.getNightVisionScale(this.minecraft.player, partialTicks); +// } else if (waterVision > 0.0F && this.minecraft.player.hasEffect(MobEffects.CONDUIT_POWER)) { +// nightVisionFactor = waterVision; +// } else { +// nightVisionFactor = 0.0F; +// } +// +//// Vector3f skyLightColor = new Vector3f(skyDarken, skyDarken, 1.0F).lerp(new Vector3f(1.0F, 1.0F, 1.0F), 0.35F); +// skyDarken = lerp(skyDarken, 1.0f, 0.35f); +// Vector3f skyLightColor = this.tempVecs[0].set(skyDarken, skyDarken, 1.0F); +// float redFlicker = this.blockLightRedFlicker + 1.5F; +// Vector3f lightColor = this.tempVecs[1]; +// +// float gamma = this.minecraft.options.gamma().get().floatValue(); +// float darkenWorldAmount = this.renderer.getDarkenWorldAmount(partialTicks); +//// boolean forceBrightLightmap = clientLevel.effects().forceBrightLightmap(); +// float ambientLight = clientLevel.dimensionType().ambientLight(); +// +// Vector3f vector3f2; +// if (clientLevel.effects().hasEndFlashes()) { +// vector3f2 = END_FLASH_SKY_LIGHT_COLOR; +// } else { +// vector3f2 = (new Vector3f(g, g, 1.0F)).lerp(new Vector3f(1.0F, 1.0F, 1.0F), 0.35F); +// } +// +// float n = this.blockLightRedFlicker + 1.5F; +// float o = clientLevel.dimensionType().ambientLight(); +// float p = ((Double)this.minecraft.options.gamma().get()).floatValue(); +// CommandEncoder commandEncoder = RenderSystem.getDevice().createCommandEncoder(); +// +// long ptr = ((NativeImageAccessor)(Object)this.lightPixels).getPixels(); +// int width = this.lightPixels.getWidth(); +// +// Vector3f tVec3f = this.tempVecs[2]; +// +// for(int y = 0; y < 16; ++y) { +// float brY = getBrightness(ambientLight, y) * skyFlashTime; +// +// for(int x = 0; x < 16; ++x) { +// float brX = getBrightness(ambientLight, x) * redFlicker; +// float t = brX * ((brX * 0.6F + 0.4F) * 0.6F + 0.4F); +// float u = brX * (brX * brX * 0.6F + 0.4F); +// lightColor.set(brX, t, u); +// +// if (forceBrightLightmap) { +// lightColor.lerp(tVec3f.set(0.99F, 1.12F, 1.0F), 0.25F); +// clampColor(lightColor); +// } else { +// tVec3f.set(skyLightColor).mul(brY); +// lightColor.add(tVec3f); +// +// tVec3f.set(0.75F, 0.75F, 0.75F); +// lightColor.lerp(tVec3f, 0.04F); +// +// if (darkenWorldAmount > 0.0F) { +// tVec3f.set(lightColor).mul(0.7F, 0.6F, 0.6F); +// lightColor.lerp(tVec3f, darkenWorldAmount); +// } +// } +// +// if (nightVisionFactor > 0.0F) { +// // scale up uniformly until 1.0 is hit by one of the colors +// float maxComponent = Math.max(lightColor.x(), Math.max(lightColor.y(), lightColor.z())); +// if (maxComponent < 1.0F) { +// float brightColor = 1.0F / maxComponent; +// tVec3f.set(lightColor).mul(brightColor); +// lightColor.lerp(tVec3f, nightVisionFactor); +// } +// } +// +// if (!forceBrightLightmap) { +// lightColor.add(-darknessScale, -darknessScale, -darknessScale); +// clampColor(lightColor); +// } +// +// tVec3f.set(this.notGamma(lightColor.x), this.notGamma(lightColor.y), this.notGamma(lightColor.z)); +// lightColor.lerp(tVec3f, Math.max(0.0F, gamma - darknessGamma)); +// +// lightColor.lerp(tVec3f.set(0.75F, 0.75F, 0.75F), 0.04F); +// clampColor(lightColor); +// +// lightColor.mul(255.0F); +// int r = (int)lightColor.x(); +// int g = (int)lightColor.y(); +// int b = (int)lightColor.z(); +// +// MemoryUtil.memPutInt(ptr + (((long) y * width + x) * 4L), 0xFF000000 | b << 16 | g << 8 | r); +// } +// } +// +// CommandPool.CommandBuffer commandBuffer = ImageUploadHelper.INSTANCE.getOrStartCommandBuffer(); +// this.lightTexture.upload(); +// +// try (MemoryStack stack = MemoryStack.stackPush()) { +// VkGlTexture.getTexture(((VkGpuTexture)this.lightTexture.getTexture()).glId()).getVulkanImage().readOnlyLayout(stack, commandBuffer.getHandle()); +// } +// +// profilerFiller.pop(); +// } +// } +// +// ci.cancel(); +// } + + @Unique + private float getDarknessGamma(float f) { + MobEffectInstance mobEffectInstance = this.minecraft.player.getEffect(MobEffects.DARKNESS); + return mobEffectInstance != null ? mobEffectInstance.getBlendFactor(this.minecraft.player, f) : 0.0F; + } + + @Unique + private float calculateDarknessScale(LivingEntity livingEntity, float f, float g) { + float h = 0.45F * f; + return Math.max(0.0F, Mth.cos(((float)livingEntity.tickCount - g) * (float) Math.PI * 0.025F) * h); + } + + @Unique + private static float lerp(float a, float x, float t) { + return (x - a) * t + a; + } + + @Unique + private static void clampColor(Vector3f vector3f) { + vector3f.set(Mth.clamp(vector3f.x, 0.0F, 1.0F), Mth.clamp(vector3f.y, 0.0F, 1.0F), Mth.clamp(vector3f.z, 0.0F, 1.0F)); + } + + @Unique + private float notGamma(float f) { + float g = 1.0F - f; + g = g * g; + return 1.0F - g * g; + } + + @Unique + private static float getBrightness(float ambientLight, int i) { + float f = (float)i / 15.0F; + float g = f / (4.0F - 3.0F * f); + return Mth.lerp(ambientLight, g, 1.0F); + } + +} diff --git a/src/main/java/net/vulkanmod/mixin/texture/update/MSpriteContents.java b/src/main/java/net/vulkanmod/mixin/texture/update/MSpriteContents.java new file mode 100644 index 000000000..1389df367 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/texture/update/MSpriteContents.java @@ -0,0 +1,38 @@ +package net.vulkanmod.mixin.texture.update; + +import com.mojang.blaze3d.textures.GpuTexture; +import net.minecraft.client.renderer.texture.SpriteContents; +import net.vulkanmod.render.engine.VkGpuTexture; +import net.vulkanmod.render.texture.SpriteUpdateUtil; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(SpriteContents.Ticker.class) +public class MSpriteContents { + + @Shadow int subFrame; + @Shadow int frame; + @Shadow @Final SpriteContents.AnimatedTexture animationInfo; + + @Inject(method = "tickAndUpload", at = @At("HEAD"), cancellable = true) + private void checkUpload(int i, int j, GpuTexture gpuTexture, CallbackInfo ci) { + if (!SpriteUpdateUtil.doUploadFrame()) { + // Update animations frames even if no upload is scheduled + ++this.subFrame; + SpriteContents.FrameInfo frameInfo = this.animationInfo.frames.get(this.frame); + if (this.subFrame >= frameInfo.time) { + this.frame = (this.frame + 1) % this.animationInfo.frames.size(); + this.subFrame = 0; + } + + ci.cancel(); + } + else { + SpriteUpdateUtil.addTransitionedLayout(((VkGpuTexture) gpuTexture).getVulkanImage()); + } + } +} diff --git a/src/main/java/net/vulkanmod/mixin/texture/MTextureManager.java b/src/main/java/net/vulkanmod/mixin/texture/update/MTextureManager.java similarity index 58% rename from src/main/java/net/vulkanmod/mixin/texture/MTextureManager.java rename to src/main/java/net/vulkanmod/mixin/texture/update/MTextureManager.java index f0baa1c9e..595ca054c 100644 --- a/src/main/java/net/vulkanmod/mixin/texture/MTextureManager.java +++ b/src/main/java/net/vulkanmod/mixin/texture/update/MTextureManager.java @@ -1,10 +1,10 @@ -package net.vulkanmod.mixin.texture; +package net.vulkanmod.mixin.texture.update; import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.client.renderer.texture.Tickable; -import net.vulkanmod.render.texture.SpriteUtil; +import net.vulkanmod.Initializer; +import net.vulkanmod.render.texture.SpriteUpdateUtil; import net.vulkanmod.vulkan.Renderer; -import net.vulkanmod.vulkan.device.DeviceManager; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; @@ -22,18 +22,14 @@ public abstract class MTextureManager { */ @Overwrite public void tick() { - if (Renderer.skipRendering) + if (Renderer.skipRendering || !Initializer.CONFIG.textureAnimations) return; //Debug D - if (SpriteUtil.shouldUpload()) - DeviceManager.getGraphicsQueue().startRecording(); for (Tickable tickable : this.tickableTextures) { tickable.tick(); } - if (SpriteUtil.shouldUpload()) { - SpriteUtil.transitionLayouts(DeviceManager.getGraphicsQueue().getCommandBuffer().getHandle()); - DeviceManager.getGraphicsQueue().endRecordingAndSubmit(); - } + + SpriteUpdateUtil.transitionLayouts(); } } diff --git a/src/main/java/net/vulkanmod/mixin/util/ScreenshotMixin.java b/src/main/java/net/vulkanmod/mixin/util/ScreenshotMixin.java new file mode 100644 index 000000000..7e2c4ef14 --- /dev/null +++ b/src/main/java/net/vulkanmod/mixin/util/ScreenshotMixin.java @@ -0,0 +1,20 @@ +package net.vulkanmod.mixin.util; + +import com.mojang.blaze3d.pipeline.RenderTarget; +import com.mojang.blaze3d.platform.NativeImage; +import net.minecraft.client.Screenshot; +import net.vulkanmod.vulkan.util.ScreenshotUtil; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; + +import java.util.function.Consumer; + +@Mixin(Screenshot.class) +public class ScreenshotMixin { + + @Overwrite + public static void takeScreenshot(RenderTarget renderTarget, int mipLevel, Consumer consumer) { + ScreenshotUtil.takeScreenshot(renderTarget, mipLevel, consumer); + } + +} diff --git a/src/main/java/net/vulkanmod/mixin/util/ScreenshotRecorderM.java b/src/main/java/net/vulkanmod/mixin/util/ScreenshotRecorderM.java deleted file mode 100644 index 58ae4ff90..000000000 --- a/src/main/java/net/vulkanmod/mixin/util/ScreenshotRecorderM.java +++ /dev/null @@ -1,32 +0,0 @@ -package net.vulkanmod.mixin.util; - -import com.mojang.blaze3d.pipeline.RenderTarget; -import com.mojang.blaze3d.platform.NativeImage; -import net.minecraft.client.Screenshot; -import net.vulkanmod.gl.GlTexture; -import net.vulkanmod.vulkan.Renderer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -@Mixin(Screenshot.class) -public class ScreenshotRecorderM { - - /** - * @author - */ - @Overwrite - public static NativeImage takeScreenshot(RenderTarget target) { - int width = target.width; - int height = target.height; - - NativeImage nativeimage = new NativeImage(width, height, false); - GlTexture.bindTexture(target.getColorTextureId()); - - // Need to submit and wait cmds if screenshot was requested - // before the end of the frame - Renderer.getInstance().flushCmds(); - - nativeimage.downloadTexture(0, true); - return nativeimage; - } -} diff --git a/src/main/java/net/vulkanmod/mixin/vertex/EntityOutlineGeneratorM.java b/src/main/java/net/vulkanmod/mixin/vertex/EntityOutlineGeneratorM.java index 1c6095267..b9be40061 100644 --- a/src/main/java/net/vulkanmod/mixin/vertex/EntityOutlineGeneratorM.java +++ b/src/main/java/net/vulkanmod/mixin/vertex/EntityOutlineGeneratorM.java @@ -15,7 +15,7 @@ public class EntityOutlineGeneratorM implements ExtendedVertexBuilder { private boolean canUseFastVertex = false; @Inject(method = "*", at = @At("RETURN")) - private void getExtBuilder(VertexConsumer vertexConsumer, int i, int j, int k, int l, CallbackInfo ci) { + private void getExtBuilder(VertexConsumer vertexConsumer, int i, CallbackInfo ci) { if (vertexConsumer instanceof ExtendedVertexBuilder) { this.extDelegate = (ExtendedVertexBuilder) vertexConsumer; this.canUseFastVertex = true; diff --git a/src/main/java/net/vulkanmod/mixin/vertex/VertexMultiConsumersM.java b/src/main/java/net/vulkanmod/mixin/vertex/VertexMultiConsumersM.java index 280f914d0..6a23dcf26 100644 --- a/src/main/java/net/vulkanmod/mixin/vertex/VertexMultiConsumersM.java +++ b/src/main/java/net/vulkanmod/mixin/vertex/VertexMultiConsumersM.java @@ -5,7 +5,7 @@ import com.mojang.blaze3d.vertex.VertexConsumer; import net.minecraft.core.Direction; import net.vulkanmod.interfaces.ExtendedVertexBuilder; -import net.vulkanmod.render.vertex.VertexUtil; +import net.vulkanmod.render.vertex.format.I32_SNorm; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.joml.Vector3f; @@ -115,15 +115,15 @@ private void checkDelegates(VertexConsumer vertexConsumer, PoseStack.Pose pose, @Override public void vertex(float x, float y, float z, int packedColor, float u, float v, int overlay, int light, int packedNormal) { - float nx = VertexUtil.unpackN1(packedNormal); - float ny = VertexUtil.unpackN2(packedNormal); - float nz = VertexUtil.unpackN3(packedNormal); + float nx = I32_SNorm.unpackX(packedNormal); + float ny = I32_SNorm.unpackY(packedNormal); + float nz = I32_SNorm.unpackZ(packedNormal); normal.set(nx, ny, nz); position.set(x, y , z, 1.0f); this.normalInversePose.transform(normal); - Direction direction = Direction.getNearest(normal.x(), normal.y(), normal.z()); + Direction direction = Direction.getApproximateNearest(normal.x(), normal.y(), normal.z()); this.cameraInversePose.transform(position); position.rotateY(3.1415927F); position.rotateX(-1.5707964F); diff --git a/src/main/java/net/vulkanmod/mixin/wayland/MinecraftMixin.java b/src/main/java/net/vulkanmod/mixin/wayland/MinecraftMixin.java index a80b32c0b..19d93d508 100644 --- a/src/main/java/net/vulkanmod/mixin/wayland/MinecraftMixin.java +++ b/src/main/java/net/vulkanmod/mixin/wayland/MinecraftMixin.java @@ -31,9 +31,9 @@ public class MinecraftMixin { */ @Redirect(method="", at=@At(value="INVOKE", target="Lcom/mojang/blaze3d/platform/Window;setIcon(Lnet/minecraft/server/packs/PackResources;Lcom/mojang/blaze3d/platform/IconSet;)V")) private void bypassWaylandIcon(Window instance, PackResources packResources, IconSet iconSet) throws IOException { - if(!Platform.isWayLand()) + if (!Platform.isWayLand()) { - this.window.setIcon(this.vanillaPackResources, SharedConstants.getCurrentVersion().isStable() ? IconSet.RELEASE : IconSet.SNAPSHOT); + this.window.setIcon(this.vanillaPackResources, SharedConstants.getCurrentVersion().stable() ? IconSet.RELEASE : IconSet.SNAPSHOT); } } } diff --git a/src/main/java/net/vulkanmod/mixin/window/WindowMixin.java b/src/main/java/net/vulkanmod/mixin/window/WindowMixin.java index 72ef9ae12..4827f9043 100644 --- a/src/main/java/net/vulkanmod/mixin/window/WindowMixin.java +++ b/src/main/java/net/vulkanmod/mixin/window/WindowMixin.java @@ -1,5 +1,6 @@ package net.vulkanmod.mixin.window; +import com.mojang.blaze3d.TracyFrameCapture; import com.mojang.blaze3d.platform.*; import com.mojang.blaze3d.systems.RenderSystem; import net.vulkanmod.Initializer; @@ -8,11 +9,12 @@ import net.vulkanmod.config.video.VideoModeManager; import net.vulkanmod.config.option.Options; import net.vulkanmod.config.video.VideoModeSet; +import net.vulkanmod.config.video.WindowMode; import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.VRenderSystem; import net.vulkanmod.vulkan.Vulkan; +import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; -import org.lwjgl.opengl.GLCapabilities; import org.slf4j.Logger; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -27,12 +29,9 @@ @Mixin(Window.class) public abstract class WindowMixin { - @Final @Shadow private long window; + @Final @Shadow private long handle; @Shadow private boolean vsync; - - @Shadow protected abstract void updateFullscreen(boolean bl); - @Shadow private boolean fullscreen; @Shadow @Final private static Logger LOGGER; @@ -53,26 +52,11 @@ public abstract class WindowMixin { @Shadow public abstract int getHeight(); + @Shadow protected abstract void updateFullscreen(boolean bl, @Nullable TracyFrameCapture tracyFrameCapture); + @Redirect(method = "", at = @At(value = "INVOKE", target = "Lorg/lwjgl/glfw/GLFW;glfwWindowHint(II)V")) private void redirect(int hint, int value) { } - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lorg/lwjgl/glfw/GLFW;glfwMakeContextCurrent(J)V")) - private void redirect2(long window) { } - - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL;createCapabilities()Lorg/lwjgl/opengl/GLCapabilities;")) - private GLCapabilities redirect2() { - return null; - } - - // Vulkan device not initialized yet - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;maxSupportedTextureSize()I")) - private int redirect3() { - return 0; - } - - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lorg/lwjgl/glfw/GLFW;glfwSetWindowSizeLimits(JIIII)V")) - private void redirect4(long window, int minwidth, int minheight, int maxwidth, int maxheight) { } - @Inject(method = "", at = @At(value = "INVOKE", target = "Lorg/lwjgl/glfw/GLFW;glfwCreateWindow(IILjava/lang/CharSequence;JJ)J")) private void vulkanHint(WindowEventHandler windowEventHandler, ScreenManager screenManager, DisplayData displayData, String string, String string2, CallbackInfo ci) { GLFW.glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); @@ -84,7 +68,7 @@ private void vulkanHint(WindowEventHandler windowEventHandler, ScreenManager scr @Inject(method = "", at = @At(value = "RETURN")) private void getHandle(WindowEventHandler windowEventHandler, ScreenManager screenManager, DisplayData displayData, String string, String string2, CallbackInfo ci) { - VRenderSystem.setWindow(this.window); + VRenderSystem.setWindow(this.handle); } /** @@ -109,12 +93,12 @@ public void toggleFullScreen() { * @author */ @Overwrite - public void updateDisplay() { - RenderSystem.flipFrame(this.window); + public void updateDisplay(@Nullable TracyFrameCapture tracyFrameCapture) { + RenderSystem.flipFrame((Window) ((Object)this), tracyFrameCapture); if (Options.fullscreenDirty) { Options.fullscreenDirty = false; - this.updateFullscreen(this.vsync); + this.updateFullscreen(this.vsync, tracyFrameCapture); } } @@ -158,12 +142,12 @@ private void setMode() { this.y = 0; this.width = videoMode.width; this.height = videoMode.height; - GLFW.glfwSetWindowMonitor(this.window, monitor, this.x, this.y, this.width, this.height, videoMode.refreshRate); + GLFW.glfwSetWindowMonitor(this.handle, monitor, this.x, this.y, this.width, this.height, videoMode.refreshRate); this.wasOnFullscreen = true; } } - else if (config.windowedFullscreen) { + else if (config.windowMode == WindowMode.WINDOWED_FULLSCREEN.mode) { VideoModeSet.VideoMode videoMode = VideoModeManager.getOsVideoMode(); if (!this.wasOnFullscreen) { @@ -176,8 +160,8 @@ else if (config.windowedFullscreen) { int width = videoMode.width; int height = videoMode.height; - GLFW.glfwSetWindowAttrib(this.window, GLFW_DECORATED, GLFW_FALSE); - GLFW.glfwSetWindowMonitor(this.window, 0L, 0, 0, width, height, -1); + GLFW.glfwSetWindowAttrib(this.handle, GLFW_DECORATED, GLFW_FALSE); + GLFW.glfwSetWindowMonitor(this.handle, 0L, 0, 0, width, height, -1); this.width = width; this.height = height; @@ -188,8 +172,8 @@ else if (config.windowedFullscreen) { this.width = this.windowedWidth; this.height = this.windowedHeight; - GLFW.glfwSetWindowMonitor(this.window, 0L, this.x, this.y, this.width, this.height, -1); - GLFW.glfwSetWindowAttrib(this.window, GLFW_DECORATED, GLFW_TRUE); + GLFW.glfwSetWindowMonitor(this.handle, 0L, this.x, this.y, this.width, this.height, -1); + GLFW.glfwSetWindowAttrib(this.handle, GLFW_DECORATED, GLFW_TRUE); this.wasOnFullscreen = false; } @@ -201,7 +185,7 @@ else if (config.windowedFullscreen) { */ @Overwrite private void onFramebufferResize(long window, int width, int height) { - if (window == this.window) { + if (window == this.handle) { int prevWidth = this.getWidth(); int prevHeight = this.getHeight(); diff --git a/src/main/java/net/vulkanmod/render/PipelineManager.java b/src/main/java/net/vulkanmod/render/PipelineManager.java index 52b037fdb..aa7d25269 100644 --- a/src/main/java/net/vulkanmod/render/PipelineManager.java +++ b/src/main/java/net/vulkanmod/render/PipelineManager.java @@ -1,27 +1,28 @@ package net.vulkanmod.render; +import com.google.gson.JsonObject; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.client.renderer.RenderType; import net.vulkanmod.render.chunk.build.thread.ThreadBuilderPack; +import net.vulkanmod.render.shader.ShaderLoadUtil; import net.vulkanmod.render.vertex.CustomVertexFormat; import net.vulkanmod.render.vertex.TerrainRenderType; import net.vulkanmod.vulkan.shader.GraphicsPipeline; import net.vulkanmod.vulkan.shader.Pipeline; -import net.vulkanmod.vulkan.shader.SPIRVUtils; import java.util.function.Function; -import static net.vulkanmod.vulkan.shader.SPIRVUtils.compileShaderAbsoluteFile; - public abstract class PipelineManager { - private static final String shaderPath = SPIRVUtils.class.getResource("/assets/vulkanmod/shaders/").toExternalForm(); - public static VertexFormat TERRAIN_VERTEX_FORMAT; + public static VertexFormat terrainVertexFormat; public static void setTerrainVertexFormat(VertexFormat format) { - TERRAIN_VERTEX_FORMAT = format; + terrainVertexFormat = format; } - static GraphicsPipeline terrainShaderEarlyZ, terrainShader, fastBlitPipeline; + static GraphicsPipeline + terrainShader, terrainShaderEarlyZ, + fastBlitPipeline, cloudsPipeline; private static Function shaderGetter; @@ -33,28 +34,33 @@ public static void init() { } public static void setDefaultShader() { - setShaderGetter(renderType -> renderType == TerrainRenderType.TRANSLUCENT ? terrainShaderEarlyZ : terrainShader); + setShaderGetter( + renderType -> renderType == TerrainRenderType.TRANSLUCENT ? terrainShaderEarlyZ : terrainShader); } private static void createBasicPipelines() { - terrainShaderEarlyZ = createPipeline("terrain","terrain", "terrain_Z", TERRAIN_VERTEX_FORMAT); - terrainShader = createPipeline("terrain", "terrain", "terrain", TERRAIN_VERTEX_FORMAT); - fastBlitPipeline = createPipeline("blit", "blit", "blit", CustomVertexFormat.NONE); + terrainShaderEarlyZ = createPipeline("terrain_earlyZ", terrainVertexFormat); + terrainShader = createPipeline("terrain", terrainVertexFormat); + fastBlitPipeline = createPipeline("blit", CustomVertexFormat.NONE); + cloudsPipeline = createPipeline("clouds", DefaultVertexFormat.POSITION_COLOR); } - private static GraphicsPipeline createPipeline(String baseName, String vertName, String fragName,VertexFormat vertexFormat) { - String pathB = String.format("basic/%s/%s", baseName, baseName); - String pathV = String.format("basic/%s/%s", baseName, vertName); - String pathF = String.format("basic/%s/%s", baseName, fragName); + private static GraphicsPipeline createPipeline(String configName, VertexFormat vertexFormat) { + Pipeline.Builder pipelineBuilder = new Pipeline.Builder(vertexFormat, configName); + + final String path = ShaderLoadUtil.resolveShaderPath("basic"); + JsonObject config = ShaderLoadUtil.getJsonConfig(path, configName); + pipelineBuilder.parseBindings(config); + + ShaderLoadUtil.loadShaders(pipelineBuilder, config, configName, path); - Pipeline.Builder pipelineBuilder = new Pipeline.Builder(vertexFormat, pathB); - pipelineBuilder.parseBindingsJSON(); + var pipeline = pipelineBuilder.createGraphicsPipeline(); - SPIRVUtils.SPIRV vertShaderSPIRV = compileShaderAbsoluteFile(String.format("%s%s.vsh", shaderPath, pathV), SPIRVUtils.ShaderKind.VERTEX_SHADER); - SPIRVUtils.SPIRV fragShaderSPIRV = compileShaderAbsoluteFile(String.format("%s%s.fsh", shaderPath, pathF), SPIRVUtils.ShaderKind.FRAGMENT_SHADER); - pipelineBuilder.setSPIRVs(vertShaderSPIRV, fragShaderSPIRV); + for (var buffer : pipeline.getBuffers()) { + buffer.setUseGlobalBuffer(true); + } - return pipelineBuilder.createGraphicsPipeline(); + return pipeline; } public static GraphicsPipeline getTerrainShader(TerrainRenderType renderType) { @@ -73,11 +79,18 @@ public static GraphicsPipeline getTerrainIndirectShader(RenderType renderType) { return terrainShaderEarlyZ; } - public static GraphicsPipeline getFastBlitPipeline() { return fastBlitPipeline; } + public static GraphicsPipeline getFastBlitPipeline() { + return fastBlitPipeline; + } + + public static GraphicsPipeline getCloudsPipeline() { + return cloudsPipeline; + } public static void destroyPipelines() { terrainShaderEarlyZ.cleanUp(); terrainShader.cleanUp(); fastBlitPipeline.cleanUp(); + cloudsPipeline.cleanUp(); } } diff --git a/src/main/java/net/vulkanmod/render/VBO.java b/src/main/java/net/vulkanmod/render/VBO.java index 1ebc59660..e3c4153ec 100644 --- a/src/main/java/net/vulkanmod/render/VBO.java +++ b/src/main/java/net/vulkanmod/render/VBO.java @@ -1,37 +1,31 @@ package net.vulkanmod.render; -import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.MeshData; import com.mojang.blaze3d.vertex.VertexFormat; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.renderer.ShaderInstance; -import net.vulkanmod.interfaces.ShaderMixed; import net.vulkanmod.vulkan.Renderer; -import net.vulkanmod.vulkan.VRenderSystem; -import net.vulkanmod.vulkan.memory.AutoIndexBuffer; -import net.vulkanmod.vulkan.memory.IndexBuffer; -import net.vulkanmod.vulkan.memory.MemoryTypes; -import net.vulkanmod.vulkan.memory.VertexBuffer; +import net.vulkanmod.vulkan.memory.*; +import net.vulkanmod.vulkan.memory.buffer.IndexBuffer; +import net.vulkanmod.vulkan.memory.buffer.VertexBuffer; +import net.vulkanmod.vulkan.memory.buffer.index.AutoIndexBuffer; import net.vulkanmod.vulkan.shader.GraphicsPipeline; import net.vulkanmod.vulkan.shader.Pipeline; import net.vulkanmod.vulkan.texture.VTextureSelector; -import org.joml.Matrix4f; import java.nio.ByteBuffer; -@Environment(EnvType.CLIENT) public class VBO { + private final MemoryType memoryType; private VertexBuffer vertexBuffer; private IndexBuffer indexBuffer; - private int indexCount; - private int vertexCount; private VertexFormat.Mode mode; - private boolean autoIndexed = false; + private int indexCount; + private int vertexCount; - public VBO() {} + public VBO(boolean useGpuMem) { + this.memoryType = useGpuMem ? MemoryTypes.GPU_MEM : MemoryTypes.HOST_MEM; + } public void upload(MeshData meshData) { MeshData.DrawState parameters = meshData.drawState(); @@ -49,10 +43,11 @@ public void upload(MeshData meshData) { private void uploadVertexBuffer(MeshData.DrawState parameters, ByteBuffer data) { if (data != null) { if (this.vertexBuffer != null) - this.vertexBuffer.freeBuffer(); + this.vertexBuffer.scheduleFree(); - this.vertexBuffer = new VertexBuffer(data.remaining(), MemoryTypes.GPU_MEM); - this.vertexBuffer.copyToVertexBuffer(parameters.format().getVertexSize(), parameters.vertexCount(), data); + int size = parameters.format().getVertexSize() * parameters.vertexCount(); + this.vertexBuffer = new VertexBuffer(size, this.memoryType); + this.vertexBuffer.copyBuffer(data, size); } } @@ -84,8 +79,9 @@ public void uploadIndexBuffer(ByteBuffer data) { default -> throw new IllegalStateException("Unexpected draw mode: %s".formatted(this.mode)); } - if (this.indexBuffer != null && !this.autoIndexed) - this.indexBuffer.freeBuffer(); + if (this.indexBuffer != null && !this.autoIndexed) { + this.indexBuffer.scheduleFree(); + } if (autoIndexBuffer != null) { autoIndexBuffer.checkCapacity(this.vertexCount); @@ -93,60 +89,36 @@ public void uploadIndexBuffer(ByteBuffer data) { } this.autoIndexed = true; - - } else { - if (this.indexBuffer != null) - this.indexBuffer.freeBuffer(); + } + else { + if (this.indexBuffer != null && !this.autoIndexed) { + this.indexBuffer.scheduleFree(); + } this.indexBuffer = new IndexBuffer(data.remaining(), MemoryTypes.GPU_MEM); - this.indexBuffer.copyBuffer(data); + this.indexBuffer.copyBuffer(data, data.remaining()); } - } - public void drawWithShader(Matrix4f MV, Matrix4f P, ShaderInstance shader) { - if (this.indexCount != 0) { - RenderSystem.assertOnRenderThread(); - - RenderSystem.setShader(() -> shader); - - drawWithShader(MV, P, ((ShaderMixed) shader).getPipeline()); - - } - } - - public void drawWithShader(Matrix4f MV, Matrix4f P, GraphicsPipeline pipeline) { - if (this.indexCount != 0) { - RenderSystem.assertOnRenderThread(); - - VRenderSystem.applyMVP(MV, P); - - VRenderSystem.setPrimitiveTopologyGL(this.mode.asGLMode); - - Renderer renderer = Renderer.getInstance(); - renderer.bindGraphicsPipeline(pipeline); - VTextureSelector.bindShaderTextures(pipeline); - renderer.uploadAndBindUBOs(pipeline); - - if (this.indexBuffer != null) - Renderer.getDrawer().drawIndexed(this.vertexBuffer, this.indexBuffer, this.indexCount); - else - Renderer.getDrawer().draw(this.vertexBuffer, this.vertexCount); - - VRenderSystem.applyMVP(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix()); - - } + public void bind(GraphicsPipeline pipeline) { + Renderer renderer = Renderer.getInstance(); + renderer.bindGraphicsPipeline(pipeline); + VTextureSelector.bindShaderTextures(pipeline); + renderer.uploadAndBindUBOs(pipeline); } public void draw() { if (this.indexCount != 0) { - RenderSystem.assertOnRenderThread(); - Renderer renderer = Renderer.getInstance(); Pipeline pipeline = renderer.getBoundPipeline(); renderer.uploadAndBindUBOs(pipeline); - Renderer.getDrawer().drawIndexed(this.vertexBuffer, this.indexBuffer, this.indexCount); + if (this.indexBuffer != null) { + Renderer.getDrawer().drawIndexed(this.vertexBuffer, this.indexBuffer, this.indexCount); + } + else { + Renderer.getDrawer().draw(this.vertexBuffer, this.vertexCount); + } } } @@ -154,11 +126,11 @@ public void close() { if (this.vertexCount <= 0) return; - this.vertexBuffer.freeBuffer(); + this.vertexBuffer.scheduleFree(); this.vertexBuffer = null; if (!this.autoIndexed) { - this.indexBuffer.freeBuffer(); + this.indexBuffer.scheduleFree(); this.indexBuffer = null; } diff --git a/src/main/java/net/vulkanmod/render/chunk/ChunkArea.java b/src/main/java/net/vulkanmod/render/chunk/ChunkArea.java index 26e6bb1e8..85400a8f1 100644 --- a/src/main/java/net/vulkanmod/render/chunk/ChunkArea.java +++ b/src/main/java/net/vulkanmod/render/chunk/ChunkArea.java @@ -11,11 +11,11 @@ public class ChunkArea { public final int index; + final DrawBuffers drawBuffers; final Vector3i position; final byte[] frustumBuffer = new byte[64]; - int sectionsContained = 0; - DrawBuffers drawBuffers; + int sectionsContained = 0; //Help JIT optimisations by hardcoding the queue size to the max possible ChunkArea limit public final StaticQueue sectionQueue = new StaticQueue<>(512); @@ -142,11 +142,15 @@ public void removeSection() { this.sectionsContained--; if (this.sectionsContained == 0) { - this.releaseBuffers(); + this.drawBuffers.releaseBuffers(); } } public void releaseBuffers() { this.drawBuffers.releaseBuffers(); } + + public void free() { + this.drawBuffers.free(); + } } diff --git a/src/main/java/net/vulkanmod/render/chunk/ChunkAreaManager.java b/src/main/java/net/vulkanmod/render/chunk/ChunkAreaManager.java index aa17b5047..4b79212b6 100644 --- a/src/main/java/net/vulkanmod/render/chunk/ChunkAreaManager.java +++ b/src/main/java/net/vulkanmod/render/chunk/ChunkAreaManager.java @@ -12,6 +12,8 @@ public class ChunkAreaManager { public static final int WIDTH = 8; public static final int HEIGHT = 8; + public static final int AREA_SIZE = WIDTH * WIDTH * HEIGHT; + public static final int AREA_SH_XZ = Util.flooredLog(WIDTH); public static final int AREA_SH_Y = Util.flooredLog(HEIGHT); @@ -29,6 +31,10 @@ public class ChunkAreaManager { int prevX; int prevZ; + private final CircularIntList xList; + private final CircularIntList zList; + private final CircularIntList.RangeIterator xComplIterator; + public ChunkAreaManager(int width, int height, int minHeight) { this.minHeight = minHeight; this.sectionGridWidth = width; @@ -59,6 +65,10 @@ public ChunkAreaManager(int width, int height, int minHeight) { this.prevX = Integer.MIN_VALUE; this.prevZ = Integer.MIN_VALUE; + + this.xList = new CircularIntList(this.xzSize); + this.zList = new CircularIntList(this.xzSize); + this.xComplIterator = this.xList.createRangeIterator(); } public void repositionAreas(int secX, int secZ) { @@ -73,8 +83,11 @@ public void repositionAreas(int secX, int secZ) { int zAbsChunkIndex = zS - this.xzSize / 2; int zStart = Math.floorMod(zAbsChunkIndex, this.xzSize); - CircularIntList xList = new CircularIntList(this.xzSize, xStart); - CircularIntList zList = new CircularIntList(this.xzSize, zStart); + CircularIntList xList = this.xList; + CircularIntList zList = this.zList; + xList.updateStartIdx(xStart); + zList.updateStartIdx(zStart); + CircularIntList.OwnIterator xIterator = xList.iterator(); CircularIntList.OwnIterator zIterator = zList.iterator(); @@ -104,9 +117,10 @@ public void repositionAreas(int secX, int secZ) { zRangeEnd = -deltaZ - 1; } - CircularIntList.RangeIterator xRangeIterator = xList.rangeIterator(xRangeStart, xRangeEnd); - CircularIntList.RangeIterator xComplIterator = xList.rangeIterator(xComplStart, xComplEnd); - CircularIntList.RangeIterator zRangeIterator = zList.rangeIterator(zRangeStart, zRangeEnd); + CircularIntList.RangeIterator xRangeIterator = xList.getRangeIterator(xRangeStart, xRangeEnd); + CircularIntList.RangeIterator zRangeIterator = zList.getRangeIterator(zRangeStart, zRangeEnd); + CircularIntList.RangeIterator xComplIterator = this.xComplIterator; + xComplIterator.update(xComplStart, xComplEnd); xAbsChunkIndex = xS - this.xzSize / 2 + xRangeStart; for (int xRelativeIndex; xRangeIterator.hasNext(); xAbsChunkIndex++) { @@ -121,12 +135,7 @@ public void repositionAreas(int secX, int secZ) { int z1 = (zAbsChunkIndex << (AREA_SH_XZ + SEC_SH)); for (int yRel = 0; yRel < this.ySize; ++yRel) { - int y1 = this.minHeight + (yRel << (AREA_SH_Y + SEC_SH)); - ChunkArea chunkArea = this.chunkAreasArr[this.getAreaIndex(xRelativeIndex, yRel, zRelativeIndex)]; - - chunkArea.setPosition(x1, y1, z1); - chunkArea.releaseBuffers(); - + this.moveArea(xRelativeIndex, yRel, zRelativeIndex, x1, z1); } } } @@ -144,12 +153,7 @@ public void repositionAreas(int secX, int secZ) { int z1 = (zAbsChunkIndex << (AREA_SH_XZ + SEC_SH)); for (int yRel = 0; yRel < this.ySize; ++yRel) { - int y1 = this.minHeight + (yRel << (AREA_SH_Y + SEC_SH)); - ChunkArea chunkArea = this.chunkAreasArr[this.getAreaIndex(xRelativeIndex, yRel, zRelativeIndex)]; - - chunkArea.setPosition(x1, y1, z1); - chunkArea.releaseBuffers(); - + this.moveArea(xRelativeIndex, yRel, zRelativeIndex, x1, z1); } } } @@ -158,6 +162,14 @@ public void repositionAreas(int secX, int secZ) { this.prevZ = zS; } + private void moveArea(int xRelativeIndex, int yRel, int zRelativeIndex, int x1, int z1) { + int y1 = this.minHeight + (yRel << (AREA_SH_Y + SEC_SH)); + ChunkArea chunkArea = this.chunkAreasArr[this.getAreaIndex(xRelativeIndex, yRel, zRelativeIndex)]; + + chunkArea.setPosition(x1, y1, z1); + chunkArea.releaseBuffers(); + } + public ChunkArea getChunkArea(RenderSection section, int x, int y, int z) { ChunkArea chunkArea; @@ -195,9 +207,9 @@ private int getAreaIndex(int x, int y, int z) { return (z * this.ySize + y) * this.xzSize + x; } - public void releaseAllBuffers() { + public void freeAllBuffers() { for (ChunkArea chunkArea : this.chunkAreasArr) { - chunkArea.releaseBuffers(); + chunkArea.free(); } } @@ -229,11 +241,12 @@ public String[] getStats() { } } - vbSize /= 1024 * 1024; - vbUsed /= 1024 * 1024; - ibSize /= 1024 * 1024; - ibUsed /= 1024 * 1024; - frag /= 1024 * 1024; + final int div = 1024 * 1024; + vbSize /= div; + vbUsed /= div; + ibSize /= div; + ibUsed /= div; + frag /= div; return new String[]{ String.format("Vertex Buffers: %d/%d MB", vbUsed, vbSize), diff --git a/src/main/java/net/vulkanmod/render/chunk/RenderSection.java b/src/main/java/net/vulkanmod/render/chunk/RenderSection.java index a1c54fca8..0ec0365c5 100644 --- a/src/main/java/net/vulkanmod/render/chunk/RenderSection.java +++ b/src/main/java/net/vulkanmod/render/chunk/RenderSection.java @@ -2,33 +2,33 @@ import com.google.common.collect.Sets; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; import net.minecraft.client.Minecraft; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; +import net.vulkanmod.render.chunk.buffer.AreaBuffer; import net.vulkanmod.render.chunk.buffer.DrawBuffers; +import net.vulkanmod.render.chunk.buffer.DrawParametersBuffer; import net.vulkanmod.render.chunk.build.RenderRegion; import net.vulkanmod.render.chunk.build.RenderRegionBuilder; -import net.vulkanmod.render.chunk.build.TaskDispatcher; +import net.vulkanmod.render.chunk.build.task.TaskDispatcher; import net.vulkanmod.render.chunk.build.task.BuildTask; import net.vulkanmod.render.chunk.build.task.ChunkTask; import net.vulkanmod.render.chunk.build.task.CompiledSection; import net.vulkanmod.render.chunk.build.task.SortTransparencyTask; +import net.vulkanmod.render.chunk.cull.QuadFacing; import net.vulkanmod.render.chunk.graph.GraphDirections; import net.vulkanmod.render.chunk.util.Util; import net.vulkanmod.render.vertex.TerrainRenderType; import java.util.Collection; -import java.util.Map; import java.util.Set; public class RenderSection { - static final Map> globalBlockEntitiesMap = new Reference2ReferenceOpenHashMap<>(); - private ChunkArea chunkArea; public byte frustumIndex; public short lastFrame = -1; private short lastFrame2 = -1; + public short inAreaIndex; public byte adjDirs; public RenderSection @@ -47,8 +47,6 @@ public class RenderSection { public int xOffset, yOffset, zOffset; - private final DrawBuffers.DrawParameters[] drawParametersArray; - // Graph-info public byte mainDir; public byte directions; @@ -60,11 +58,6 @@ public RenderSection(int index, int x, int y, int z) { this.xOffset = x; this.yOffset = y; this.zOffset = z; - - this.drawParametersArray = new DrawBuffers.DrawParameters[TerrainRenderType.VALUES.length]; - for (int i = 0; i < this.drawParametersArray.length; ++i) { - this.drawParametersArray[i] = new DrawBuffers.DrawParameters(); - } } public void setOrigin(int x, int y, int z) { @@ -297,8 +290,20 @@ public int zOffset() { return zOffset; } - public DrawBuffers.DrawParameters getDrawParameters(TerrainRenderType renderType) { - return drawParametersArray[renderType.ordinal()]; + public void resetDrawParameters(TerrainRenderType renderType) { + for (int i = 0; i < QuadFacing.COUNT; ++i) { + DrawBuffers drawBuffers = this.chunkArea.getDrawBuffers(); + long ptr = DrawParametersBuffer.getParamsPtr(drawBuffers.getDrawParamsPtr(), this.inAreaIndex, renderType.ordinal(), i); + + AreaBuffer areaBuffer = drawBuffers.getAreaBuffer(renderType); + int vertexOffset = DrawParametersBuffer.getVertexOffset(ptr); + if (areaBuffer != null && vertexOffset != -1) { + int segmentOffset = vertexOffset * DrawBuffers.VERTEX_SIZE; + areaBuffer.setSegmentFree(segmentOffset); + } + + DrawParametersBuffer.resetParameters(ptr); + } } public void setChunkArea(ChunkArea chunkArea) { @@ -339,6 +344,10 @@ public byte getVisibilityDirs() { return (byte) (this.visibility >> (Util.getOppositeDirIdx(this.mainDir) << 3)); } + public long getVisibility() { + return visibility; + } + public boolean isCompletelyEmpty() { return this.completelyEmpty; } @@ -348,26 +357,19 @@ public boolean containsBlockEntities() { } public void updateGlobalBlockEntities(Collection fullSet) { - if (fullSet.isEmpty()) - return; - - Set set = Sets.newHashSet(fullSet); - Set set1; - Set sectionSet; - synchronized (globalBlockEntitiesMap) { - sectionSet = globalBlockEntitiesMap.computeIfAbsent(this, - (section) -> new ObjectOpenHashSet<>()); - } + Set sectionSet = compileStatus.globalBlockEntities; if (sectionSet.size() != fullSet.size() || !sectionSet.containsAll(fullSet)) { - set1 = Sets.newHashSet(sectionSet); - set.removeAll(sectionSet); - set1.removeAll(fullSet); + Set toRemove = Sets.newHashSet(sectionSet); + Set toAdd = Sets.newHashSet(fullSet); + toAdd.removeAll(sectionSet); + toRemove.removeAll(fullSet); sectionSet.clear(); sectionSet.addAll(fullSet); - Minecraft.getInstance().levelRenderer.updateGlobalBlockEntities(set1, set); + // TODO +// Minecraft.getInstance().levelRenderer.updateGlobalBlockEntities(toRemove, toAdd); } } @@ -385,8 +387,12 @@ private void resetDrawParameters() { if (this.chunkArea == null) return; - for (TerrainRenderType r : TerrainRenderType.VALUES) { - this.getDrawParameters(r).reset(this.chunkArea, r); + long basePtr = this.chunkArea.getDrawBuffers().getDrawParamsPtr(); + for (TerrainRenderType renderType : TerrainRenderType.VALUES) { + for (QuadFacing facing : QuadFacing.VALUES) { + long ptr = DrawParametersBuffer.getParamsPtr(basePtr, this.inAreaIndex, renderType.ordinal(), facing.ordinal()); + DrawParametersBuffer.resetParameters(ptr); + } } } @@ -418,8 +424,13 @@ public short getLastFrame() { return this.lastFrame; } + public short getLastFrame2() { + return this.lastFrame2; + } + static class CompileStatus { CompiledSection compiledSection = CompiledSection.UNCOMPILED; + Set globalBlockEntities = new ObjectOpenHashSet<>(); BuildTask buildTask; SortTransparencyTask sortTask; } diff --git a/src/main/java/net/vulkanmod/render/chunk/SectionGrid.java b/src/main/java/net/vulkanmod/render/chunk/SectionGrid.java index 54ee8d3ed..f7075774a 100644 --- a/src/main/java/net/vulkanmod/render/chunk/SectionGrid.java +++ b/src/main/java/net/vulkanmod/render/chunk/SectionGrid.java @@ -23,14 +23,22 @@ public class SectionGrid { private int prevSecX; private int prevSecZ; + private final CircularIntList xList; + private final CircularIntList zList; + private final CircularIntList.RangeIterator xComplIterator; + public SectionGrid(Level level, int viewDistance) { this.level = level; this.setViewDistance(viewDistance); this.createChunks(); - this.chunkAreaManager = new ChunkAreaManager(this.gridWidth, this.gridHeight, this.level.getMinBuildHeight()); + this.chunkAreaManager = new ChunkAreaManager(this.gridWidth, this.gridHeight, this.level.getMinY()); this.prevSecX = Integer.MIN_VALUE; this.prevSecZ = Integer.MIN_VALUE; + + this.xList = new CircularIntList(this.gridWidth); + this.zList = new CircularIntList(this.gridWidth); + this.xComplIterator = this.xList.createRangeIterator(); } protected void createChunks() { @@ -53,8 +61,8 @@ protected void createChunks() { } } - public void releaseAllBuffers() { - this.chunkAreaManager.releaseAllBuffers(); + public void freeAllBuffers() { + this.chunkAreaManager.freeAllBuffers(); } private int getChunkIndex(int x, int y, int z) { @@ -86,8 +94,11 @@ public void repositionCamera(double x, double z) { int zAbsChunkIndex = secZ - this.gridWidth / 2; int zStart = Math.floorMod(zAbsChunkIndex, this.gridWidth); - CircularIntList xList = new CircularIntList(this.gridWidth, xStart); - CircularIntList zList = new CircularIntList(this.gridWidth, zStart); + CircularIntList xList = this.xList; + CircularIntList zList = this.zList; + xList.updateStartIdx(xStart); + zList.updateStartIdx(zStart); + CircularIntList.OwnIterator xIterator = xList.iterator(); CircularIntList.OwnIterator zIterator = zList.iterator(); @@ -117,9 +128,10 @@ public void repositionCamera(double x, double z) { zRangeEnd = -dz - 1; } - CircularIntList.RangeIterator xRangeIterator = xList.rangeIterator(xRangeStart, xRangeEnd); - CircularIntList.RangeIterator xComplIterator = xList.rangeIterator(xComplStart, xComplEnd); - CircularIntList.RangeIterator zRangeIterator = zList.rangeIterator(zRangeStart, zRangeEnd); + CircularIntList.RangeIterator xRangeIterator = xList.getRangeIterator(xRangeStart, xRangeEnd); + CircularIntList.RangeIterator zRangeIterator = zList.getRangeIterator(zRangeStart, zRangeEnd); + CircularIntList.RangeIterator xComplIterator = this.xComplIterator; + xComplIterator.update(xComplStart, xComplEnd); xAbsChunkIndex = secX - (this.gridWidth >> 1) + xRangeStart; for (int xRelativeIndex; xRangeIterator.hasNext(); xAbsChunkIndex++) { @@ -133,19 +145,9 @@ public void repositionCamera(double x, double z) { zRelativeIndex = zIterator.next(); int z1 = (zAbsChunkIndex << 4); - for (int yRel = 0; - yRel < this.gridHeight; ++yRel) { - int y1 = this.level.getMinBuildHeight() + (yRel << 4); - RenderSection renderSection = this.sections[this.getChunkIndex(xRelativeIndex, yRel, zRelativeIndex)]; - - renderSection.setOrigin(x1, y1, z1); - - this.unsetNeighbours(renderSection); - - this.setNeighbours(renderSection, xList, zList, xRangeIterator.getCurrentIndex(), zIterator.getCurrentIndex(), - xRelativeIndex, yRel, zRelativeIndex); - - this.setChunkArea(renderSection, x1, y1, z1); + for (int yRel = 0; yRel < this.gridHeight; ++yRel) { + moveSection(xRelativeIndex, yRel, zRelativeIndex, x1, z1, + xList, zList, xRangeIterator.getCurrentIndex(), zIterator.getCurrentIndex()); } } } @@ -162,26 +164,45 @@ public void repositionCamera(double x, double z) { zRelativeIndex = zRangeIterator.next(); int z1 = (zAbsChunkIndex << 4); - for (int yRel = 0; - yRel < this.gridHeight; ++yRel) { - int y1 = this.level.getMinBuildHeight() + (yRel << 4); - RenderSection renderSection = this.sections[this.getChunkIndex(xRelativeIndex, yRel, zRelativeIndex)]; + for (int yRel = 0; yRel < this.gridHeight; ++yRel) { + moveSection(xRelativeIndex, yRel, zRelativeIndex, x1, z1, + xList, zList, xComplIterator.getCurrentIndex(), zRangeIterator.getCurrentIndex()); + } + } + } - renderSection.setOrigin(x1, y1, z1); + this.prevSecX = secX; + this.prevSecZ = secZ; + } - this.unsetNeighbours(renderSection); + private void moveSection(int xRelativeIndex, int yRel, int zRelativeIndex, + int x1, int z1, + CircularIntList xList, CircularIntList zList, + int xCurrentIdx, int zCurrentIdx) { - this.setNeighbours(renderSection, xList, zList, xComplIterator.getCurrentIndex(), zRangeIterator.getCurrentIndex(), - xRelativeIndex, yRel, zRelativeIndex); + int y1 = this.level.getMinY() + (yRel << 4); + RenderSection renderSection = this.sections[this.getChunkIndex(xRelativeIndex, yRel, zRelativeIndex)]; - this.setChunkArea(renderSection, x1, y1, z1); + this.unsetNeighbours(renderSection); - } - } + renderSection.setOrigin(x1, y1, z1); + + this.setNeighbours(renderSection, xList, zList, xCurrentIdx, zCurrentIdx, + xRelativeIndex, yRel, zRelativeIndex); + + ChunkArea oldArea = renderSection.getChunkArea(); + + if (oldArea != null) { + oldArea.removeSection(); } - this.prevSecX = secX; - this.prevSecZ = secZ; + ChunkArea chunkArea = this.chunkAreaManager.getChunkArea(renderSection, x1, y1, z1); + chunkArea.addSection(); + renderSection.setChunkArea(chunkArea); + + renderSection.inAreaIndex = (short) (((x1 - chunkArea.position.x()) >> 4) + + (((z1 - chunkArea.position.z()) >> 4) * 8 + ((y1 - chunkArea.position.y()) >> 4)) * 8); + } private void setNeighbours(RenderSection section, CircularIntList xList, CircularIntList zList, @@ -260,7 +281,7 @@ private void setChunkArea(RenderSection section, int x, int y, int z) { public void setDirty(int sectionX, int sectionY, int sectionZ, boolean playerChanged) { int i = Math.floorMod(sectionX, this.gridWidth); - int j = Math.floorMod(sectionY - this.level.getMinSection(), this.gridHeight); + int j = Math.floorMod(sectionY - this.level.getMinSectionY(), this.gridHeight); int k = Math.floorMod(sectionZ, this.gridWidth); RenderSection renderSection = this.sections[this.getChunkIndex(i, j, k)]; renderSection.setDirty(playerChanged); @@ -273,7 +294,7 @@ public RenderSection getSectionAtBlockPos(BlockPos blockPos) { public RenderSection getSectionAtBlockPos(int x, int y, int z) { int i = x >> 4; - int j = (y - this.level.getMinBuildHeight()) >> 4; + int j = (y - this.level.getMinY()) >> 4; int k = z >> 4; return this.getSectionAtSectionPos(i, j, k); diff --git a/src/main/java/net/vulkanmod/render/chunk/WorldRenderer.java b/src/main/java/net/vulkanmod/render/chunk/WorldRenderer.java index c7fe74ef1..06d5a0a5d 100644 --- a/src/main/java/net/vulkanmod/render/chunk/WorldRenderer.java +++ b/src/main/java/net/vulkanmod/render/chunk/WorldRenderer.java @@ -1,34 +1,40 @@ package net.vulkanmod.render.chunk; import com.google.common.collect.Sets; +import com.mojang.blaze3d.opengl.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.SheetedDecalTextureGenerator; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.blaze3d.vertex.VertexMultiConsumer; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderBuffers; -import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.SubmitNodeStorage; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; +import net.minecraft.client.renderer.blockentity.state.BlockEntityRenderState; import net.minecraft.client.renderer.culling.Frustum; -import net.minecraft.client.resources.model.ModelBakery; +import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.client.renderer.feature.FeatureRenderDispatcher; +import net.minecraft.client.renderer.feature.ModelFeatureRenderer; +import net.minecraft.client.renderer.state.LevelRenderState; +import net.minecraft.client.renderer.texture.AbstractTexture; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.core.BlockPos; import net.minecraft.core.SectionPos; import net.minecraft.server.level.BlockDestructionProgress; import net.minecraft.util.Mth; +import net.minecraft.util.profiling.ProfilerFiller; +import net.minecraft.util.profiling.Zone; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.phys.Vec3; import net.vulkanmod.Initializer; import net.vulkanmod.render.PipelineManager; import net.vulkanmod.render.chunk.buffer.DrawBuffers; -import net.vulkanmod.render.chunk.build.BlockRenderer; import net.vulkanmod.render.chunk.build.RenderRegionBuilder; -import net.vulkanmod.render.chunk.build.TaskDispatcher; +import net.vulkanmod.render.chunk.build.task.TaskDispatcher; import net.vulkanmod.render.chunk.build.task.ChunkTask; import net.vulkanmod.render.chunk.graph.SectionGraph; import net.vulkanmod.render.profiling.BuildTimeProfiler; @@ -36,9 +42,9 @@ import net.vulkanmod.render.vertex.TerrainRenderType; import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.VRenderSystem; -import net.vulkanmod.vulkan.memory.Buffer; -import net.vulkanmod.vulkan.memory.IndexBuffer; -import net.vulkanmod.vulkan.memory.IndirectBuffer; +import net.vulkanmod.vulkan.memory.buffer.Buffer; +import net.vulkanmod.vulkan.memory.buffer.IndexBuffer; +import net.vulkanmod.vulkan.memory.buffer.IndirectBuffer; import net.vulkanmod.vulkan.memory.MemoryTypes; import net.vulkanmod.vulkan.shader.GraphicsPipeline; import net.vulkanmod.vulkan.texture.VTextureSelector; @@ -51,11 +57,30 @@ public class WorldRenderer { private static WorldRenderer INSTANCE; + public static WorldRenderer init(EntityRenderDispatcher entityRenderDispatcher, + BlockEntityRenderDispatcher blockEntityRenderDispatcher, + RenderBuffers renderBuffers, + LevelRenderState levelRenderState, + FeatureRenderDispatcher featureRenderDispatcher) { + if (INSTANCE != null) { + return INSTANCE; + } + else { + return INSTANCE = new WorldRenderer(entityRenderDispatcher, blockEntityRenderDispatcher, renderBuffers, levelRenderState, featureRenderDispatcher); + } + } + private final Minecraft minecraft; private ClientLevel level; private int renderDistance; private final RenderBuffers renderBuffers; + private final EntityRenderDispatcher entityRenderDispatcher; + private final BlockEntityRenderDispatcher blockEntityRenderDispatcher; + private final LevelRenderState levelRenderState; + private final FeatureRenderDispatcher featureRenderDispatcher; + + private float partialTick; private Vec3 cameraPos; private int lastCameraSectionX; private int lastCameraSectionY; @@ -85,15 +110,25 @@ public class WorldRenderer { private final List onAllChangedCallbacks = new ObjectArrayList<>(); - private WorldRenderer(RenderBuffers renderBuffers) { + private WorldRenderer(EntityRenderDispatcher entityRenderDispatcher, + BlockEntityRenderDispatcher blockEntityRenderDispatcher, + RenderBuffers renderBuffers, + LevelRenderState levelRenderState, + FeatureRenderDispatcher featureRenderDispatcher) + { this.minecraft = Minecraft.getInstance(); this.renderBuffers = renderBuffers; + this.entityRenderDispatcher = entityRenderDispatcher; + this.blockEntityRenderDispatcher = blockEntityRenderDispatcher; + this.levelRenderState = levelRenderState; + this.featureRenderDispatcher = featureRenderDispatcher; + this.renderRegionCache = new RenderRegionBuilder(); this.taskDispatcher = new TaskDispatcher(); + ChunkTask.setTaskDispatcher(this.taskDispatcher); allocateIndirectBuffers(); - - BlockRenderer.setBlockColors(this.minecraft.getBlockColors()); + TerrainRenderType.updateMapping(); Renderer.getInstance().addOnResizeCallback(() -> { if (this.indirectBuffers.length != Renderer.getFramesNum()) @@ -103,35 +138,13 @@ private WorldRenderer(RenderBuffers renderBuffers) { private void allocateIndirectBuffers() { if (this.indirectBuffers != null) - Arrays.stream(this.indirectBuffers).forEach(Buffer::freeBuffer); + Arrays.stream(this.indirectBuffers).forEach(Buffer::scheduleFree); this.indirectBuffers = new IndirectBuffer[Renderer.getFramesNum()]; for (int i = 0; i < this.indirectBuffers.length; ++i) { this.indirectBuffers[i] = new IndirectBuffer(1000000, MemoryTypes.HOST_MEM); -// this.indirectBuffers[i] = new IndirectBuffer(1000000, MemoryTypes.GPU_MEM); } - -// uniformBuffers = new UniformBuffers(100000, MemoryTypes.GPU_MEM); - } - - public static WorldRenderer init(RenderBuffers renderBuffers) { - if (INSTANCE != null) - return INSTANCE; - else - return INSTANCE = new WorldRenderer(renderBuffers); - } - - public static WorldRenderer getInstance() { - return INSTANCE; - } - - public static ClientLevel getLevel() { - return INSTANCE.level; - } - - public static Vec3 getCameraPos() { - return INSTANCE.cameraPos; } private void benchCallback() { @@ -142,6 +155,8 @@ public void setupRenderer(Camera camera, Frustum frustum, boolean isCapturedFrus Profiler profiler = Profiler.getMainProfiler(); profiler.push("Setup_Renderer"); + ProfilerFiller mcProfiler = net.minecraft.util.profiling.Profiler.get(); + benchCallback(); this.cameraPos = camera.getPosition(); @@ -149,7 +164,7 @@ public void setupRenderer(Camera camera, Frustum frustum, boolean isCapturedFrus this.allChanged(); } - this.level.getProfiler().push("camera"); + mcProfiler.push("camera"); float cameraX = (float) cameraPos.x(); float cameraY = (float) cameraPos.y(); float cameraZ = (float) cameraPos.z(); @@ -169,10 +184,9 @@ public void setupRenderer(Camera camera, Frustum frustum, boolean isCapturedFrus double entityDistanceScaling = this.minecraft.options.entityDistanceScaling().get(); Entity.setViewScale(Mth.clamp((double) this.renderDistance / 8.0D, 1.0D, 2.5D) * entityDistanceScaling); - this.level.getProfiler().popPush("cull"); - this.minecraft.getProfiler().popPush("culling"); + mcProfiler.popPush("cull"); - this.minecraft.getProfiler().popPush("update"); + mcProfiler.popPush("update"); boolean cameraMoved = false; float d_xRot = Math.abs(camera.getXRot() - this.lastCamRotX); @@ -186,7 +200,7 @@ public void setupRenderer(Camera camera, Frustum frustum, boolean isCapturedFrus //Debug // this.graphNeedsUpdate = true; - if (this.graphNeedsUpdate) { + if (this.graphNeedsUpdate()) { this.graphNeedsUpdate = false; this.lastCameraX = cameraX; this.lastCameraY = cameraY; @@ -199,14 +213,14 @@ public void setupRenderer(Camera camera, Frustum frustum, boolean isCapturedFrus } this.indirectBuffers[Renderer.getCurrentFrame()].reset(); -// this.uniformBuffers.reset(); - this.minecraft.getProfiler().pop(); + mcProfiler.pop(); profiler.pop(); } public void uploadSections() { - this.minecraft.getProfiler().push("upload"); + ProfilerFiller mcProfiler = net.minecraft.util.profiling.Profiler.get(); + mcProfiler.push("upload"); Profiler profiler = Profiler.getMainProfiler(); profiler.push("Uploads"); @@ -221,7 +235,7 @@ public void uploadSections() { profiler.pop(); - this.minecraft.getProfiler().pop(); + mcProfiler.pop(); } public boolean isSectionCompiled(BlockPos blockPos) { @@ -231,18 +245,16 @@ public boolean isSectionCompiled(BlockPos blockPos) { public void allChanged() { if (this.level != null) { -// this.graphicsChanged(); this.level.clearTintCaches(); this.renderRegionCache.clear(); - this.taskDispatcher.createThreads(); + this.taskDispatcher.createThreads(Initializer.CONFIG.builderThreads); this.graphNeedsUpdate = true; -// this.generateClouds = true; this.renderDistance = this.minecraft.options.getEffectiveRenderDistance(); if (this.sectionGrid != null) { - this.sectionGrid.releaseAllBuffers(); + this.sectionGrid.freeAllBuffers(); } this.taskDispatcher.clearBatchQueue(); @@ -278,7 +290,7 @@ public void setLevel(@Nullable ClientLevel level) { this.allChanged(); } else { if (this.sectionGrid != null) { - this.sectionGrid.releaseAllBuffers(); + this.sectionGrid.freeAllBuffers(); this.sectionGrid = null; } @@ -297,34 +309,57 @@ public void clearOnAllChangedCallbacks() { this.onAllChangedCallbacks.clear(); } - public void renderSectionLayer(RenderType renderType, double camX, double camY, double camZ, Matrix4f modelView, Matrix4f projection) { - TerrainRenderType terrainRenderType = TerrainRenderType.get(renderType); - renderType.setupRenderState(); + public void renderSectionLayer(TerrainRenderType renderType, double camX, double camY, double camZ, Matrix4f modelView, Matrix4f projection) { + Renderer.getInstance().getMainPass().rebindMainTarget(); this.sortTranslucentSections(camX, camY, camZ); - this.minecraft.getProfiler().push("filterempty"); - this.minecraft.getProfiler().popPush(() -> "render_" + renderType); + ProfilerFiller mcProfiler = net.minecraft.util.profiling.Profiler.get(); + Zone zone = mcProfiler.zone(() -> "render_" + renderType); - final boolean isTranslucent = terrainRenderType == TerrainRenderType.TRANSLUCENT; + final boolean isTranslucent = renderType == TerrainRenderType.TRANSLUCENT; final boolean indirectDraw = Initializer.CONFIG.indirectDraw; + if (!isTranslucent) { + GlStateManager._disableBlend(); + } else { + GlStateManager._enableBlend(); + VRenderSystem.blendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + } + + VRenderSystem.enableCull(); + VRenderSystem.depthFunc(GL11.GL_LEQUAL); + + GlStateManager._enableDepthTest(); + GlStateManager._depthMask(true); + + GlStateManager._colorMask(true, true, true, true); + GlStateManager._disablePolygonOffset(); + VRenderSystem.setPolygonModeGL(GL11.GL_FILL); + VRenderSystem.applyMVP(modelView, projection); VRenderSystem.setPrimitiveTopologyGL(GL11.GL_TRIANGLES); Renderer renderer = Renderer.getInstance(); - GraphicsPipeline pipeline = PipelineManager.getTerrainShader(terrainRenderType); + GraphicsPipeline pipeline = PipelineManager.getTerrainShader(renderType); renderer.bindGraphicsPipeline(pipeline); + TextureManager textureManager = Minecraft.getInstance().getTextureManager(); + AbstractTexture blockAtlasTexture = textureManager.getTexture(TextureAtlas.LOCATION_BLOCKS); + blockAtlasTexture.setUseMipmaps(true); + + RenderSystem.setShaderTexture(0, blockAtlasTexture.getTextureView()); + RenderSystem.setShaderTexture(2, Minecraft.getInstance().gameRenderer.lightTexture().getTextureView()); + VTextureSelector.bindShaderTextures(pipeline); IndexBuffer indexBuffer = Renderer.getDrawer().getQuadsIndexBuffer().getIndexBuffer(); - Renderer.getDrawer().bindIndexBuffer(Renderer.getCommandBuffer(), indexBuffer); + Renderer.getDrawer().bindIndexBuffer(Renderer.getCommandBuffer(), indexBuffer, indexBuffer.indexType.value); int currentFrame = Renderer.getCurrentFrame(); Set allowedRenderTypes = Initializer.CONFIG.uniqueOpaqueLayer ? TerrainRenderType.COMPACT_RENDER_TYPES : TerrainRenderType.SEMI_COMPACT_RENDER_TYPES; - if (allowedRenderTypes.contains(terrainRenderType)) { - terrainRenderType.setCutoutUniform(); + if (allowedRenderTypes.contains(renderType)) { + renderType.setCutoutUniform(); for (Iterator iterator = this.sectionGraph.getChunkAreaQueue().iterator(isTranslucent); iterator.hasNext(); ) { ChunkArea chunkArea = iterator.next(); @@ -332,42 +367,39 @@ public void renderSectionLayer(RenderType renderType, double camX, double camY, DrawBuffers drawBuffers = chunkArea.drawBuffers; renderer.uploadAndBindUBOs(pipeline); - if (drawBuffers.getAreaBuffer(terrainRenderType) != null && queue.size() > 0) { + if (drawBuffers.getAreaBuffer(renderType) != null && queue.size() > 0) { - drawBuffers.bindBuffers(Renderer.getCommandBuffer(), pipeline, terrainRenderType, camX, camY, camZ); + drawBuffers.bindBuffers(Renderer.getCommandBuffer(), pipeline, renderType, camX, camY, camZ); renderer.uploadAndBindUBOs(pipeline); if (indirectDraw) - drawBuffers.buildDrawBatchesIndirect(indirectBuffers[currentFrame], queue, terrainRenderType); + drawBuffers.buildDrawBatchesIndirect(cameraPos, indirectBuffers[currentFrame], queue, renderType); else - drawBuffers.buildDrawBatchesDirect(queue, terrainRenderType); + drawBuffers.buildDrawBatchesDirect(cameraPos, queue, renderType); } } } - if (terrainRenderType == TerrainRenderType.CUTOUT || terrainRenderType == TerrainRenderType.TRIPWIRE) { + if (renderType == TerrainRenderType.CUTOUT || renderType == TerrainRenderType.TRIPWIRE) { indirectBuffers[currentFrame].submitUploads(); // uniformBuffers.submitUploads(); } - //Need to reset push constants in case the pipeline will still be used for rendering + // Need to reset push constants in case the pipeline will still be used for rendering if (!indirectDraw) { - VRenderSystem.setChunkOffset(0, 0, 0); + VRenderSystem.setModelOffset(0, 0, 0); renderer.pushConstants(pipeline); } - this.minecraft.getProfiler().pop(); - renderType.clearRenderState(); - - VRenderSystem.applyMVP(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix()); + zone.close(); } private void sortTranslucentSections(double camX, double camY, double camZ) { - this.minecraft.getProfiler().push("translucent_sort"); + ProfilerFiller mcProfiler = net.minecraft.util.profiling.Profiler.get(); + mcProfiler.push("translucent_sort"); double d0 = camX - this.xTransparentOld; double d1 = camY - this.yTransparentOld; double d2 = camZ - this.zTransparentOld; -// if (d0 * d0 + d1 * d1 + d2 * d2 > 1.0D) { if (d0 * d0 + d1 * d1 + d2 * d2 > 2.0D) { this.xTransparentOld = camX; this.yTransparentOld = camY; @@ -376,52 +408,82 @@ private void sortTranslucentSections(double camX, double camY, double camZ) { Iterator iterator = this.sectionGraph.getSectionQueue().iterator(false); - while (iterator.hasNext() && j < 15) { + while (iterator.hasNext() && j < 200) { RenderSection section = iterator.next(); - section.resortTransparency(this.taskDispatcher); - ++j; + if (!section.isCompletelyEmpty()) { + ++j; + } } } - this.minecraft.getProfiler().pop(); + mcProfiler.pop(); } - public void renderBlockEntities(PoseStack poseStack, double camX, double camY, double camZ, - Long2ObjectMap> destructionProgress, float gameTime) { + public void renderBlockEntities(PoseStack poseStack, LevelRenderState levelRenderState, + SubmitNodeStorage submitNodeStorage, + Long2ObjectMap> destructionProgress) { Profiler profiler = Profiler.getMainProfiler(); profiler.pop(); profiler.push("Block-entities"); - MultiBufferSource bufferSource = this.renderBuffers.bufferSource(); + Vec3 vec3 = levelRenderState.cameraRenderState.pos; + double camX = vec3.x(); + double camY = vec3.y(); + double camZ = vec3.z(); for (RenderSection renderSection : this.sectionGraph.getBlockEntitiesSections()) { List list = renderSection.getCompiledSection().getBlockEntities(); if (!list.isEmpty()) { for (BlockEntity blockEntity : list) { BlockPos blockPos = blockEntity.getBlockPos(); - MultiBufferSource bufferSource1 = bufferSource; - poseStack.pushPose(); - poseStack.translate((double) blockPos.getX() - camX, (double) blockPos.getY() - camY, (double) blockPos.getZ() - camZ); - SortedSet sortedset = destructionProgress.get(blockPos.asLong()); - if (sortedset != null && !sortedset.isEmpty()) { - int j1 = sortedset.last().getProgress(); - if (j1 >= 0) { - PoseStack.Pose pose = poseStack.last(); - VertexConsumer vertexconsumer = new SheetedDecalTextureGenerator(this.renderBuffers.crumblingBufferSource().getBuffer(ModelBakery.DESTROY_TYPES.get(j1)), pose, 1.0f); - bufferSource1 = (renderType) -> { - VertexConsumer vertexConsumer2 = bufferSource.getBuffer(renderType); - return renderType.affectsCrumbling() ? VertexMultiConsumer.create(vertexconsumer, vertexConsumer2) : vertexConsumer2; - }; - } + SortedSet sortedSet = destructionProgress.get(blockPos.asLong()); + ModelFeatureRenderer.CrumblingOverlay crumblingOverlay; + if (sortedSet != null && !sortedSet.isEmpty()) { + poseStack.pushPose(); + poseStack.translate(blockPos.getX() - camX, blockPos.getY() - camY, blockPos.getZ() - camZ); + crumblingOverlay = new ModelFeatureRenderer.CrumblingOverlay(sortedSet.last() + .getProgress(), poseStack.last()); + poseStack.popPose(); + } else { + crumblingOverlay = null; } - this.minecraft.getBlockEntityRenderDispatcher().render(blockEntity, gameTime, poseStack, bufferSource1); - poseStack.popPose(); + BlockEntityRenderState blockEntityRenderState = this.blockEntityRenderDispatcher.tryExtractRenderState(blockEntity, this.partialTick, crumblingOverlay); + if (blockEntityRenderState != null) { + levelRenderState.blockEntityRenderStates.add(blockEntityRenderState); + } } } } + + Iterator iterator = this.level.getGloballyRenderedBlockEntities().iterator(); + + while (iterator.hasNext()) { + BlockEntity blockEntity2 = iterator.next(); + if (blockEntity2.isRemoved()) { + iterator.remove(); + } else { + BlockEntityRenderState blockEntityRenderState2 = this.blockEntityRenderDispatcher.tryExtractRenderState(blockEntity2, this.partialTick, null); + if (blockEntityRenderState2 != null) { + levelRenderState.blockEntityRenderStates.add(blockEntityRenderState2); + } + } + } + + for (BlockEntityRenderState blockEntityRenderState : levelRenderState.blockEntityRenderStates) { + BlockPos blockPos = blockEntityRenderState.blockPos; + poseStack.pushPose(); + poseStack.translate(blockPos.getX() - camX, blockPos.getY() - camY, blockPos.getZ() - camZ); + var blockEntityRenderDispatcher = this.minecraft.getBlockEntityRenderDispatcher(); + blockEntityRenderDispatcher.submit(blockEntityRenderState, poseStack, submitNodeStorage, levelRenderState.cameraRenderState); + poseStack.popPose(); + } + } + + public void setPartialTick(float partialTick) { + this.partialTick = partialTick; } public void scheduleGraphUpdate() { @@ -447,6 +509,8 @@ public SectionGrid getSectionGrid() { } public ChunkAreaManager getChunkAreaManager() { + if (this.sectionGrid == null) + return null; return this.sectionGrid.chunkAreaManager; } @@ -463,12 +527,28 @@ public int getRenderDistance() { } public String getChunkStatistics() { + if (this.sectionGraph == null) { + return null; + } + return this.sectionGraph.getStatistics(); } public void cleanUp() { if (indirectBuffers != null) - Arrays.stream(indirectBuffers).forEach(Buffer::freeBuffer); + Arrays.stream(indirectBuffers).forEach(Buffer::scheduleFree); + } + + public static WorldRenderer getInstance() { + return INSTANCE; + } + + public static ClientLevel getLevel() { + return INSTANCE.level; + } + + public static Vec3 getCameraPos() { + return INSTANCE.cameraPos; } } diff --git a/src/main/java/net/vulkanmod/render/chunk/buffer/AreaBuffer.java b/src/main/java/net/vulkanmod/render/chunk/buffer/AreaBuffer.java index b19f3a112..018324a69 100644 --- a/src/main/java/net/vulkanmod/render/chunk/buffer/AreaBuffer.java +++ b/src/main/java/net/vulkanmod/render/chunk/buffer/AreaBuffer.java @@ -4,6 +4,9 @@ import net.vulkanmod.Initializer; import net.vulkanmod.render.chunk.util.Util; import net.vulkanmod.vulkan.memory.*; +import net.vulkanmod.vulkan.memory.buffer.Buffer; +import net.vulkanmod.vulkan.memory.buffer.IndexBuffer; +import net.vulkanmod.vulkan.memory.buffer.VertexBuffer; import org.apache.logging.log4j.Logger; import java.nio.ByteBuffer; @@ -49,14 +52,61 @@ private Buffer allocateBuffer() { return buffer; } - public Segment upload(ByteBuffer byteBuffer, int oldOffset, DrawBuffers.DrawParameters drawParameters) { - // Free old segment - if (oldOffset != -1) { + public Segment allocateSegment(int size) { + if (DEBUG && size % elementSize != 0) + throw new RuntimeException("Unaligned buffer"); + + Segment segment = findSegment(size); + + if (segment.size - size > 0) { + Segment s1 = new Segment(segment.offset + size, segment.size - size); + segments++; + + if (segment.next != null) { + s1.bindNext(segment.next); + } else + this.last = s1; + + segment.bindNext(s1); + + segment.size = size; + } + + segment.free = false; + this.usedSegments.put(segment.offset, segment); + + segment.paramsPtr = 0; + + this.used += size; + + return segment; + } + + public void freeSegment(int offset) { + if (offset != -1) { // Need to delay segment freeing since it might be still used by prev frames in flight // this.setSegmentFree(oldOffset); - MemoryManager.getInstance().addToFreeSegment(this, oldOffset); + MemoryManager.getInstance().addToFreeSegment(this, offset); + } + } + + public void upload(Segment segment, ByteBuffer byteBuffer, int offset) { + int size = byteBuffer.remaining(); + + if (DEBUG && size % elementSize != 0) + throw new RuntimeException("Unaligned buffer"); + + if (size + offset > segment.size) { + throw new RuntimeException("trying to upload %d at offset %d, but segment size is %d".formatted(size, offset, segment.size)); } + Buffer dst = this.buffer; + UploadManager.INSTANCE.recordUpload(dst, segment.offset + offset, size, byteBuffer); + } + + public Segment upload(ByteBuffer byteBuffer, int oldOffset, long paramsPtr) { + freeSegment(oldOffset); + int size = byteBuffer.remaining(); if (DEBUG && size % elementSize != 0) @@ -81,7 +131,7 @@ public Segment upload(ByteBuffer byteBuffer, int oldOffset, DrawBuffers.DrawPara segment.free = false; this.usedSegments.put(segment.offset, segment); - segment.drawParameters = drawParameters; + segment.paramsPtr = paramsPtr; Buffer dst = this.buffer; UploadManager.INSTANCE.recordUpload(dst, segment.offset, size, byteBuffer); @@ -115,9 +165,10 @@ public Segment reallocate(int uploadSize) { int oldSize = this.size; int minIncrement = this.size >> 3; - minIncrement = Util.align(minIncrement, this.elementSize); + minIncrement = (int) Util.align(minIncrement, this.elementSize); - int increment = Math.max(minIncrement, uploadSize << 1); +// int increment = Math.max(minIncrement, uploadSize << 1); + int increment = Math.max(minIncrement, uploadSize); if (increment < uploadSize) throw new RuntimeException(String.format("Size increment %d < %d (Upload size)", increment, uploadSize)); @@ -132,7 +183,7 @@ public Segment reallocate(int uploadSize) { // TODO: moving only used segments causes corruption // moveUsedSegments(dst); - this.buffer.freeBuffer(); + this.buffer.scheduleFree(); this.buffer = dst; if (last.isFree()) { @@ -227,7 +278,7 @@ public void setSegmentFree(int offset) { this.used -= segment.size; segment.free = true; - segment.drawParameters = null; + segment.paramsPtr = -1; Segment next = segment.next; if (next != null && next.isFree()) { @@ -254,13 +305,11 @@ private void mergeSegments(Segment segment, Segment next) { } private void updateDrawParams(Segment segment) { - DrawBuffers.DrawParameters params = segment.drawParameters; - int elementOffset = segment.offset / elementSize; if (this.usage == Usage.VERTEX.usage) { - params.vertexOffset = elementOffset; + DrawParametersBuffer.setVertexOffset(segment.paramsPtr, elementOffset); } else { - params.firstIndex = elementOffset; + DrawParametersBuffer.setFirstIndex(segment.paramsPtr, elementOffset); } } @@ -269,7 +318,7 @@ public long getId() { } public void freeBuffer() { - this.buffer.freeBuffer(); + this.buffer.scheduleFree(); } public int fragmentation() { @@ -351,7 +400,7 @@ public int getUsed() { public static class Segment { int offset, size; boolean free = true; - DrawBuffers.DrawParameters drawParameters; + long paramsPtr; Segment next, prev; diff --git a/src/main/java/net/vulkanmod/render/chunk/buffer/DrawBuffers.java b/src/main/java/net/vulkanmod/render/chunk/buffer/DrawBuffers.java index 8556e0426..f43a5200b 100644 --- a/src/main/java/net/vulkanmod/render/chunk/buffer/DrawBuffers.java +++ b/src/main/java/net/vulkanmod/render/chunk/buffer/DrawBuffers.java @@ -1,14 +1,17 @@ package net.vulkanmod.render.chunk.buffer; +import net.minecraft.world.phys.Vec3; +import net.vulkanmod.Initializer; import net.vulkanmod.render.PipelineManager; -import net.vulkanmod.render.chunk.ChunkArea; +import net.vulkanmod.render.chunk.ChunkAreaManager; import net.vulkanmod.render.chunk.RenderSection; import net.vulkanmod.render.chunk.build.UploadBuffer; +import net.vulkanmod.render.chunk.cull.QuadFacing; import net.vulkanmod.render.chunk.util.StaticQueue; import net.vulkanmod.render.vertex.CustomVertexFormat; import net.vulkanmod.render.vertex.TerrainRenderType; import net.vulkanmod.vulkan.Renderer; -import net.vulkanmod.vulkan.memory.IndirectBuffer; +import net.vulkanmod.vulkan.memory.buffer.IndirectBuffer; import net.vulkanmod.vulkan.shader.Pipeline; import org.joml.Vector3i; import org.lwjgl.system.MemoryStack; @@ -21,8 +24,15 @@ import static org.lwjgl.vulkan.VK10.*; public class DrawBuffers { - private static final int VERTEX_SIZE = PipelineManager.TERRAIN_VERTEX_FORMAT.getVertexSize(); - private static final int INDEX_SIZE = Short.BYTES; + public static final int VERTEX_SIZE = PipelineManager.terrainVertexFormat.getVertexSize(); + public static final int INDEX_SIZE = Short.BYTES; + public static final int UNDEFINED_FACING_IDX = QuadFacing.UNDEFINED.ordinal(); + public static final float POS_OFFSET = CustomVertexFormat.getPositionOffset(); + + private static final int CMD_STRIDE = 32; + + private static final long cmdBufferPtr = MemoryUtil.nmemAlignedAlloc(CMD_STRIDE, (long) ChunkAreaManager.AREA_SIZE * QuadFacing.COUNT * CMD_STRIDE); + private final int index; private final Vector3i origin; private final int minHeight; @@ -31,36 +41,105 @@ public class DrawBuffers { AreaBuffer indexBuffer; private final EnumMap vertexBuffers = new EnumMap<>(TerrainRenderType.class); - //Need ugly minHeight Parameter to fix custom world heights (exceeding 384 Blocks in total) + long drawParamsPtr; + final int[] sectionIndices = new int[512]; + final int[] masks = new int[512]; + + // Need ugly minHeight parameter to fix custom world heights (exceeding 384 Blocks in total) public DrawBuffers(int index, Vector3i origin, int minHeight) { this.index = index; this.origin = origin; this.minHeight = minHeight; + + this.drawParamsPtr = DrawParametersBuffer.allocateBuffer(); } public void upload(RenderSection section, UploadBuffer buffer, TerrainRenderType renderType) { - DrawParameters drawParameters = section.getDrawParameters(renderType); - int vertexOffset = drawParameters.vertexOffset; - int firstIndex = -1; + var vertexBuffers = buffer.getVertexBuffers(); + + if (buffer.indexOnly) { + long paramsPtr = DrawParametersBuffer.getParamsPtr(this.drawParamsPtr, section.inAreaIndex, renderType.ordinal(), QuadFacing.UNDEFINED.ordinal()); + + int firstIndex = DrawParametersBuffer.getFirstIndex(paramsPtr); + int indexCount = DrawParametersBuffer.getIndexCount(paramsPtr); - if (!buffer.indexOnly) { - AreaBuffer.Segment segment = this.getAreaBufferOrAlloc(renderType).upload(buffer.getVertexBuffer(), vertexOffset, drawParameters); - vertexOffset = segment.offset / VERTEX_SIZE; + int oldOffset = indexCount > 0 ? firstIndex : -1; + AreaBuffer.Segment segment = this.indexBuffer.upload(buffer.getIndexBuffer(), oldOffset, paramsPtr); + firstIndex = segment.offset / INDEX_SIZE; + + DrawParametersBuffer.setFirstIndex(paramsPtr, firstIndex); - drawParameters.baseInstance = encodeSectionOffset(section.xOffset(), section.yOffset(), section.zOffset()); + buffer.release(); + return; } - if (!buffer.autoIndices) { - if (this.indexBuffer == null) - this.indexBuffer = new AreaBuffer(AreaBuffer.Usage.INDEX, 60000, INDEX_SIZE); + int oldOffset = -1; + int size = 0; + for (int i = 0; i < QuadFacing.COUNT; i++) { + long paramPtr = DrawParametersBuffer.getParamsPtr(this.drawParamsPtr, section.inAreaIndex, renderType.ordinal(), i); + int vertexOffset = DrawParametersBuffer.getVertexOffset(paramPtr); - AreaBuffer.Segment segment = this.indexBuffer.upload(buffer.getIndexBuffer(), drawParameters.firstIndex, drawParameters); - firstIndex = segment.offset / INDEX_SIZE; + // Only need to get first used offset, as it identifies the whole segment that will be freed + if (oldOffset == -1) { + oldOffset = vertexOffset; + } + + var vertexBuffer = vertexBuffers[i]; + if (vertexBuffer != null) { + size += vertexBuffer.remaining(); + + } + } + + AreaBuffer areaBuffer = null; + AreaBuffer.Segment segment = null; + boolean doUpload = false; + if (size > 0) { + areaBuffer = this.getAreaBufferOrAlloc(renderType); + areaBuffer.freeSegment(oldOffset); + segment = areaBuffer.allocateSegment(size); + doUpload = true; } - drawParameters.indexCount = buffer.indexCount; - drawParameters.firstIndex = firstIndex; - drawParameters.vertexOffset = vertexOffset; + int baseInstance = encodeSectionOffset(section.xOffset(), section.yOffset(), section.zOffset()); + + int offset = 0; + for (int i = 0; i < QuadFacing.COUNT; i++) { + long paramPtr = DrawParametersBuffer.getParamsPtr(this.drawParamsPtr, section.inAreaIndex, renderType.ordinal(), i); + + int vertexOffset = -1; + int firstIndex = 0; + int indexCount = 0; + + var vertexBuffer = vertexBuffers[i]; + int vertexCount = 0; + + if (vertexBuffer != null && doUpload) { + areaBuffer.upload(segment, vertexBuffer, offset); + vertexOffset = (segment.offset + offset) / VERTEX_SIZE; + + offset += vertexBuffer.remaining(); + vertexCount = vertexBuffer.limit() / VERTEX_SIZE; + indexCount = vertexCount * 6 / 4; + } + + if (i == QuadFacing.UNDEFINED.ordinal() && !buffer.autoIndices) { + if (this.indexBuffer == null) { + this.indexBuffer = new AreaBuffer(AreaBuffer.Usage.INDEX, 60000, INDEX_SIZE); + } + + oldOffset = DrawParametersBuffer.getIndexCount(paramPtr) > 0 ? DrawParametersBuffer.getFirstIndex(paramPtr) : -1; + AreaBuffer.Segment ibSegment = this.indexBuffer.upload(buffer.getIndexBuffer(), oldOffset, paramPtr); + firstIndex = ibSegment.offset / INDEX_SIZE; + } else { + Renderer.getDrawer().getQuadsIndexBuffer().checkCapacity(vertexCount); + } + + DrawParametersBuffer.setIndexCount(paramPtr, indexCount); + DrawParametersBuffer.setFirstIndex(paramPtr, firstIndex); + DrawParametersBuffer.setVertexOffset(paramPtr, vertexOffset); + DrawParametersBuffer.setBaseInstance(paramPtr, baseInstance); + } buffer.release(); } @@ -93,9 +172,6 @@ private int encodeSectionOffset(int xOffset, int yOffset, int zOffset) { return yOffset1 << 16 | zOffset1 << 8 | xOffset1; } - // TODO: refactor - public static final float POS_OFFSET = PipelineManager.TERRAIN_VERTEX_FORMAT == CustomVertexFormat.COMPRESSED_TERRAIN ? 4.0f : 0.0f; - private void updateChunkAreaOrigin(VkCommandBuffer commandBuffer, Pipeline pipeline, double camX, double camY, double camZ, MemoryStack stack) { float xOffset = (float) ((this.origin.x) + POS_OFFSET - camX); float yOffset = (float) ((this.origin.y) + POS_OFFSET - camY); @@ -110,73 +186,278 @@ private void updateChunkAreaOrigin(VkCommandBuffer commandBuffer, Pipeline pipel vkCmdPushConstants(commandBuffer, pipeline.getLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, byteBuffer); } - public void buildDrawBatchesIndirect(IndirectBuffer indirectBuffer, StaticQueue queue, TerrainRenderType terrainRenderType) { + public void buildDrawBatchesIndirect(Vec3 cameraPos, IndirectBuffer indirectBuffer, StaticQueue queue, TerrainRenderType terrainRenderType) { + long bufferPtr = cmdBufferPtr; - try (MemoryStack stack = MemoryStack.stackPush()) { + boolean isTranslucent = terrainRenderType == TerrainRenderType.TRANSLUCENT; + boolean backFaceCulling = Initializer.CONFIG.backFaceCulling && !isTranslucent; - ByteBuffer byteBuffer = stack.malloc(20 * queue.size()); - long bufferPtr = MemoryUtil.memAddress0(byteBuffer); + int drawCount = 0; - boolean isTranslucent = terrainRenderType == TerrainRenderType.TRANSLUCENT; + long drawParamsBasePtr = this.drawParamsPtr + (terrainRenderType.ordinal() * DrawParametersBuffer.SECTIONS * DrawParametersBuffer.FACINGS) * DrawParametersBuffer.STRIDE; + final long facingsStride = DrawParametersBuffer.FACINGS * DrawParametersBuffer.STRIDE; - int drawCount = 0; + int count = 0; + if (backFaceCulling) { for (var iterator = queue.iterator(isTranslucent); iterator.hasNext(); ) { + final RenderSection section = iterator.next(); + + sectionIndices[count] = section.inAreaIndex; + masks[count] = getMask(cameraPos, section); + count++; + } + + long ptr = bufferPtr; + + for (int j = 0; j < count; ++j) { + final int sectionIdx = sectionIndices[j]; + + int mask = masks[j]; + + long drawParamsBasePtr2 = drawParamsBasePtr + (sectionIdx * facingsStride); + + int indexCount = 0; + int firstIndex = 0; + int vertexOffset = 0; + int baseInstance = 0; + + for (int i = 0; i < QuadFacing.COUNT; i++) { + + if ((mask & 1 << i) == 0) { + drawParamsBasePtr2 += DrawParametersBuffer.STRIDE; + + // Flush draw cmd + if (indexCount > 0) { + MemoryUtil.memPutInt(ptr, indexCount); + MemoryUtil.memPutInt(ptr + 4, 1); + MemoryUtil.memPutInt(ptr + 8, firstIndex); + MemoryUtil.memPutInt(ptr + 12, vertexOffset); + MemoryUtil.memPutInt(ptr + 16, baseInstance); + + ptr += CMD_STRIDE; + drawCount++; + } + indexCount = 0; + firstIndex = 0; + vertexOffset = 0; + baseInstance = 0; + + continue; + } + + long drawParamsPtr = drawParamsBasePtr2; + + final int indexCount_i = DrawParametersBuffer.getIndexCount(drawParamsPtr); + final int firstIndex_i = DrawParametersBuffer.getFirstIndex(drawParamsPtr); + final int vertexOffset_i = DrawParametersBuffer.getVertexOffset(drawParamsPtr); + final int baseInstance_i = DrawParametersBuffer.getBaseInstance(drawParamsPtr); + + if (indexCount == 0) { + indexCount = indexCount_i; + firstIndex = firstIndex_i; + vertexOffset = vertexOffset_i; + baseInstance = baseInstance_i; + } + else { + indexCount += indexCount_i; + } + + drawParamsBasePtr2 += DrawParametersBuffer.STRIDE; + } + + if (indexCount > 0) { + MemoryUtil.memPutInt(ptr, indexCount); + MemoryUtil.memPutInt(ptr + 4, 1); + MemoryUtil.memPutInt(ptr + 8, firstIndex); + MemoryUtil.memPutInt(ptr + 12, vertexOffset); + MemoryUtil.memPutInt(ptr + 16, baseInstance); + + ptr += CMD_STRIDE; + drawCount++; + } + } + + } + else { + for (var iterator = queue.iterator(isTranslucent); iterator.hasNext(); ) { final RenderSection section = iterator.next(); - final DrawParameters drawParameters = section.getDrawParameters(terrainRenderType); - if (drawParameters.indexCount <= 0) + sectionIndices[count] = section.inAreaIndex; + count++; + } + + final long facingOffset = UNDEFINED_FACING_IDX * DrawParametersBuffer.STRIDE; + drawParamsBasePtr += facingOffset; + + long ptr = bufferPtr; + for (int i = 0; i < count; ++i) { + int sectionIdx = sectionIndices[i]; + + long drawParamsPtr = drawParamsBasePtr + (sectionIdx * facingsStride); + + final int indexCount = DrawParametersBuffer.getIndexCount(drawParamsPtr); + final int firstIndex = DrawParametersBuffer.getFirstIndex(drawParamsPtr); + final int vertexOffset = DrawParametersBuffer.getVertexOffset(drawParamsPtr); + final int baseInstance = DrawParametersBuffer.getBaseInstance(drawParamsPtr); + + if (indexCount <= 0) { continue; + } - long ptr = bufferPtr + (drawCount * 20L); - MemoryUtil.memPutInt(ptr, drawParameters.indexCount); + MemoryUtil.memPutInt(ptr, indexCount); MemoryUtil.memPutInt(ptr + 4, 1); - MemoryUtil.memPutInt(ptr + 8, drawParameters.firstIndex == -1 ? 0 : drawParameters.firstIndex); - MemoryUtil.memPutInt(ptr + 12, drawParameters.vertexOffset); - MemoryUtil.memPutInt(ptr + 16, drawParameters.baseInstance); + MemoryUtil.memPutInt(ptr + 8, firstIndex); + MemoryUtil.memPutInt(ptr + 12, vertexOffset); + MemoryUtil.memPutInt(ptr + 16, baseInstance); + ptr += CMD_STRIDE; drawCount++; } + } + + if (drawCount == 0) { + return; + } + + ByteBuffer byteBuffer = MemoryUtil.memByteBuffer(cmdBufferPtr, queue.size() * QuadFacing.COUNT * CMD_STRIDE); + indirectBuffer.recordCopyCmd(byteBuffer.position(0)); + + vkCmdDrawIndexedIndirect(Renderer.getCommandBuffer(), indirectBuffer.getId(), indirectBuffer.getOffset(), drawCount, CMD_STRIDE); + } + + public void buildDrawBatchesDirect(Vec3 cameraPos, StaticQueue queue, TerrainRenderType terrainRenderType) { + boolean isTranslucent = terrainRenderType == TerrainRenderType.TRANSLUCENT; + boolean backFaceCulling = Initializer.CONFIG.backFaceCulling && !isTranslucent; + + VkCommandBuffer commandBuffer = Renderer.getCommandBuffer(); + + long drawParamsBasePtr = this.drawParamsPtr + (terrainRenderType.ordinal() * DrawParametersBuffer.SECTIONS * DrawParametersBuffer.FACINGS) * DrawParametersBuffer.STRIDE; + final long facingsStride = DrawParametersBuffer.FACINGS * DrawParametersBuffer.STRIDE; + + int count = 0; + if (backFaceCulling) { + for (var iterator = queue.iterator(isTranslucent); iterator.hasNext(); ) { + final RenderSection section = iterator.next(); + + sectionIndices[count] = section.inAreaIndex; + masks[count] = getMask(cameraPos, section); + count++; + } + + for (int j = 0; j < count; ++j) { + final int sectionIdx = sectionIndices[j]; + + int mask = masks[j]; + + long drawParamsBasePtr2 = drawParamsBasePtr + (sectionIdx * facingsStride); + + int indexCount = 0; + int firstIndex = 0; + int vertexOffset = 0; + int baseInstance = 0; + + for (int i = 0; i < QuadFacing.COUNT; i++) { + + if ((mask & 1 << i) == 0) { + drawParamsBasePtr2 += DrawParametersBuffer.STRIDE; + + // Flush draw cmd + if (indexCount > 0) { + vkCmdDrawIndexed(commandBuffer, indexCount, 1, firstIndex, vertexOffset, baseInstance); + } + + indexCount = 0; + firstIndex = 0; + vertexOffset = 0; + baseInstance = 0; - if (drawCount == 0) return; + continue; + } - indirectBuffer.recordCopyCmd(byteBuffer.position(0)); + long drawParamsPtr = drawParamsBasePtr2; + final int indexCount_i = DrawParametersBuffer.getIndexCount(drawParamsPtr); + final int firstIndex_i = DrawParametersBuffer.getFirstIndex(drawParamsPtr); + final int vertexOffset_i = DrawParametersBuffer.getVertexOffset(drawParamsPtr); + final int baseInstance_i = DrawParametersBuffer.getBaseInstance(drawParamsPtr); + + if (indexCount == 0) { + indexCount = indexCount_i; + firstIndex = firstIndex_i; + vertexOffset = vertexOffset_i; + baseInstance = baseInstance_i; + } + else { + indexCount += indexCount_i; + } + + drawParamsBasePtr2 += DrawParametersBuffer.STRIDE; + } + + if (indexCount > 0) { + vkCmdDrawIndexed(commandBuffer, indexCount, 1, firstIndex, vertexOffset, baseInstance); + } + } - vkCmdDrawIndexedIndirect(Renderer.getCommandBuffer(), indirectBuffer.getId(), indirectBuffer.getOffset(), drawCount, 20); } + else { + final long facingOffset = UNDEFINED_FACING_IDX * DrawParametersBuffer.STRIDE; + drawParamsBasePtr += facingOffset; + for (var iterator = queue.iterator(isTranslucent); iterator.hasNext(); ) { + final RenderSection section = iterator.next(); - } + sectionIndices[count] = section.inAreaIndex; + count++; + } - public void buildDrawBatchesDirect(StaticQueue queue, TerrainRenderType renderType) { - boolean isTranslucent = renderType == TerrainRenderType.TRANSLUCENT; - VkCommandBuffer commandBuffer = Renderer.getCommandBuffer(); + for (int i = 0; i < count; ++i) { + int sectionIdx = sectionIndices[i]; - for (var iterator = queue.iterator(isTranslucent); iterator.hasNext(); ) { - final RenderSection section = iterator.next(); - final DrawParameters drawParameters = section.getDrawParameters(renderType); + long drawParamsPtr = drawParamsBasePtr + (sectionIdx * facingsStride); - if (drawParameters.indexCount <= 0) - continue; + final int indexCount = DrawParametersBuffer.getIndexCount(drawParamsPtr); + final int firstIndex = DrawParametersBuffer.getFirstIndex(drawParamsPtr); + final int vertexOffset = DrawParametersBuffer.getVertexOffset(drawParamsPtr); + final int baseInstance = DrawParametersBuffer.getBaseInstance(drawParamsPtr); + + if (indexCount <= 0) { + continue; + } - final int firstIndex = drawParameters.firstIndex == -1 ? 0 : drawParameters.firstIndex; - vkCmdDrawIndexed(commandBuffer, drawParameters.indexCount, 1, firstIndex, drawParameters.vertexOffset, drawParameters.baseInstance); + vkCmdDrawIndexed(commandBuffer, indexCount, 1, firstIndex, vertexOffset, baseInstance); + } } } - public void bindBuffers(VkCommandBuffer commandBuffer, Pipeline pipeline, TerrainRenderType terrainRenderType, double camX, double camY, double camZ) { + private int getMask(Vec3 camera, RenderSection section) { + final int secX = section.xOffset; + final int secY = section.yOffset; + final int secZ = section.zOffset; + + int mask = 1 << UNDEFINED_FACING_IDX; + mask |= camera.x - secX >= 0 ? 1 << QuadFacing.X_POS.ordinal() : 0; + mask |= camera.y - secY >= 0 ? 1 << QuadFacing.Y_POS.ordinal() : 0; + mask |= camera.z - secZ >= 0 ? 1 << QuadFacing.Z_POS.ordinal() : 0; + mask |= camera.x - (secX + 16) < 0 ? 1 << QuadFacing.X_NEG.ordinal() : 0; + mask |= camera.y - (secY + 16) < 0 ? 1 << QuadFacing.Y_NEG.ordinal() : 0; + mask |= camera.z - (secZ + 16) < 0 ? 1 << QuadFacing.Z_NEG.ordinal() : 0; + + return mask; + } + + public void bindBuffers(VkCommandBuffer commandBuffer, Pipeline pipeline, TerrainRenderType terrainRenderType, double camX, double camY, double camZ) { try (MemoryStack stack = MemoryStack.stackPush()) { var vertexBuffer = getAreaBuffer(terrainRenderType); nvkCmdBindVertexBuffers(commandBuffer, 0, 1, stack.npointer(vertexBuffer.getId()), stack.npointer(0)); updateChunkAreaOrigin(commandBuffer, pipeline, camX, camY, camZ, stack); } - if (terrainRenderType == TerrainRenderType.TRANSLUCENT) { + if (terrainRenderType == TerrainRenderType.TRANSLUCENT && this.indexBuffer != null) { vkCmdBindIndexBuffer(commandBuffer, this.indexBuffer.getId(), 0, VK_INDEX_TYPE_UINT16); } - } public void releaseBuffers() { @@ -193,6 +474,12 @@ public void releaseBuffers() { this.allocated = false; } + public void free() { + this.releaseBuffers(); + + DrawParametersBuffer.freeBuffer(this.drawParamsPtr); + } + public boolean isAllocated() { return !this.vertexBuffers.isEmpty(); } @@ -205,25 +492,8 @@ public AreaBuffer getIndexBuffer() { return indexBuffer; } - public static class DrawParameters { - int indexCount = 0; - int firstIndex = -1; - int vertexOffset = -1; - int baseInstance; - - public DrawParameters() {} - - public void reset(ChunkArea chunkArea, TerrainRenderType r) { - AreaBuffer areaBuffer = chunkArea.getDrawBuffers().getAreaBuffer(r); - if (areaBuffer != null && this.vertexOffset != -1) { - int segmentOffset = this.vertexOffset * VERTEX_SIZE; - areaBuffer.setSegmentFree(segmentOffset); - } - - this.indexCount = 0; - this.firstIndex = -1; - this.vertexOffset = -1; - } + public long getDrawParamsPtr() { + return drawParamsPtr; } } diff --git a/src/main/java/net/vulkanmod/render/chunk/buffer/DrawParametersBuffer.java b/src/main/java/net/vulkanmod/render/chunk/buffer/DrawParametersBuffer.java new file mode 100644 index 000000000..f26c2420d --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/buffer/DrawParametersBuffer.java @@ -0,0 +1,77 @@ +package net.vulkanmod.render.chunk.buffer; + +import net.vulkanmod.render.chunk.ChunkAreaManager; +import net.vulkanmod.render.chunk.cull.QuadFacing; +import net.vulkanmod.render.vertex.TerrainRenderType; +import org.lwjgl.system.MemoryUtil; + +public abstract class DrawParametersBuffer { + static final long INDEX_COUNT_OFFSET = 0; + static final long FIRST_INDEX_OFFSET = 4; + static final long VERTEX_OFFSET_OFFSET = 8; + static final long BASE_INSTANCE_OFFSET = 12; + + public static final long STRIDE = 16; + + static final int SECTIONS = ChunkAreaManager.AREA_SIZE; + static final int FACINGS = 7; + + public static long allocateBuffer() { + int size = (int) (ChunkAreaManager.AREA_SIZE * TerrainRenderType.VALUES.length * QuadFacing.COUNT * DrawParametersBuffer.STRIDE); + long drawParamsPtr = MemoryUtil.nmemAlignedAlloc(32, size); + + for (long ptr = drawParamsPtr; ptr < drawParamsPtr + size; ptr += DrawParametersBuffer.STRIDE) { + DrawParametersBuffer.resetParameters(ptr); + } + + return drawParamsPtr; + } + + public static void freeBuffer(long ptr) { + MemoryUtil.nmemAlignedFree(ptr); + } + + public static long getParamsPtr(long basePtr, int section, int renderType, int facing) { + return basePtr + (((renderType * SECTIONS + section) * FACINGS) + facing) * STRIDE; + } + + public static void resetParameters(long ptr) { + setIndexCount(ptr, 0); + setFirstIndex(ptr, 0); + setVertexOffset(ptr, -1); + setBaseInstance(ptr, 0); + } + + public static void setIndexCount(long ptr, int value) { + MemoryUtil.memPutInt(ptr + INDEX_COUNT_OFFSET, value); + } + + public static void setFirstIndex(long ptr, int value) { + MemoryUtil.memPutInt(ptr + FIRST_INDEX_OFFSET, value); + } + + public static void setVertexOffset(long ptr, int value) { + MemoryUtil.memPutInt(ptr + VERTEX_OFFSET_OFFSET, value); + } + + public static void setBaseInstance(long ptr, int value) { + MemoryUtil.memPutInt(ptr + BASE_INSTANCE_OFFSET, value); + } + + public static int getIndexCount(long ptr) { + return MemoryUtil.memGetInt(ptr + INDEX_COUNT_OFFSET); + } + + public static int getFirstIndex(long ptr) { + return MemoryUtil.memGetInt(ptr + FIRST_INDEX_OFFSET); + } + + public static int getVertexOffset(long ptr) { + return MemoryUtil.memGetInt(ptr + VERTEX_OFFSET_OFFSET); + } + + public static int getBaseInstance(long ptr) { + return MemoryUtil.memGetInt(ptr + BASE_INSTANCE_OFFSET); + } + +} diff --git a/src/main/java/net/vulkanmod/render/chunk/buffer/UploadManager.java b/src/main/java/net/vulkanmod/render/chunk/buffer/UploadManager.java index 9f14e3ccd..5ab8bee72 100644 --- a/src/main/java/net/vulkanmod/render/chunk/buffer/UploadManager.java +++ b/src/main/java/net/vulkanmod/render/chunk/buffer/UploadManager.java @@ -4,8 +4,8 @@ import net.vulkanmod.vulkan.Synchronization; import net.vulkanmod.vulkan.Vulkan; import net.vulkanmod.vulkan.device.DeviceManager; -import net.vulkanmod.vulkan.memory.Buffer; -import net.vulkanmod.vulkan.memory.StagingBuffer; +import net.vulkanmod.vulkan.memory.buffer.Buffer; +import net.vulkanmod.vulkan.memory.buffer.StagingBuffer; import net.vulkanmod.vulkan.queue.CommandPool; import net.vulkanmod.vulkan.queue.Queue; import net.vulkanmod.vulkan.queue.TransferQueue; @@ -43,13 +43,12 @@ public void submitUploads() { } public void recordUpload(Buffer buffer, long dstOffset, long bufferSize, ByteBuffer src) { - beginCommands(); - - VkCommandBuffer commandBuffer = this.commandBuffer.getHandle(); - StagingBuffer stagingBuffer = Vulkan.getStagingBuffer(); stagingBuffer.copyBuffer((int) bufferSize, src); + beginCommands(); + VkCommandBuffer commandBuffer = this.commandBuffer.getHandle(); + if (!this.dstBuffers.add(buffer.getId())) { try (MemoryStack stack = MemoryStack.stackPush()) { VkMemoryBarrier.Buffer barrier = VkMemoryBarrier.calloc(1, stack); @@ -75,7 +74,7 @@ public void copyBuffer(Buffer src, Buffer dst) { copyBuffer(src, 0, dst, 0, src.getBufferSize()); } - public void copyBuffer(Buffer src, int srcOffset, Buffer dst, int dstOffset, int size) { + public void copyBuffer(Buffer src, long srcOffset, Buffer dst, long dstOffset, long size) { beginCommands(); VkCommandBuffer commandBuffer = this.commandBuffer.getHandle(); diff --git a/src/main/java/net/vulkanmod/render/chunk/build/BlockRenderer.java b/src/main/java/net/vulkanmod/render/chunk/build/BlockRenderer.java deleted file mode 100644 index 7c3e95405..000000000 --- a/src/main/java/net/vulkanmod/render/chunk/build/BlockRenderer.java +++ /dev/null @@ -1,216 +0,0 @@ -package net.vulkanmod.render.chunk.build; - -import it.unimi.dsi.fastutil.objects.Object2ByteLinkedOpenHashMap; -import net.minecraft.client.Minecraft; -import net.minecraft.client.color.block.BlockColors; -import net.minecraft.client.renderer.block.model.BakedQuad; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Vec3i; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -import net.minecraft.world.phys.shapes.BooleanOp; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import net.vulkanmod.render.chunk.build.light.LightPipeline; -import net.vulkanmod.render.chunk.build.light.data.QuadLightData; -import net.vulkanmod.render.chunk.build.thread.BuilderResources; -import net.vulkanmod.render.model.quad.QuadUtils; -import net.vulkanmod.render.model.quad.QuadView; -import net.vulkanmod.render.vertex.TerrainBufferBuilder; -import net.vulkanmod.render.vertex.VertexUtil; -import net.vulkanmod.vulkan.util.ColorUtil; -import org.joml.Vector3f; - -import java.util.List; - -public class BlockRenderer { - - static final Direction[] DIRECTIONS = Direction.values(); - private static BlockColors blockColors; - - RandomSource randomSource = RandomSource.createNewThreadLocalInstance(); - - Vector3f pos; - BlockPos blockPos; - BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); - - BuilderResources resources; - - BlockState blockState; - - public void setResources(BuilderResources resources) { - this.resources = resources; - } - - final Object2ByteLinkedOpenHashMap occlusionCache = new Object2ByteLinkedOpenHashMap<>(2048, 0.25F) { - protected void rehash(int i) { - } - }; - - public BlockRenderer() { - occlusionCache.defaultReturnValue((byte) 127); - } - - public static void setBlockColors(BlockColors blockColors) { - BlockRenderer.blockColors = blockColors; - } - - public void renderBlock(BlockState blockState, BlockPos blockPos, Vector3f pos, TerrainBufferBuilder bufferBuilder) { - this.pos = pos; - this.blockPos = blockPos; - this.blockState = blockState; - - long seed = blockState.getSeed(blockPos); - - BakedModel model = Minecraft.getInstance().getBlockRenderer().getBlockModel(blockState); - tessellateBlock(model, bufferBuilder, seed); - } - - public void tessellateBlock(BakedModel bakedModel, TerrainBufferBuilder bufferBuilder, long seed) { - Vec3 offset = blockState.getOffset(resources.region, blockPos); - - pos.add((float) offset.x, (float) offset.y, (float) offset.z); - - boolean useAO = Minecraft.useAmbientOcclusion() && blockState.getLightEmission() == 0 && bakedModel.useAmbientOcclusion(); - LightPipeline lightPipeline = useAO ? resources.smoothLightPipeline : resources.flatLightPipeline; - - //noinspection ForLoopReplaceableByForEach - for (int i = 0; i < DIRECTIONS.length; ++i) { - Direction direction = DIRECTIONS[i]; - - randomSource.setSeed(seed); - List quads = bakedModel.getQuads(blockState, direction, randomSource); - - if (!quads.isEmpty()) { - mutableBlockPos.setWithOffset(blockPos, direction); - if (shouldRenderFace(blockState, direction, mutableBlockPos)) { - renderModelFace(bufferBuilder, quads, lightPipeline, direction); - } - } - } - - randomSource.setSeed(seed); - List quads = bakedModel.getQuads(blockState, null, randomSource); - if (!quads.isEmpty()) { - renderModelFace(bufferBuilder, quads, lightPipeline, null); - } - } - - private void renderModelFace(TerrainBufferBuilder bufferBuilder, List quads, LightPipeline lightPipeline, Direction cullFace) { - QuadLightData quadLightData = resources.quadLightData; - - for (int i = 0; i < quads.size(); ++i) { - BakedQuad bakedQuad = quads.get(i); - QuadView quadView = (QuadView) bakedQuad; - lightPipeline.calculate(quadView, blockPos, quadLightData, cullFace, bakedQuad.getDirection(), bakedQuad.isShade()); - putQuadData(bufferBuilder, quadView, quadLightData); - } - } - - private void putQuadData(TerrainBufferBuilder bufferBuilder, QuadView quadView, QuadLightData quadLightData) { - float r, g, b; - if (quadView.isTinted()) { - int color = blockColors.getColor(blockState, resources.region, blockPos, quadView.getColorIndex()); - r = ColorUtil.ARGB.unpackR(color); - g = ColorUtil.ARGB.unpackG(color); - b = ColorUtil.ARGB.unpackB(color); - } else { - r = 1.0F; - g = 1.0F; - b = 1.0F; - } - - putQuadData(bufferBuilder, pos, quadView, quadLightData, r, g, b); - } - - public static void putQuadData(TerrainBufferBuilder bufferBuilder, Vector3f pos, QuadView quad, QuadLightData quadLightData, float red, float green, float blue) { - Vec3i normal = quad.getFacingDirection().getNormal(); - int packedNormal = VertexUtil.packNormal(normal.getX(), normal.getY(), normal.getZ()); - - float[] brightnessArr = quadLightData.br; - int[] lights = quadLightData.lm; - - // Rotate triangles if needed to fix AO anisotropy - int idx = QuadUtils.getIterationStartIdx(brightnessArr, lights); - - bufferBuilder.ensureCapacity(); - - for (byte i = 0; i < 4; ++i) { - final float x = pos.x() + quad.getX(idx); - final float y = pos.y() + quad.getY(idx); - final float z = pos.z() + quad.getZ(idx); - - final float r, g, b; - final float quadR, quadG, quadB; - - final int quadColor = quad.getColor(idx); - quadR = ColorUtil.RGBA.unpackR(quadColor); - quadG = ColorUtil.RGBA.unpackG(quadColor); - quadB = ColorUtil.RGBA.unpackB(quadColor); - - final float brightness = brightnessArr[idx]; - r = quadR * brightness * red; - g = quadG * brightness * green; - b = quadB * brightness * blue; - - final int color = ColorUtil.RGBA.pack(r, g, b, 1.0f); - final int light = lights[idx]; - final float u = quad.getU(idx); - final float v = quad.getV(idx); - - bufferBuilder.vertex(x, y, z, color, u, v, light, packedNormal); - - idx = (idx + 1) & 0b11; - } - - } - - public boolean shouldRenderFace(BlockState blockState, Direction direction, BlockPos adjPos) { - BlockGetter blockGetter = resources.region; - BlockState adjBlockState = blockGetter.getBlockState(adjPos); - - if (blockState.skipRendering(adjBlockState, direction)) { - return false; - } - - if (adjBlockState.canOcclude()) { - VoxelShape shape = blockState.getFaceOcclusionShape(blockGetter, blockPos, direction); - - if (shape.isEmpty()) - return true; - - VoxelShape adjShape = adjBlockState.getFaceOcclusionShape(blockGetter, adjPos, direction.getOpposite()); - - if (adjShape.isEmpty()) - return true; - - if (shape == Shapes.block() && adjShape == Shapes.block()) { - return false; - } - - Block.BlockStatePairKey blockStatePairKey = new Block.BlockStatePairKey(blockState, adjBlockState, direction); - - byte b = occlusionCache.getAndMoveToFirst(blockStatePairKey); - if (b != 127) { - return b != 0; - } else { - boolean bl = Shapes.joinIsNotEmpty(shape, adjShape, BooleanOp.ONLY_FIRST); - - if (occlusionCache.size() == 2048) { - occlusionCache.removeLastByte(); - } - - occlusionCache.putAndMoveToFirst(blockStatePairKey, (byte) (bl ? 1 : 0)); - return bl; - } - } - - return true; - } -} - diff --git a/src/main/java/net/vulkanmod/render/chunk/build/RenderRegion.java b/src/main/java/net/vulkanmod/render/chunk/build/RenderRegion.java index 79a65a152..f9402f0ce 100644 --- a/src/main/java/net/vulkanmod/render/chunk/build/RenderRegion.java +++ b/src/main/java/net/vulkanmod/render/chunk/build/RenderRegion.java @@ -16,6 +16,8 @@ import net.minecraft.world.level.levelgen.DebugLevelSource; import net.minecraft.world.level.lighting.LevelLightEngine; import net.minecraft.world.level.material.FluidState; +import net.vulkanmod.render.chunk.build.biome.BiomeData; +import net.vulkanmod.render.chunk.build.color.TintCache; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -43,13 +45,15 @@ public class RenderRegion implements BlockAndTintGetter { private final BlockState[] blockData; private final DataLayer[][] lightData; + private BiomeData biomeData; private TintCache tintCache; private final Map blockEntityMap; private final Function blockStateGetter; - RenderRegion(Level level, int x, int y, int z, PalettedContainer[] blockData, DataLayer[][] lightData, Map blockEntityMap) { + RenderRegion(Level level, int x, int y, int z, PalettedContainer[] blockData, DataLayer[][] lightData, + BiomeData biomeData, Map blockEntityMap) { this.level = level; this.minSecX = x - 1; @@ -64,6 +68,7 @@ public class RenderRegion implements BlockAndTintGetter { this.blockDataContainers = blockData; this.lightData = lightData; + this.biomeData = biomeData; this.blockEntityMap = blockEntityMap; this.blockData = new BlockState[BLOCK_COUNT]; @@ -76,14 +81,14 @@ public class RenderRegion implements BlockAndTintGetter { public void loadBlockStates() { Arrays.fill(blockData, Blocks.AIR.defaultBlockState()); - for(int x = 0; x <= 2; ++x) { - for(int z = 0; z <= 2; ++z) { - for(int y = 0; y <= 2; ++y) { + for (int x = 0; x <= 2; ++x) { + for (int z = 0; z <= 2; ++z) { + for (int y = 0; y <= 2; ++y) { final int idx = getSectionIdx(x, y, z); PalettedContainer container = blockDataContainers[idx]; - if(container == null) + if (container == null) continue; int absBlockX = (x + minSecX) << 4; @@ -99,8 +104,8 @@ public void loadBlockStates() { int tMaxZ = Math.min(maxZ, absBlockZ + 16); loadSectionBlockStates(container, blockData, - tMinX, tMinY, tMinZ, tMaxX, tMaxY, tMaxZ); - + tMinX, tMinY, tMinZ, tMaxX, tMaxY, tMaxZ); + } } } @@ -124,7 +129,7 @@ void loadSectionBlockStates(PalettedContainer container, BlockState[ public void initTintCache(TintCache tintCache) { this.tintCache = tintCache; - this.tintCache.init(blendRadius, minSecX + 1, minSecY + 1, minSecZ + 1); + this.tintCache.init(biomeData, blendRadius, minSecX + 1, minSecY + 1, minSecZ + 1); } public BlockState getBlockState(BlockPos blockPos) { @@ -187,8 +192,8 @@ public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver) { return tintCache.getColor(blockPos, colorResolver); } - public int getMinBuildHeight() { - return this.level.getMinBuildHeight(); + public int getMinY() { + return this.level.getMinY(); } public int getHeight() { diff --git a/src/main/java/net/vulkanmod/render/chunk/build/RenderRegionBuilder.java b/src/main/java/net/vulkanmod/render/chunk/build/RenderRegionBuilder.java index adf6db694..b3148e219 100644 --- a/src/main/java/net/vulkanmod/render/chunk/build/RenderRegionBuilder.java +++ b/src/main/java/net/vulkanmod/render/chunk/build/RenderRegionBuilder.java @@ -10,6 +10,8 @@ import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunkSection; import net.minecraft.world.level.chunk.PalettedContainer; +import net.vulkanmod.interfaces.biome.BiomeManagerExtended; +import net.vulkanmod.render.chunk.build.biome.BiomeData; public class RenderRegionBuilder { private static final DataLayer DEFAULT_SKY_LIGHT_DATA_LAYER = new DataLayer(15); @@ -26,7 +28,7 @@ public RenderRegion createRegion(Level level, int secX, int secY, int secZ) { if (section == null || section.hasOnlyAir()) return null; - var entityMap = levelChunk.getBlockEntities(); + var blockEntityMap = levelChunk.getBlockEntities(); int minSecX = secX - 1; int minSecZ = secZ - 1; @@ -39,7 +41,10 @@ public RenderRegion createRegion(Level level, int secX, int secY, int secZ) { DataLayer[][] lightData = new DataLayer[RenderRegion.SIZE][2 /* Light types */]; - final int minHeightSec = level.getMinBuildHeight() >> 4; + long biomeZoomSeed = BiomeManagerExtended.of(level.getBiomeManager()).getBiomeZoomSeed(); + BiomeData biomeData = new BiomeData(biomeZoomSeed, minSecX, minSecY, minSecZ); + + final int minHeightSec = level.getMinY() >> 4; for (int x = minSecX; x <= maxSecX; ++x) { for (int z = minSecZ; z <= maxSecZ; ++z) { LevelChunk levelChunk1 = getLevelChunk(level, x, z); @@ -60,11 +65,13 @@ public RenderRegion createRegion(Level level, int secX, int secY, int secZ) { DataLayer[] dataLayers = getSectionDataLayers(level, pos); lightData[idx] = dataLayers; + + biomeData.getBiomeData(level, section, relX, relY, relZ); } } } - return new RenderRegion(level, secX, secY, secZ, blockData, lightData, entityMap); + return new RenderRegion(level, secX, secY, secZ, blockData, lightData, biomeData, blockEntityMap); } private DataLayer[] getSectionDataLayers(Level level, SectionPos pos) { diff --git a/src/main/java/net/vulkanmod/render/chunk/build/TintCache.java b/src/main/java/net/vulkanmod/render/chunk/build/TintCache.java deleted file mode 100644 index 2c296f955..000000000 --- a/src/main/java/net/vulkanmod/render/chunk/build/TintCache.java +++ /dev/null @@ -1,136 +0,0 @@ -package net.vulkanmod.render.chunk.build; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.BiomeColors; -import net.minecraft.core.BlockPos; -import net.minecraft.util.Mth; -import net.minecraft.world.level.ColorResolver; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.biome.Biome; -import net.vulkanmod.render.chunk.WorldRenderer; -import net.vulkanmod.render.chunk.build.biome.BoxBlur; - -import java.util.Arrays; -import java.util.function.BiFunction; - -public class TintCache { - private static final int SECTION_WIDTH = 16; - - private final Layer[] layers = new Layer[SECTION_WIDTH]; - - private int blendRadius, totalWidth; - private int secX, secY, secZ; - private int minX, minZ; - private int maxX, maxZ; - - private int dataSize; - private int[] temp; - - public TintCache() { - Arrays.fill(layers, new Layer()); - } - - public void init(int blendRadius, int secX, int secY, int secZ) { - this.blendRadius = Minecraft.getInstance().options.biomeBlendRadius().get(); - this.totalWidth = (blendRadius * 2) + 16; - - this.secX = secX; - this.secY = secY; - this.secZ = secZ; - - minX = (secX << 4) - blendRadius; - minZ = (secZ << 4) - blendRadius; - maxX = (secX << 4) + 16 + blendRadius; - maxZ = (secZ << 4) + 16 + blendRadius; - - int size = totalWidth * totalWidth; - - if(size != dataSize) { - this.dataSize = size; - for (Layer layer : layers) { - layer.allocate(size); - } - temp = new int[size]; - } else { - for (Layer layer : layers) { - layer.invalidate(); - } - } - } - - public int getColor(BlockPos blockPos, ColorResolver colorResolver) { - int relY = blockPos.getY() & 15; - Layer layer = layers[relY]; - if(layer.invalidated) - calculateLayer(relY); - - int[] values = layer.getValues(colorResolver); - int relX = blockPos.getX() & 15; - int relZ = blockPos.getZ() & 15; - int idx = totalWidth * (relZ + blendRadius) + (relX + blendRadius); - return values[idx]; - } - - public void calculateLayer(int y) { - Level level = WorldRenderer.getLevel(); - Layer layer = layers[y]; - - BlockPos.MutableBlockPos blockPos = new BlockPos.MutableBlockPos(); - int absY = (secY << 4) + y; - - Biome tB = level.getBiome(blockPos.set(minX, absY, minZ)).value(); - boolean mixed = false; - for (int absZ = minZ; absZ < maxZ ; absZ++) { - for (int absX = minX; absX < maxX ; absX++) { - blockPos.set(absX, absY, absZ); - Biome biome = level.getBiome(blockPos).value(); - - if (biome != tB) - mixed = true; - - final int idx = (absX - minX) + (absZ - minZ) * totalWidth; - layer.grass[idx] = biome.getGrassColor(absX, absZ); - layer.foliage[idx] = biome.getFoliageColor(); - layer.water[idx] = biome.getWaterColor(); - } - } - - if(mixed && blendRadius > 0) { - BoxBlur.blur(layer.grass, temp, SECTION_WIDTH, blendRadius); - BoxBlur.blur(layer.foliage, temp, SECTION_WIDTH, blendRadius); - BoxBlur.blur(layer.water, temp, SECTION_WIDTH, blendRadius); - } - - layer.invalidated = false; - } - - static class Layer { - private boolean invalidated = true; - - private int[] grass; - private int[] foliage; - private int[] water; - - void allocate(int size) { - grass = new int[size]; - foliage = new int[size]; - water = new int[size]; - invalidate(); - } - - void invalidate() { - this.invalidated = true; - } - - public int[] getValues(ColorResolver colorResolver) { - if(colorResolver == BiomeColors.GRASS_COLOR_RESOLVER) - return grass; - else if(colorResolver == BiomeColors.FOLIAGE_COLOR_RESOLVER) - return foliage; - else if(colorResolver == BiomeColors.WATER_COLOR_RESOLVER) - return water; - - throw new IllegalArgumentException("Unexpected resolver: " + colorResolver.toString()); - } - } -} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/UploadBuffer.java b/src/main/java/net/vulkanmod/render/chunk/build/UploadBuffer.java index cd8b72404..3254b19c4 100644 --- a/src/main/java/net/vulkanmod/render/chunk/build/UploadBuffer.java +++ b/src/main/java/net/vulkanmod/render/chunk/build/UploadBuffer.java @@ -1,7 +1,9 @@ package net.vulkanmod.render.chunk.build; +import net.vulkanmod.render.chunk.cull.QuadFacing; import net.vulkanmod.render.chunk.util.BufferUtil; import net.vulkanmod.render.vertex.TerrainBufferBuilder; +import net.vulkanmod.render.vertex.TerrainBuilder; import org.lwjgl.system.MemoryUtil; import java.nio.ByteBuffer; @@ -10,32 +12,43 @@ public class UploadBuffer { public final int indexCount; public final boolean autoIndices; public final boolean indexOnly; - private final ByteBuffer vertexBuffer; + private final ByteBuffer[] vertexBuffers; private final ByteBuffer indexBuffer; - public UploadBuffer(TerrainBufferBuilder.RenderedBuffer renderedBuffer) { - TerrainBufferBuilder.DrawState drawState = renderedBuffer.drawState(); + public UploadBuffer(TerrainBuilder terrainBuilder, TerrainBuilder.DrawState drawState) { this.indexCount = drawState.indexCount(); this.autoIndices = drawState.sequentialIndex(); this.indexOnly = drawState.indexOnly(); - if (!this.indexOnly) - this.vertexBuffer = BufferUtil.clone(renderedBuffer.vertexBuffer()); - else - this.vertexBuffer = null; + if (!this.indexOnly) { + this.vertexBuffers = new ByteBuffer[QuadFacing.COUNT]; - if (!drawState.sequentialIndex()) - this.indexBuffer = BufferUtil.clone(renderedBuffer.indexBuffer()); - else + for (int i = 0; i < QuadFacing.COUNT; i++) { + var bufferBuilder = terrainBuilder.getBufferBuilder(i); + + if (bufferBuilder.getVertices() > 0) { + this.vertexBuffers[i] = BufferUtil.clone(bufferBuilder.getBuffer()); + } + } + } + else { + this.vertexBuffers = null; + } + + if (!drawState.sequentialIndex()) { + this.indexBuffer = BufferUtil.clone(terrainBuilder.getIndexBuffer()); + } + else { this.indexBuffer = null; + } } public int indexCount() { return indexCount; } - public ByteBuffer getVertexBuffer() { - return vertexBuffer; + public ByteBuffer[] getVertexBuffers() { + return vertexBuffers; } public ByteBuffer getIndexBuffer() { @@ -43,8 +56,12 @@ public ByteBuffer getIndexBuffer() { } public void release() { - if (vertexBuffer != null) - MemoryUtil.memFree(vertexBuffer); + if (vertexBuffers != null) + for (var vertexBuffer : vertexBuffers) { + if (vertexBuffer != null) + MemoryUtil.memFree(vertexBuffer); + } + if (indexBuffer != null) MemoryUtil.memFree(indexBuffer); } diff --git a/src/main/java/net/vulkanmod/render/chunk/build/biome/BiomeData.java b/src/main/java/net/vulkanmod/render/chunk/build/biome/BiomeData.java new file mode 100644 index 000000000..fe701cbe6 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/biome/BiomeData.java @@ -0,0 +1,153 @@ +package net.vulkanmod.render.chunk.build.biome; + +import net.minecraft.core.registries.Registries; +import net.minecraft.util.LinearCongruentialGenerator; +import net.minecraft.util.Mth; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.Biomes; +import net.minecraft.world.level.chunk.LevelChunkSection; +import net.vulkanmod.render.chunk.build.RenderRegion; +import org.joml.Vector3f; + +public class BiomeData { + private static final int ZOOM_LENGTH = 4; + private static final int BIOMES_PER_SECTION = 4 * 4 * 4; + private static final int SIZE = RenderRegion.SIZE * BIOMES_PER_SECTION; + + Biome[] biomes = new Biome[SIZE]; + private final long biomeZoomSeed; + + int secX, secY, secZ; + + // Cached cell offsets + Vector3f[] offsets = new Vector3f[SIZE]; + + public BiomeData(long biomeZoomSeed, int secX, int secY, int secZ) { + this.biomeZoomSeed = biomeZoomSeed; + this.secX = secX; + this.secY = secY; + this.secZ = secZ; + } + + public void getBiomeData(Level level, LevelChunkSection chunkSection, int secX, int secY, int secZ) { + Biome defaultValue = level.registryAccess() + .lookupOrThrow(Registries.BIOME) + .getOrThrow(Biomes.PLAINS) + .value(); + + int baseIdx = getRelativeSectionIdx(secX, secY, secZ); + + for (int x = 0; x < 4; x++) { + for (int y = 0; y < 4; y++) { + for (int z = 0; z < 4; z++) { + int relIdx = getRelativeIdx(x, y, z); + int idx = baseIdx + relIdx; + + if (chunkSection != null) { + biomes[idx] = chunkSection.getNoiseBiome(x, y, z) + .value(); + } + else { + biomes[idx] = defaultValue; + } + + } + } + } + + } + + public Biome getBiome(int blockX, int blockY, int blockZ) { + int x = blockX - 2; + int y = blockY - 2; + int z = blockZ - 2; + + int zoomX = x >> 2; + int zoomY = y >> 2; + int zoomZ = z >> 2; + + float fracZoomX = (x & 3) * 0.25f; + float fracZoomY = (y & 3) * 0.25f; + float fracZoomZ = (z & 3) * 0.25f; + + int closestCellIdx = 0; + double closestDistance = Double.POSITIVE_INFINITY; + + for (int i = 0; i < 8; ++i) { + boolean dirX = (i & 4) != 0; + boolean dirY = (i & 2) != 0; + boolean dirZ = (i & 1) != 0; + + int cellX = dirX ? zoomX + 1 : zoomX; + int cellY = dirY ? zoomY + 1 : zoomY; + int cellZ = dirZ ? zoomZ + 1 : zoomZ; + + float fCellX = dirX ? fracZoomX - 1.0f : fracZoomX; + float fCellY = dirY ? fracZoomY - 1.0f : fracZoomY; + float fCellZ = dirZ ? fracZoomZ - 1.0f : fracZoomZ; + + int baseSectionIdx = getSectionIdx(cellX >> 2, cellY >> 2, cellZ >> 2); + int cellIdx = baseSectionIdx + getRelativeIdx(cellX & 3, cellY & 3, cellZ & 3); + + Vector3f offset = getOffset(baseSectionIdx, cellX, cellY, cellZ); + float distance = Mth.square(fCellX + offset.x()) + Mth.square(fCellY + offset.y()) + Mth.square(fCellZ + offset.z()); + + if (closestDistance > distance) { + closestCellIdx = cellIdx; + closestDistance = distance; + } + } + + return this.biomes[closestCellIdx]; + } + + private int getSectionIdx(int secX, int secY, int secZ) { + return getRelativeSectionIdx(secX - this.secX, secY - this.secY, secZ - this.secZ); + } + + private Vector3f getOffset(int baseIndex, int cellX, int cellY, int cellZ) { + int relCellX = cellX & 3; + int relCellY = cellY & 3; + int relCellZ = cellZ & 3; + int idx = baseIndex + getRelativeIdx(relCellX, relCellY, relCellZ); + + if (this.offsets[idx] == null) { + this.offsets[idx] = computeCellOffset(this.biomeZoomSeed, cellX, cellY, cellZ); + } + + return this.offsets[idx]; + } + + private static Vector3f computeCellOffset(long l, int cellX, int cellY, int cellZ) { + long seed; + seed = LinearCongruentialGenerator.next(l, cellX); + seed = LinearCongruentialGenerator.next(seed, cellY); + seed = LinearCongruentialGenerator.next(seed, cellZ); + seed = LinearCongruentialGenerator.next(seed, cellX); + seed = LinearCongruentialGenerator.next(seed, cellY); + seed = LinearCongruentialGenerator.next(seed, cellZ); + + float xOffset = getFiddle(seed); + seed = LinearCongruentialGenerator.next(seed, l); + float yOffset = getFiddle(seed); + seed = LinearCongruentialGenerator.next(seed, l); + float zOffset = getFiddle(seed); + + return new Vector3f(xOffset, yOffset, zOffset); + } + + private static float getFiddle(long l) { + float d = Math.floorMod(l >> 24, 1024) * (1.0f / 1024.0f); + return (d - 0.5f) * 0.9f; + } + + private static int getRelativeSectionIdx(int x, int y, int z) { + return ((x * RenderRegion.WIDTH * RenderRegion.WIDTH) + (y * RenderRegion.WIDTH) + z) * BIOMES_PER_SECTION; + } + + private static int getRelativeIdx(int x, int y, int z) { + return (x * ZOOM_LENGTH * ZOOM_LENGTH) + (y * ZOOM_LENGTH) + z; + } + +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/color/BlockColorRegistry.java b/src/main/java/net/vulkanmod/render/chunk/build/color/BlockColorRegistry.java new file mode 100644 index 000000000..b8ec0ca39 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/color/BlockColorRegistry.java @@ -0,0 +1,21 @@ +package net.vulkanmod.render.chunk.build.color; + +import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; +import net.minecraft.client.color.block.BlockColor; +import net.minecraft.world.level.block.Block; + +public class BlockColorRegistry { + + private final Reference2ReferenceOpenHashMap map = new Reference2ReferenceOpenHashMap<>(); + + public void register(BlockColor blockColor, Block... blocks) { + for (Block block : blocks) { + this.map.put(block, blockColor); + } + } + + public BlockColor getBlockColor(Block block) { + return this.map.get(block); + } + +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/biome/BoxBlur.java b/src/main/java/net/vulkanmod/render/chunk/build/color/BoxBlur.java similarity index 96% rename from src/main/java/net/vulkanmod/render/chunk/build/biome/BoxBlur.java rename to src/main/java/net/vulkanmod/render/chunk/build/color/BoxBlur.java index 7c484acf8..f86333de7 100644 --- a/src/main/java/net/vulkanmod/render/chunk/build/biome/BoxBlur.java +++ b/src/main/java/net/vulkanmod/render/chunk/build/color/BoxBlur.java @@ -1,6 +1,6 @@ -package net.vulkanmod.render.chunk.build.biome; +package net.vulkanmod.render.chunk.build.color; -public class BoxBlur { +public abstract class BoxBlur { public static void blur(int[] buffer, int[] temp, int width, int filterRadius) { horizontalBlur(buffer, temp, 0, width, filterRadius); diff --git a/src/main/java/net/vulkanmod/render/chunk/build/color/TintCache.java b/src/main/java/net/vulkanmod/render/chunk/build/color/TintCache.java new file mode 100644 index 000000000..e31cc965e --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/color/TintCache.java @@ -0,0 +1,169 @@ +package net.vulkanmod.render.chunk.build.color; + +import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BiomeColors; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.ColorResolver; +import net.minecraft.world.level.biome.Biome; +import net.vulkanmod.render.chunk.build.biome.BiomeData; + +public class TintCache { + private static final int SECTION_WIDTH = 16; + private static final int BOUNDARY_WIDTH = 16; + private static final int LAYER_COUNT = SECTION_WIDTH + (BOUNDARY_WIDTH * 2); + + private final Reference2ReferenceOpenHashMap layers; + + private BiomeData biomeData; + private int blendRadius, totalWidth; + private int secX, secY, secZ; + private int minX, minY, minZ; + private int maxX, maxY, maxZ; + + private int dataSize; + private int[] temp; + + public TintCache() { + this.layers = new Reference2ReferenceOpenHashMap<>(); + + // Default resolvers + this.layers.put(BiomeColors.FOLIAGE_COLOR_RESOLVER, allocateLayers()); + this.layers.put(BiomeColors.GRASS_COLOR_RESOLVER, allocateLayers()); + this.layers.put(BiomeColors.WATER_COLOR_RESOLVER, allocateLayers()); + } + + public void init(BiomeData biomeData, int blendRadius, int secX, int secY, int secZ) { + this.biomeData = biomeData; + this.blendRadius = Minecraft.getInstance().options.biomeBlendRadius().get(); + this.totalWidth = (blendRadius * 2) + 16; + + this.secX = secX; + this.secY = secY; + this.secZ = secZ; + + this.minX = (secX << 4) - blendRadius; + this.minZ = (secZ << 4) - blendRadius; + this.maxX = (secX << 4) + 15 + blendRadius; + this.maxZ = (secZ << 4) + 15 + blendRadius; + + this.minY = (secY << 4) - 2; + this.maxY = this.minY + 15 + 4; + + int size = totalWidth * totalWidth; + + if (size != this.dataSize) { + this.dataSize = size; + + for (Layer[] layers : layers.values()) { + for (Layer layer : layers) { + layer.allocate(size); + } + } + + this.temp = new int[size]; + } + else { + for (Layer[] layers : layers.values()) { + for (Layer layer : layers) { + layer.invalidate(); + } + } + } + } + + public int getColor(BlockPos blockPos, ColorResolver colorResolver) { + int relY = blockPos.getY() - this.minY; + + if (!this.layers.containsKey(colorResolver)) { + addResolver(colorResolver); + } + + Layer layer = this.layers.get(colorResolver)[relY]; + + if (layer.invalidated) { + calculateLayer(layer, colorResolver, relY); + } + + int[] values = layer.getValues(); + + int relX = blockPos.getX() - this.minX; + int relZ = blockPos.getZ() - this.minZ; + + int idx = this.totalWidth * (relZ) + (relX); + return values[idx]; + } + + private void addResolver(ColorResolver colorResolver) { + Layer[] layers1 = allocateLayers(); + + for (Layer layer : layers1) { + layer.allocate(this.dataSize); + } + + this.layers.put(colorResolver, layers1); + } + + private Layer[] allocateLayers() { + Layer[] layers = new Layer[LAYER_COUNT]; + + for (int i = 0; i < LAYER_COUNT; i++) { + layers[i] = new Layer(); + } + + return layers; + } + + private void calculateLayer(Layer layer, ColorResolver colorResolver, int y) { + int absY = minY + y; + + int[] values = layer.values; + + for (int absZ = minZ; absZ <= maxZ; absZ++) { + for (int absX = minX; absX <= maxX; absX++) { + Biome biome = this.biomeData.getBiome(absX, absY, absZ); + + final int idx = (absX - minX) + (absZ - minZ) * totalWidth; + values[idx] = colorResolver.getColor(biome, absX, absZ); + } + } + + if (blendRadius > 0) { + this.applyBlur(values); + } + + layer.invalidated = false; + } + + private void applyBlur(int[] buffer) { + int value = buffer[0]; + boolean needsBlur = false; + for (int i = 1; i < buffer.length; ++i) { + if (value != buffer[i]) { + needsBlur = true; + break; + } + } + + if (needsBlur) + BoxBlur.blur(buffer, temp, SECTION_WIDTH, blendRadius); + } + + static class Layer { + private boolean invalidated = true; + private int[] values; + + void allocate(int size) { + this.values = new int[size]; + invalidate(); + } + + void invalidate() { + this.invalidated = true; + } + + public int[] getValues() { + return this.values; + } + } +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/VulkanModRenderer.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/VulkanModRenderer.java new file mode 100644 index 000000000..eea26fc79 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/VulkanModRenderer.java @@ -0,0 +1,76 @@ +package net.vulkanmod.render.chunk.build.frapi; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.fabricmc.fabric.api.renderer.v1.mesh.MutableMesh; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; +import net.fabricmc.fabric.api.renderer.v1.render.BlockVertexConsumerProvider; +import net.fabricmc.fabric.api.renderer.v1.render.FabricBlockModelRenderer; +import net.fabricmc.fabric.api.renderer.v1.render.RenderLayerHelper; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.block.BlockRenderDispatcher; +import net.minecraft.client.renderer.block.ModelBlockRenderer; +import net.minecraft.client.renderer.block.model.BlockStateModel; +import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.minecraft.core.BlockPos; + +import net.fabricmc.fabric.api.renderer.v1.Renderer; +import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.RenderShape; +import net.minecraft.world.level.block.state.BlockState; +import net.vulkanmod.mixin.render.frapi.BlockRenderDispatcherAccessor; +import net.vulkanmod.render.chunk.build.frapi.accessor.AccessLayerRenderState; +import net.vulkanmod.render.chunk.build.frapi.mesh.MutableMeshImpl; +import net.vulkanmod.render.chunk.build.frapi.render.BlockRenderContext; +import net.vulkanmod.render.chunk.build.frapi.render.SimpleBlockRenderContext; + +/** + * Fabric renderer implementation. + */ +public class VulkanModRenderer implements Renderer { + public static final VulkanModRenderer INSTANCE = new VulkanModRenderer(); + + private VulkanModRenderer() {} + + @Override + public MutableMesh mutableMesh() { + return new MutableMeshImpl(); + } + + @Override + public void render(ModelBlockRenderer modelBlockRenderer, BlockAndTintGetter blockAndTintGetter, + BlockStateModel blockStateModel, BlockState blockState, BlockPos blockPos, PoseStack poseStack, + BlockVertexConsumerProvider blockVertexConsumerProvider, boolean cull, long seed, int overlay) { + BlockRenderContext.POOL.get().render(blockAndTintGetter, blockStateModel, blockState, blockPos, poseStack, blockVertexConsumerProvider, cull, seed, overlay); + } + + @Override + public void render(PoseStack.Pose pose, BlockVertexConsumerProvider blockVertexConsumerProvider, BlockStateModel blockStateModel, + float v, float v1, float v2, int i, int i1, BlockAndTintGetter blockAndTintGetter, + BlockPos blockPos, BlockState blockState) { + SimpleBlockRenderContext.POOL.get().bufferModel(pose, blockVertexConsumerProvider, blockStateModel, v, v1, v2, i, i1, blockAndTintGetter, blockPos, blockState); + } + + @Override + public void renderBlockAsEntity(BlockRenderDispatcher blockRenderDispatcher, BlockState blockState, + PoseStack poseStack, MultiBufferSource multiBufferSource, int light, int overlay, + BlockAndTintGetter blockAndTintGetter, BlockPos pos) { + RenderShape blockRenderType = blockState.getRenderShape(); + + if (blockRenderType != RenderShape.INVISIBLE) { + BlockStateModel model = blockRenderDispatcher.getBlockModel(blockState); + int tint = ((BlockRenderDispatcherAccessor) blockRenderDispatcher).getBlockColors().getColor(blockState, null, null, 0); + float red = (tint >> 16 & 255) / 255.0F; + float green = (tint >> 8 & 255) / 255.0F; + float blue = (tint & 255) / 255.0F; + FabricBlockModelRenderer.render(poseStack.last(), layer -> multiBufferSource.getBuffer(RenderLayerHelper.getEntityBlockLayer(layer)), model, red, green, blue, light, overlay, blockAndTintGetter, pos, blockState); + ((BlockRenderDispatcherAccessor) blockRenderDispatcher).getBlockEntityModelsGetter().get().renderByBlock(blockState.getBlock(), ItemDisplayContext.NONE, poseStack, Minecraft.getInstance().gameRenderer.getSubmitNodeStorage(), light, overlay, 0); + } + } + + @Override + public QuadEmitter getLayerRenderStateEmitter(ItemStackRenderState.LayerRenderState layer) { + return ((AccessLayerRenderState) layer).getMutableMesh().emitter(); + } +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/accessor/AccessBatchingRenderCommandQueue.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/accessor/AccessBatchingRenderCommandQueue.java new file mode 100644 index 000000000..aa1b3f992 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/accessor/AccessBatchingRenderCommandQueue.java @@ -0,0 +1,10 @@ +package net.vulkanmod.render.chunk.build.frapi.accessor; + + +import net.vulkanmod.render.chunk.build.frapi.render.MeshItemCommand; + +import java.util.List; + +public interface AccessBatchingRenderCommandQueue { + List getMeshItemCommands(); +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/accessor/AccessChunkRendererRegion.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/accessor/AccessChunkRendererRegion.java new file mode 100644 index 000000000..a24048ae3 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/accessor/AccessChunkRendererRegion.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.vulkanmod.render.chunk.build.frapi.accessor; + +import net.fabricmc.fabric.impl.client.indigo.renderer.render.TerrainRenderContext; + +/** + * Used to stash block renderer reference in local scope during + * chunk rebuild, thus avoiding repeated thread-local lookups. + */ +public interface AccessChunkRendererRegion { + TerrainRenderContext fabric_getRenderer(); + + void fabric_setRenderer(TerrainRenderContext renderer); +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/accessor/AccessLayerRenderState.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/accessor/AccessLayerRenderState.java new file mode 100644 index 000000000..f2d56f756 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/accessor/AccessLayerRenderState.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.vulkanmod.render.chunk.build.frapi.accessor; + + +import net.vulkanmod.render.chunk.build.frapi.mesh.MutableMeshImpl; + +public interface AccessLayerRenderState { + MutableMeshImpl getMutableMesh(); +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/accessor/AccessRenderCommandQueue.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/accessor/AccessRenderCommandQueue.java new file mode 100644 index 000000000..5d958f088 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/accessor/AccessRenderCommandQueue.java @@ -0,0 +1,15 @@ +package net.vulkanmod.render.chunk.build.frapi.accessor; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.fabricmc.fabric.api.renderer.v1.mesh.MeshView; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.minecraft.world.item.ItemDisplayContext; + + +import java.util.List; + +public interface AccessRenderCommandQueue { + void submitItem(PoseStack matrices, ItemDisplayContext displayContext, int light, int overlay, int outlineColors, int[] tintLayers, List quads, RenderType renderLayer, ItemStackRenderState.FoilType glintType, MeshView mesh); +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/helper/ColorHelper.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/helper/ColorHelper.java new file mode 100644 index 000000000..80003422e --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/helper/ColorHelper.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.vulkanmod.render.chunk.build.frapi.helper; + +import java.nio.ByteOrder; + +/** + * Static routines of general utility for renderer implementations. + * Renderers are not required to use these helpers, but they were + * designed to be usable without the default renderer. + */ +public abstract class ColorHelper { + private ColorHelper() { } + + private static final boolean BIG_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; + + /** + * Component-wise max. + */ + public static int maxLight(int l0, int l1) { + if (l0 == 0) return l1; + if (l1 == 0) return l0; + + return Math.max(l0 & 0xFFFF, l1 & 0xFFFF) | Math.max(l0 & 0xFFFF0000, l1 & 0xFFFF0000); + } + + /** Component-wise multiply. Components need to be in same order in both inputs! */ + public static int multiplyColor(int color1, int color2) { + if (color1 == -1) { + return color2; + } else if (color2 == -1) { + return color1; + } + + final int alpha = ((color1 >>> 24) & 0xFF) * ((color2 >>> 24) & 0xFF) / 0xFF; + final int red = ((color1 >>> 16) & 0xFF) * ((color2 >>> 16) & 0xFF) / 0xFF; + final int green = ((color1 >>> 8) & 0xFF) * ((color2 >>> 8) & 0xFF) / 0xFF; + final int blue = (color1 & 0xFF) * (color2 & 0xFF) / 0xFF; + + return (alpha << 24) | (red << 16) | (green << 8) | blue; + } + + /** Multiplies three lowest components by shade. High byte (usually alpha) unchanged. */ + public static int multiplyRGB(int color, float shade) { + final int alpha = ((color >>> 24) & 0xFF); + final int red = (int) (((color >>> 16) & 0xFF) * shade); + final int green = (int) (((color >>> 8) & 0xFF) * shade); + final int blue = (int) ((color & 0xFF) * shade); + + return (alpha << 24) | (red << 16) | (green << 8) | blue; + } + + /** + * Component-wise max. + */ + public static int maxBrightness(int b0, int b1) { + if (b0 == 0) return b1; + if (b1 == 0) return b0; + + return Math.max(b0 & 0xFFFF, b1 & 0xFFFF) | Math.max(b0 & 0xFFFF0000, b1 & 0xFFFF0000); + } + + /* + Renderer color format: ARGB (0xAARRGGBB) + Vanilla color format (little endian): ABGR (0xAABBGGRR) + Vanilla color format (big endian): RGBA (0xRRGGBBAA) + + Why does the vanilla color format change based on endianness? + See VertexConsumer#quad. Quad data is loaded as integers into + a native byte order buffer. Color is read directly from bytes + 12, 13, 14 of each vertex. A different byte order will yield + different results. + + The renderer always uses ARGB because the API color methods + always consume and return ARGB. Vanilla block and item colors + also use ARGB. + */ + + /** + * Converts from ARGB color to ABGR color if little endian or RGBA color if big endian. + */ + public static int toVanillaColor(int color) { + if (color == -1) { + return -1; + } + + if (BIG_ENDIAN) { + // ARGB to RGBA + return ((color & 0x00FFFFFF) << 8) | ((color & 0xFF000000) >>> 24); + } else { + // ARGB to ABGR + return (color & 0xFF00FF00) | ((color & 0x00FF0000) >>> 16) | ((color & 0x000000FF) << 16); + } + } + + /** + * Converts to ARGB color from ABGR color if little endian or RGBA color if big endian. + */ + public static int fromVanillaColor(int color) { + if (color == -1) { + return -1; + } + + if (BIG_ENDIAN) { + // RGBA to ARGB + return ((color & 0xFFFFFF00) >>> 8) | ((color & 0x000000FF) << 24); + } else { + // ABGR to ARGB + return (color & 0xFF00FF00) | ((color & 0x00FF0000) >>> 16) | ((color & 0x000000FF) << 16); + } + } +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/helper/GeometryHelper.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/helper/GeometryHelper.java new file mode 100644 index 000000000..fc68442cd --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/helper/GeometryHelper.java @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.vulkanmod.render.chunk.build.frapi.helper; + +import static net.minecraft.util.Mth.equal; + +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import org.joml.Vector3fc; + +/** + * Static routines of general utility for renderer implementations. + * Renderers are not required to use these helpers, but they were + * designed to be usable without the default renderer. + */ +public abstract class GeometryHelper { + private GeometryHelper() { } + + /** set when a quad touches all four corners of a unit cube. */ + public static final int CUBIC_FLAG = 1; + + /** set when a quad is parallel to (but not necessarily on) a its light face. */ + public static final int AXIS_ALIGNED_FLAG = CUBIC_FLAG << 1; + + /** set when a quad is coplanar with its light face. Implies {@link #AXIS_ALIGNED_FLAG} */ + public static final int LIGHT_FACE_FLAG = AXIS_ALIGNED_FLAG << 1; + + /** how many bits quad header encoding should reserve for encoding geometry flags. */ + public static final int FLAG_BIT_COUNT = 3; + + private static final float EPS_MIN = 0.0001f; + private static final float EPS_MAX = 1.0f - EPS_MIN; + + /** + * Analyzes the quad and returns a value with some combination + * of {@link #AXIS_ALIGNED_FLAG}, {@link #LIGHT_FACE_FLAG} and {@link #CUBIC_FLAG}. + * Intended use is to optimize lighting when the geometry is regular. + * Expects convex quads with all points co-planar. + */ + public static int computeShapeFlags(QuadView quad) { + Direction lightFace = quad.lightFace(); + int bits = 0; + + if (isQuadParallelToFace(lightFace, quad)) { + bits |= AXIS_ALIGNED_FLAG; + + if (isParallelQuadOnFace(lightFace, quad)) { + bits |= LIGHT_FACE_FLAG; + } + } + + if (isQuadCubic(lightFace, quad)) { + bits |= CUBIC_FLAG; + } + + return bits; + } + + /** + * Returns true if quad is parallel to the given face. + * Does not validate quad winding order. + * Expects convex quads with all points co-planar. + */ + public static boolean isQuadParallelToFace(Direction face, QuadView quad) { + int i = face.getAxis().ordinal(); + final float val = quad.posByIndex(0, i); + return equal(val, quad.posByIndex(1, i)) && equal(val, quad.posByIndex(2, i)) && equal(val, quad.posByIndex(3, i)); + } + + /** + * True if quad - already known to be parallel to a face - is actually coplanar with it. + * For compatibility with vanilla resource packs, also true if quad is outside the face. + * + *

Test will be unreliable if not already parallel, use {@link #isQuadParallelToFace(Direction, QuadView)} + * for that purpose. Expects convex quads with all points co-planar. + */ + public static boolean isParallelQuadOnFace(Direction lightFace, QuadView quad) { + final float x = quad.posByIndex(0, lightFace.getAxis().ordinal()); + return lightFace.getAxisDirection() == AxisDirection.POSITIVE ? x >= EPS_MAX : x <= EPS_MIN; + } + + /** + * Returns true if quad is truly a quad (not a triangle) and fills a full block cross-section. + * If known to be true, allows use of a simpler/faster AO lighting algorithm. + * + *

Does not check if quad is actually coplanar with the light face, nor does it check that all + * quad vertices are coplanar with each other. + * + *

Expects convex quads with all points co-planar. + */ + public static boolean isQuadCubic(Direction lightFace, QuadView quad) { + int a, b; + + switch (lightFace) { + case EAST: + case WEST: + a = 1; + b = 2; + break; + case UP: + case DOWN: + a = 0; + b = 2; + break; + case SOUTH: + case NORTH: + a = 1; + b = 0; + break; + default: + // handle WTF case + return false; + } + + return confirmSquareCorners(a, b, quad); + } + + /** + * Used by {@link #isQuadCubic(Direction, QuadView)}. + * True if quad touches all four corners of unit square. + * + *

For compatibility with resource packs that contain models with quads exceeding + * block boundaries, considers corners outside the block to be at the corners. + */ + private static boolean confirmSquareCorners(int aCoordinate, int bCoordinate, QuadView quad) { + int flags = 0; + + for (int i = 0; i < 4; i++) { + final float a = quad.posByIndex(i, aCoordinate); + final float b = quad.posByIndex(i, bCoordinate); + + if (a <= EPS_MIN) { + if (b <= EPS_MIN) { + flags |= 1; + } else if (b >= EPS_MAX) { + flags |= 2; + } else { + return false; + } + } else if (a >= EPS_MAX) { + if (b <= EPS_MIN) { + flags |= 4; + } else if (b >= EPS_MAX) { + flags |= 8; + } else { + return false; + } + } else { + return false; + } + } + + return flags == 15; + } + + /** + * Identifies the face to which the quad is most closely aligned. + * This mimics the value that {@link BakedQuad#getDirection()} returns, and is + * used in the vanilla renderer for all diffuse lighting. + * + *

Derived from the quad face normal and expects convex quads with all points co-planar. + */ + public static Direction lightFace(QuadView quad) { + final Vector3fc normal = quad.faceNormal(); + switch (GeometryHelper.longestAxis(normal)) { + case X: + return normal.x() > 0 ? Direction.EAST : Direction.WEST; + + case Y: + return normal.y() > 0 ? Direction.UP : Direction.DOWN; + + case Z: + return normal.z() > 0 ? Direction.SOUTH : Direction.NORTH; + + default: + // handle WTF case + return Direction.UP; + } + } + + /** + * Simple 4-way compare, doesn't handle NaN values. + */ + public static float min(float a, float b, float c, float d) { + final float x = a < b ? a : b; + final float y = c < d ? c : d; + return x < y ? x : y; + } + + /** + * Simple 4-way compare, doesn't handle NaN values. + */ + public static float max(float a, float b, float c, float d) { + final float x = a > b ? a : b; + final float y = c > d ? c : d; + return x > y ? x : y; + } + + /** + * @see #longestAxis(float, float, float) + */ + public static Axis longestAxis(Vector3fc vec) { + return longestAxis(vec.x(), vec.y(), vec.z()); + } + + /** + * Identifies the largest (max absolute magnitude) component (X, Y, Z) in the given vector. + */ + public static Axis longestAxis(float normalX, float normalY, float normalZ) { + Axis result = Axis.Y; + float longest = Math.abs(normalY); + float a = Math.abs(normalX); + + if (a > longest) { + result = Axis.X; + longest = a; + } + + return Math.abs(normalZ) > longest + ? Axis.Z : result; + } +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/helper/NormalHelper.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/helper/NormalHelper.java new file mode 100644 index 000000000..8b8ebb1b0 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/helper/NormalHelper.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.vulkanmod.render.chunk.build.frapi.helper; + +import net.vulkanmod.render.model.quad.ModelQuadView; +import net.vulkanmod.render.vertex.format.I32_SNorm; +import org.jetbrains.annotations.NotNull; +import org.joml.Vector3f; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; +import net.minecraft.core.Direction; +import net.minecraft.core.Vec3i; +import net.minecraft.util.Mth; + +/** + * Static routines of general utility for renderer implementations. + * Renderers are not required to use these helpers, but they were + * designed to be usable without the default renderer. + */ +public abstract class NormalHelper { + private NormalHelper() { } + + private static final float PACK = 127.0f; + private static final float UNPACK = 1.0f / PACK; + + /** + * Stores a normal plus an extra value as a quartet of signed bytes. + * This is the same normal format that vanilla rendering expects. + * The extra value is for use by shaders. + */ + public static int packNormal(float x, float y, float z, float w) { + x = Mth.clamp(x, -1, 1); + y = Mth.clamp(y, -1, 1); + z = Mth.clamp(z, -1, 1); + w = Mth.clamp(w, -1, 1); + + return ((int) (x * PACK) & 0xFF) | (((int) (y * PACK) & 0xFF) << 8) | (((int) (z * PACK) & 0xFF) << 16) | (((int) (w * PACK) & 0xFF) << 24); + } + + /** + * Version of {@link #packNormal(float, float, float, float)} that accepts a vector type. + */ + public static int packNormal(Vector3f normal, float w) { + return packNormal(normal.x(), normal.y(), normal.z(), w); + } + + /** + * Like {@link #packNormal(float, float, float, float)}, but without a {@code w} value. + */ + public static int packNormal(float x, float y, float z) { + x = Mth.clamp(x, -1, 1); + y = Mth.clamp(y, -1, 1); + z = Mth.clamp(z, -1, 1); + + return ((int) (x * PACK) & 0xFF) | (((int) (y * PACK) & 0xFF) << 8) | (((int) (z * PACK) & 0xFF) << 16); + } + + /** + * Like {@link #packNormal(Vector3f, float)}, but without a {@code w} value. + */ + public static int packNormal(Vector3f normal) { + return packNormal(normal.x(), normal.y(), normal.z()); + } + + public static float unpackNormalX(int packedNormal) { + return ((byte) (packedNormal & 0xFF)) * UNPACK; + } + + public static float unpackNormalY(int packedNormal) { + return ((byte) ((packedNormal >>> 8) & 0xFF)) * UNPACK; + } + + public static float unpackNormalZ(int packedNormal) { + return ((byte) ((packedNormal >>> 16) & 0xFF)) * UNPACK; + } + + public static float unpackNormalW(int packedNormal) { + return ((byte) ((packedNormal >>> 24) & 0xFF)) * UNPACK; + } + + public static void unpackNormal(int packedNormal, Vector3f target) { + target.set(unpackNormalX(packedNormal), unpackNormalY(packedNormal), unpackNormalZ(packedNormal)); + } + + /** + * Computes the face normal of the given quad and saves it in the provided non-null vector. + * If {@link QuadView#nominalFace()} is set will optimize by confirming quad is parallel to that + * face and, if so, use the standard normal for that face direction. + * + *

Will work with triangles also. Assumes counter-clockwise winding order, which is the norm. + * Expects convex quads with all points co-planar. + */ + public static void computeFaceNormal(@NotNull Vector3f saveTo, QuadView q) { + final Direction nominalFace = q.nominalFace(); + + if (nominalFace != null && GeometryHelper.isQuadParallelToFace(nominalFace, q)) { + Vec3i vec = nominalFace.getUnitVec3i(); + saveTo.set(vec.getX(), vec.getY(), vec.getZ()); + return; + } + + final float x0 = q.x(0); + final float y0 = q.y(0); + final float z0 = q.z(0); + final float x1 = q.x(1); + final float y1 = q.y(1); + final float z1 = q.z(1); + final float x2 = q.x(2); + final float y2 = q.y(2); + final float z2 = q.z(2); + final float x3 = q.x(3); + final float y3 = q.y(3); + final float z3 = q.z(3); + + final float dx0 = x2 - x0; + final float dy0 = y2 - y0; + final float dz0 = z2 - z0; + final float dx1 = x3 - x1; + final float dy1 = y3 - y1; + final float dz1 = z3 - z1; + + float normX = dy0 * dz1 - dz0 * dy1; + float normY = dz0 * dx1 - dx0 * dz1; + float normZ = dx0 * dy1 - dy0 * dx1; + + float l = (float) Math.sqrt(normX * normX + normY * normY + normZ * normZ); + + if (l != 0) { + normX /= l; + normY /= l; + normZ /= l; + } + + saveTo.set(normX, normY, normZ); + } + + public static int computePackedNormal(ModelQuadView q) { + final float x0 = q.getX(0); + final float y0 = q.getY(0); + final float z0 = q.getZ(0); + final float x1 = q.getX(1); + final float y1 = q.getY(1); + final float z1 = q.getZ(1); + final float x2 = q.getX(2); + final float y2 = q.getY(2); + final float z2 = q.getZ(2); + final float x3 = q.getX(3); + final float y3 = q.getY(3); + final float z3 = q.getZ(3); + + final float dx0 = x2 - x0; + final float dy0 = y2 - y0; + final float dz0 = z2 - z0; + final float dx1 = x3 - x1; + final float dy1 = y3 - y1; + final float dz1 = z3 - z1; + + float normX = dy0 * dz1 - dz0 * dy1; + float normY = dz0 * dx1 - dx0 * dz1; + float normZ = dx0 * dy1 - dy0 * dx1; + + float l = (float) Math.sqrt(normX * normX + normY * normY + normZ * normZ); + + if (l != 0) { + normX /= l; + normY /= l; + normZ /= l; + } + + return I32_SNorm.packNormal(normX, normY, normZ); + } + + public static int packedNormalFromDirection(Direction direction) { + Vec3i normal = direction.getUnitVec3i(); + + return I32_SNorm.packNormal(normal.getX(), normal.getY(), normal.getZ()); + } + + public static void unpackNormalTo(int packedNormal, Vector3f normal) { + normal.set(I32_SNorm.unpackX(packedNormal), I32_SNorm.unpackY(packedNormal), I32_SNorm.unpackZ(packedNormal)); + } +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/helper/TextureHelper.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/helper/TextureHelper.java new file mode 100644 index 000000000..bc622cd92 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/helper/TextureHelper.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.vulkanmod.render.chunk.build.frapi.helper; + +import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.Direction; + +/** + * Handles most texture-baking use cases for model loaders and model libraries + * via {@link #bakeSprite(MutableQuadView, TextureAtlasSprite, int)}. Also used by the API + * itself to implement automatic block-breaking models for enhanced models. + */ +public class TextureHelper { + private TextureHelper() { } + + private static final float NORMALIZER = 1f / 16f; + + /** + * Bakes textures in the provided vertex data, handling UV locking, + * rotation, interpolation, etc. Textures must not be already baked. + */ + public static void bakeSprite(MutableQuadView quad, TextureAtlasSprite sprite, int bakeFlags) { + if (quad.nominalFace() != null && (MutableQuadView.BAKE_LOCK_UV & bakeFlags) != 0) { + // Assigns normalized UV coordinates based on vertex positions + applyModifier(quad, UVLOCKERS[quad.nominalFace().get3DDataValue()]); + } else if ((MutableQuadView.BAKE_NORMALIZED & bakeFlags) == 0) { // flag is NOT set, UVs are assumed to not be normalized yet as is the default, normalize through dividing by 16 + // Scales from 0-16 to 0-1 + applyModifier(quad, (q, i) -> q.uv(i, q.u(i) * NORMALIZER, q.v(i) * NORMALIZER)); + } + + final int rotation = bakeFlags & 3; + + if (rotation != 0) { + // Rotates texture around the center of sprite. + // Assumes normalized coordinates. + applyModifier(quad, ROTATIONS[rotation]); + } + + if ((MutableQuadView.BAKE_FLIP_U & bakeFlags) != 0) { + // Inverts U coordinates. Assumes normalized (0-1) values. + applyModifier(quad, (q, i) -> q.uv(i, 1 - q.u(i), q.v(i))); + } + + if ((MutableQuadView.BAKE_FLIP_V & bakeFlags) != 0) { + // Inverts V coordinates. Assumes normalized (0-1) values. + applyModifier(quad, (q, i) -> q.uv(i, q.u(i), 1 - q.v(i))); + } + + interpolate(quad, sprite); + } + + /** + * Faster than sprite method. Sprite computes span and normalizes inputs each call, + * so we'd have to denormalize before we called, only to have the sprite renormalize immediately. + */ + private static void interpolate(MutableQuadView q, TextureAtlasSprite sprite) { + final float uMin = sprite.getU0(); + final float uSpan = sprite.getU1() - uMin; + final float vMin = sprite.getV0(); + final float vSpan = sprite.getV1() - vMin; + + for (int i = 0; i < 4; i++) { + q.uv(i, uMin + q.u(i) * uSpan, vMin + q.v(i) * vSpan); + } + } + + @FunctionalInterface + private interface VertexModifier { + void apply(MutableQuadView quad, int vertexIndex); + } + + private static void applyModifier(MutableQuadView quad, VertexModifier modifier) { + for (int i = 0; i < 4; i++) { + modifier.apply(quad, i); + } + } + + private static final VertexModifier[] ROTATIONS = new VertexModifier[] { + null, + (q, i) -> q.uv(i, q.v(i), 1 - q.u(i)), //90 + (q, i) -> q.uv(i, 1 - q.u(i), 1 - q.v(i)), //180 + (q, i) -> q.uv(i, 1 - q.v(i), q.u(i)) // 270 + }; + + private static final VertexModifier[] UVLOCKERS = new VertexModifier[6]; + + static { + UVLOCKERS[Direction.EAST.get3DDataValue()] = (q, i) -> q.uv(i, 1 - q.z(i), 1 - q.y(i)); + UVLOCKERS[Direction.WEST.get3DDataValue()] = (q, i) -> q.uv(i, q.z(i), 1 - q.y(i)); + UVLOCKERS[Direction.NORTH.get3DDataValue()] = (q, i) -> q.uv(i, 1 - q.x(i), 1 - q.y(i)); + UVLOCKERS[Direction.SOUTH.get3DDataValue()] = (q, i) -> q.uv(i, q.x(i), 1 - q.y(i)); + UVLOCKERS[Direction.DOWN.get3DDataValue()] = (q, i) -> q.uv(i, q.x(i), 1 - q.z(i)); + UVLOCKERS[Direction.UP.get3DDataValue()] = (q, i) -> q.uv(i, q.x(i), q.z(i)); + } +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/mesh/EncodingFormat.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/mesh/EncodingFormat.java new file mode 100644 index 000000000..a0de50146 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/mesh/EncodingFormat.java @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.vulkanmod.render.chunk.build.frapi.mesh; + +import com.google.common.base.Preconditions; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.VertexFormat; +import net.fabricmc.fabric.api.renderer.v1.mesh.ShadeMode; +import net.fabricmc.fabric.api.util.TriState; +import net.minecraft.client.renderer.chunk.ChunkSectionLayer; +import net.minecraft.client.renderer.item.ItemStackRenderState; +import org.apache.commons.lang3.ArrayUtils; +import org.jetbrains.annotations.Nullable; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; +import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper; +import net.vulkanmod.render.chunk.build.frapi.helper.GeometryHelper; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; + +/** + * Holds all the array offsets and bit-wise encoders/decoders for + * packing/unpacking quad data in an array of integers. + * All of this is implementation-specific - that's why it isn't a "helper" class. + */ +public final class EncodingFormat { + private EncodingFormat() { } + + static final int HEADER_BITS = 0; + static final int HEADER_FACE_NORMAL = 1; + static final int HEADER_TINT_INDEX = 2; + static final int HEADER_TAG = 3; + public static final int HEADER_STRIDE = 4; + + static final int VERTEX_X; + static final int VERTEX_Y; + static final int VERTEX_Z; + static final int VERTEX_COLOR; + static final int VERTEX_U; + static final int VERTEX_V; + static final int VERTEX_LIGHTMAP; + static final int VERTEX_NORMAL; + public static final int VERTEX_STRIDE; + + public static final int QUAD_STRIDE; + public static final int QUAD_STRIDE_BYTES; + public static final int TOTAL_STRIDE; + + static { + final VertexFormat format = DefaultVertexFormat.BLOCK; + VERTEX_X = HEADER_STRIDE + 0; + VERTEX_Y = HEADER_STRIDE + 1; + VERTEX_Z = HEADER_STRIDE + 2; + VERTEX_COLOR = HEADER_STRIDE + 3; + VERTEX_U = HEADER_STRIDE + 4; + VERTEX_V = VERTEX_U + 1; + VERTEX_LIGHTMAP = HEADER_STRIDE + 6; + VERTEX_NORMAL = HEADER_STRIDE + 7; + VERTEX_STRIDE = format.getVertexSize() / 4; + QUAD_STRIDE = VERTEX_STRIDE * 4; + QUAD_STRIDE_BYTES = QUAD_STRIDE * 4; + TOTAL_STRIDE = HEADER_STRIDE + QUAD_STRIDE; + + Preconditions.checkState(VERTEX_STRIDE == QuadView.VANILLA_VERTEX_STRIDE, "Indigo vertex stride (%s) mismatched with rendering API (%s)", VERTEX_STRIDE, QuadView.VANILLA_VERTEX_STRIDE); + Preconditions.checkState(QUAD_STRIDE == QuadView.VANILLA_QUAD_STRIDE, "Indigo quad stride (%s) mismatched with rendering API (%s)", QUAD_STRIDE, QuadView.VANILLA_QUAD_STRIDE); + } + + private static final int DIRECTION_COUNT = Direction.values().length; + private static final int NULLABLE_DIRECTION_COUNT = DIRECTION_COUNT + 1; + + private static final @Nullable ChunkSectionLayer[] NULLABLE_BLOCK_RENDER_LAYERS = ArrayUtils.add(ChunkSectionLayer.values(), null); + private static final int NULLABLE_BLOCK_RENDER_LAYER_COUNT = NULLABLE_BLOCK_RENDER_LAYERS.length; + private static final TriState[] TRI_STATES = TriState.values(); + private static final int TRI_STATE_COUNT = TRI_STATES.length; + private static final @Nullable ItemStackRenderState.FoilType[] NULLABLE_GLINTS = ArrayUtils.add(ItemStackRenderState.FoilType.values(), null); + private static final int NULLABLE_GLINT_COUNT = NULLABLE_GLINTS.length; + private static final ShadeMode[] SHADE_MODES = ShadeMode.values(); + private static final int SHADE_MODE_COUNT = SHADE_MODES.length; + + private static final int NULL_RENDER_LAYER_INDEX = NULLABLE_BLOCK_RENDER_LAYER_COUNT - 1; + private static final int NULL_GLINT_INDEX = NULLABLE_GLINT_COUNT - 1; + + private static final int CULL_BIT_LENGTH = Mth.ceillog2(NULLABLE_DIRECTION_COUNT); + private static final int LIGHT_BIT_LENGTH = Mth.ceillog2(DIRECTION_COUNT); + private static final int NORMALS_BIT_LENGTH = 4; + private static final int GEOMETRY_BIT_LENGTH = GeometryHelper.FLAG_BIT_COUNT; + private static final int RENDER_LAYER_BIT_LENGTH = Mth.ceillog2(NULLABLE_BLOCK_RENDER_LAYER_COUNT); + private static final int EMISSIVE_BIT_LENGTH = 1; + private static final int DIFFUSE_BIT_LENGTH = 1; + private static final int AO_BIT_LENGTH = Mth.ceillog2(TRI_STATE_COUNT); + private static final int GLINT_BIT_LENGTH = Mth.ceillog2(NULLABLE_GLINT_COUNT); + private static final int SHADE_MODE_BIT_LENGTH = Mth.ceillog2(SHADE_MODE_COUNT); + + private static final int CULL_BIT_OFFSET = 0; + private static final int LIGHT_BIT_OFFSET = CULL_BIT_OFFSET + CULL_BIT_LENGTH; + private static final int NORMALS_BIT_OFFSET = LIGHT_BIT_OFFSET + LIGHT_BIT_LENGTH; + private static final int GEOMETRY_BIT_OFFSET = NORMALS_BIT_OFFSET + NORMALS_BIT_LENGTH; + private static final int RENDER_LAYER_BIT_OFFSET = GEOMETRY_BIT_OFFSET + GEOMETRY_BIT_LENGTH; + private static final int EMISSIVE_BIT_OFFSET = RENDER_LAYER_BIT_OFFSET + RENDER_LAYER_BIT_LENGTH; + private static final int DIFFUSE_BIT_OFFSET = EMISSIVE_BIT_OFFSET + EMISSIVE_BIT_LENGTH; + private static final int AO_BIT_OFFSET = DIFFUSE_BIT_OFFSET + DIFFUSE_BIT_LENGTH; + private static final int GLINT_BIT_OFFSET = AO_BIT_OFFSET + AO_BIT_LENGTH; + private static final int SHADE_MODE_BIT_OFFSET = GLINT_BIT_OFFSET + GLINT_BIT_LENGTH; + private static final int TOTAL_BIT_LENGTH = SHADE_MODE_BIT_OFFSET + SHADE_MODE_BIT_LENGTH; + + private static final int CULL_MASK = bitMask(CULL_BIT_LENGTH, CULL_BIT_OFFSET); + private static final int LIGHT_MASK = bitMask(LIGHT_BIT_LENGTH, LIGHT_BIT_OFFSET); + private static final int NORMALS_MASK = bitMask(NORMALS_BIT_LENGTH, NORMALS_BIT_OFFSET); + private static final int GEOMETRY_MASK = bitMask(GEOMETRY_BIT_LENGTH, GEOMETRY_BIT_OFFSET); + private static final int RENDER_LAYER_MASK = bitMask(RENDER_LAYER_BIT_LENGTH, RENDER_LAYER_BIT_OFFSET); + private static final int EMISSIVE_MASK = bitMask(EMISSIVE_BIT_LENGTH, EMISSIVE_BIT_OFFSET); + private static final int DIFFUSE_MASK = bitMask(DIFFUSE_BIT_LENGTH, DIFFUSE_BIT_OFFSET); + private static final int AO_MASK = bitMask(AO_BIT_LENGTH, AO_BIT_OFFSET); + private static final int GLINT_MASK = bitMask(GLINT_BIT_LENGTH, GLINT_BIT_OFFSET); + private static final int SHADE_MODE_MASK = bitMask(SHADE_MODE_BIT_LENGTH, SHADE_MODE_BIT_OFFSET); + + static { + Preconditions.checkArgument(TOTAL_BIT_LENGTH <= 32, "Indigo header encoding bit count (%s) exceeds integer bit length)", TOTAL_STRIDE); + } + + private static int bitMask(int bitLength, int bitOffset) { + return ((1 << bitLength) - 1) << bitOffset; + } + + @Nullable + static Direction cullFace(int bits) { + return ModelHelper.faceFromIndex((bits & CULL_MASK) >>> CULL_BIT_OFFSET); + } + + static int cullFace(int bits, @Nullable Direction face) { + return (bits & ~CULL_MASK) | (ModelHelper.toFaceIndex(face) << CULL_BIT_OFFSET); + } + + static Direction lightFace(int bits) { + return ModelHelper.faceFromIndex((bits & LIGHT_MASK) >>> LIGHT_BIT_OFFSET); + } + + static int lightFace(int bits, Direction face) { + return (bits & ~LIGHT_MASK) | (ModelHelper.toFaceIndex(face) << LIGHT_BIT_OFFSET); + } + + /** indicate if vertex normal has been set - bits correspond to vertex ordinals. */ + static int normalFlags(int bits) { + return (bits & NORMALS_MASK) >>> NORMALS_BIT_OFFSET; + } + + static int normalFlags(int bits, int normalFlags) { + return (bits & ~NORMALS_MASK) | ((normalFlags << NORMALS_BIT_OFFSET) & NORMALS_MASK); + } + + static int geometryFlags(int bits) { + return (bits & GEOMETRY_MASK) >>> GEOMETRY_BIT_OFFSET; + } + + static int geometryFlags(int bits, int geometryFlags) { + return (bits & ~GEOMETRY_MASK) | ((geometryFlags << GEOMETRY_BIT_OFFSET) & GEOMETRY_MASK); + } + + @Nullable + static ChunkSectionLayer renderLayer(int bits) { + return NULLABLE_BLOCK_RENDER_LAYERS[(bits & RENDER_LAYER_MASK) >>> RENDER_LAYER_BIT_OFFSET]; + } + + static int renderLayer(int bits, @Nullable ChunkSectionLayer renderLayer) { + int index = renderLayer == null ? NULL_RENDER_LAYER_INDEX : renderLayer.ordinal(); + return (bits & ~RENDER_LAYER_MASK) | (index << RENDER_LAYER_BIT_OFFSET); + } + + static boolean emissive(int bits) { + return (bits & EMISSIVE_MASK) != 0; + } + + static int emissive(int bits, boolean emissive) { + return emissive ? (bits | EMISSIVE_MASK) : (bits & ~EMISSIVE_MASK); + } + + static boolean diffuseShade(int bits) { + return (bits & DIFFUSE_MASK) != 0; + } + + static int diffuseShade(int bits, boolean shade) { + return shade ? (bits | DIFFUSE_MASK) : (bits & ~DIFFUSE_MASK); + } + + static TriState ambientOcclusion(int bits) { + return TRI_STATES[(bits & AO_MASK) >>> AO_BIT_OFFSET]; + } + + static int ambientOcclusion(int bits, TriState ao) { + return (bits & ~AO_MASK) | (ao.ordinal() << AO_BIT_OFFSET); + } + + @Nullable + static ItemStackRenderState.FoilType glint(int bits) { + return NULLABLE_GLINTS[(bits & GLINT_MASK) >>> GLINT_BIT_OFFSET]; + } + + static int glint(int bits, @Nullable ItemStackRenderState.FoilType glint) { + int index = glint == null ? NULL_GLINT_INDEX : glint.ordinal(); + return (bits & ~GLINT_MASK) | (index << GLINT_BIT_OFFSET); + } + + static ShadeMode shadeMode(int bits) { + return SHADE_MODES[(bits & SHADE_MODE_MASK) >>> SHADE_MODE_BIT_OFFSET]; + } + + static int shadeMode(int bits, ShadeMode mode) { + return (bits & ~SHADE_MODE_MASK) | (mode.ordinal() << SHADE_MODE_BIT_OFFSET); + } +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/mesh/MeshImpl.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/mesh/MeshImpl.java new file mode 100644 index 000000000..834f867b8 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/mesh/MeshImpl.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.vulkanmod.render.chunk.build.frapi.mesh; + +import java.util.function.Consumer; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.jetbrains.annotations.Range; + +import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; + +public class MeshImpl implements Mesh { + /** Used to satisfy external calls to {@link #forEach(Consumer)}. */ + private static final ThreadLocal> CURSOR_POOLS = ThreadLocal.withInitial(ObjectArrayList::new); + + int[] data; + int limit; + + MeshImpl(int[] data) { + this.data = data; + limit = data.length; + } + + MeshImpl() { + } + + @Override + @Range(from = 0, to = Integer.MAX_VALUE) + public int size() { + return limit / EncodingFormat.TOTAL_STRIDE; + } + + @Override + public void forEach(Consumer action) { + ObjectArrayList pool = CURSOR_POOLS.get(); + QuadViewImpl cursor; + + if (pool.isEmpty()) { + cursor = new QuadViewImpl(); + } else { + cursor = pool.pop(); + } + + forEach(action, cursor); + + pool.push(cursor); + } + + /** + * The renderer can call this with its own cursor to avoid the performance hit of a + * thread-local lookup or to use a mutable cursor. + */ + void forEach(Consumer action, C cursor) { + final int limit = this.limit; + int index = 0; + cursor.data = data; + + while (index < limit) { + cursor.baseIndex = index; + cursor.load(); + action.accept(cursor); + index += EncodingFormat.TOTAL_STRIDE; + } + + cursor.data = null; + } + + // TODO: This could be optimized by checking if the emitter is that of a MutableMeshImpl and if + // it has no transforms, in which case the entire data array can be copied in bulk. + @Override + public void outputTo(QuadEmitter emitter) { + MutableQuadViewImpl e = (MutableQuadViewImpl) emitter; + final int[] data = this.data; + final int limit = this.limit; + int index = 0; + + while (index < limit) { + System.arraycopy(data, index, e.data, e.baseIndex, EncodingFormat.TOTAL_STRIDE); + e.load(); + e.transformAndEmit(); + index += EncodingFormat.TOTAL_STRIDE; + } + + e.clear(); + } +} \ No newline at end of file diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/mesh/MutableMeshImpl.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/mesh/MutableMeshImpl.java new file mode 100644 index 000000000..79ab94df6 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/mesh/MutableMeshImpl.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.vulkanmod.render.chunk.build.frapi.mesh; + +import java.util.function.Consumer; + +import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh; +import net.fabricmc.fabric.api.renderer.v1.mesh.MutableMesh; +import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; + +/** + * Our implementation of {@link MutableMesh}, mainly used for optimized mesh creation. + * Not much to it - mainly it just needs to grow the int[] array as quads are appended + * and maintain/provide a properly-configured {@link MutableQuadView} instance. + * All the encoding and other work is handled in the quad base classes. + * The one interesting bit is in {@link #emitter}. + */ +public class MutableMeshImpl extends MeshImpl implements MutableMesh { + private final MutableQuadViewImpl emitter = new MutableQuadViewImpl() { + @Override + protected void emitDirectly() { + // Necessary because the validity of geometry is not encoded; reading mesh data always + // uses QuadViewImpl#load(), which assumes valid geometry. Built immutable meshes + // should also have valid geometry for better performance. + computeGeometry(); + limit += EncodingFormat.TOTAL_STRIDE; + ensureCapacity(EncodingFormat.TOTAL_STRIDE); + baseIndex = limit; + } + }; + + public MutableMeshImpl() { + data = new int[8 * EncodingFormat.TOTAL_STRIDE]; + limit = 0; + + ensureCapacity(EncodingFormat.TOTAL_STRIDE); + emitter.data = data; + emitter.baseIndex = limit; + emitter.clear(); + } + + private void ensureCapacity(int stride) { + if (stride > data.length - limit) { + final int[] bigger = new int[data.length * 2]; + System.arraycopy(data, 0, bigger, 0, limit); + data = bigger; + emitter.data = data; + } + } + + @Override + public QuadEmitter emitter() { + emitter.clear(); + return emitter; + } + + @Override + public void forEachMutable(Consumer action) { + // emitDirectly will not be called by forEach, so just reuse the main emitter. + forEach(action, emitter); + emitter.data = data; + emitter.baseIndex = limit; + } + + @Override + public Mesh immutableCopy() { + final int[] packed = new int[limit]; + System.arraycopy(data, 0, packed, 0, limit); + return new MeshImpl(packed); + } + + @Override + public void clear() { + limit = 0; + emitter.baseIndex = limit; + emitter.clear(); + } +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/mesh/MutableQuadViewImpl.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/mesh/MutableQuadViewImpl.java new file mode 100644 index 000000000..215db6398 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/mesh/MutableQuadViewImpl.java @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.vulkanmod.render.chunk.build.frapi.mesh; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.fabricmc.fabric.api.renderer.v1.mesh.ShadeMode; +import net.fabricmc.fabric.api.util.TriState; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.chunk.ChunkSectionLayer; +import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.vulkanmod.render.model.quad.ModelQuadView; +import org.jetbrains.annotations.Nullable; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadTransform; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; +import net.vulkanmod.render.chunk.build.frapi.helper.ColorHelper; +import net.vulkanmod.render.chunk.build.frapi.helper.NormalHelper; +import net.vulkanmod.render.chunk.build.frapi.helper.TextureHelper; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.core.Direction; + +import java.util.Objects; + +import static net.vulkanmod.render.chunk.build.frapi.mesh.EncodingFormat.*; + +/** + * Almost-concrete implementation of a mutable quad. The only missing part is {@link #emitDirectly()}, + * because that depends on where/how it is used. (Mesh encoding vs. render-time transformation). + * + *

In many cases an instance of this class is used as an "editor quad". The editor quad's + * {@link #emitDirectly()} method calls some other internal method that transforms the quad + * data and then buffers it. Transformations should be the same as they would be in a vanilla + * render - the editor is serving mainly as a way to access vertex data without magical + * numbers. It also allows for a consistent interface for those transformations. + */ +public abstract class MutableQuadViewImpl extends QuadViewImpl implements QuadEmitter { + private static final QuadTransform NO_TRANSFORM = q -> true; + + private static final int[] DEFAULT_QUAD_DATA = new int[EncodingFormat.TOTAL_STRIDE]; + + static { + MutableQuadViewImpl quad = new MutableQuadViewImpl() { + @Override + protected void emitDirectly() { + // This quad won't be emitted. It's only used to configure the default quad data. + } + }; + + // Start with all zeroes + quad.data = DEFAULT_QUAD_DATA; + // Apply non-zero defaults + quad.color(-1, -1, -1, -1); + quad.cullFace(null); + quad.renderLayer(null); + quad.diffuseShade(true); + quad.ambientOcclusion(TriState.DEFAULT); + quad.glint(null); + quad.tintIndex(-1); + quad.tintIndex(-1); + } + + protected boolean hasTransform = false; + private QuadTransform activeTransform = NO_TRANSFORM; + private final ObjectArrayList transformStack = new ObjectArrayList<>(); + private final QuadTransform stackTransform = q -> { + int i = transformStack.size() - 1; + + while (i >= 0) { + if (!transformStack.get(i--).transform(q)) { + return false; + } + } + + return true; + }; + + public final void clear() { + System.arraycopy(DEFAULT_QUAD_DATA, 0, data, baseIndex, EncodingFormat.TOTAL_STRIDE); + isGeometryInvalid = true; + nominalFace = null; + } + + @Override + public MutableQuadViewImpl pos(int vertexIndex, float x, float y, float z) { + final int index = baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_X; + data[index] = Float.floatToRawIntBits(x); + data[index + 1] = Float.floatToRawIntBits(y); + data[index + 2] = Float.floatToRawIntBits(z); + isGeometryInvalid = true; + return this; + } + + @Override + public MutableQuadViewImpl color(int vertexIndex, int color) { + data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_COLOR] = color; + return this; + } + + @Override + public MutableQuadViewImpl uv(int vertexIndex, float u, float v) { + final int i = baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_U; + data[i] = Float.floatToRawIntBits(u); + data[i + 1] = Float.floatToRawIntBits(v); + return this; + } + + @Override + public MutableQuadViewImpl spriteBake(TextureAtlasSprite sprite, int bakeFlags) { + TextureHelper.bakeSprite(this, sprite, bakeFlags); + return this; + } + + @Override + public MutableQuadViewImpl lightmap(int vertexIndex, int lightmap) { + data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_LIGHTMAP] = lightmap; + return this; + } + + protected void normalFlags(int flags) { + data[baseIndex + HEADER_BITS] = EncodingFormat.normalFlags(data[baseIndex + HEADER_BITS], flags); + } + + @Override + public MutableQuadViewImpl normal(int vertexIndex, float x, float y, float z) { + normalFlags(normalFlags() | (1 << vertexIndex)); + data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_NORMAL] = NormalHelper.packNormal(x, y, z); + return this; + } + + /** + * Internal helper method. Copies face normals to vertex normals lacking one. + */ + public final void populateMissingNormals() { + final int normalFlags = this.normalFlags(); + + if (normalFlags == 0b1111) return; + + final int packedFaceNormal = packedFaceNormal(); + + for (int v = 0; v < 4; v++) { + if ((normalFlags & (1 << v)) == 0) { + data[baseIndex + v * VERTEX_STRIDE + VERTEX_NORMAL] = packedFaceNormal; + } + } + + normalFlags(0b1111); + } + + @Override + public final MutableQuadViewImpl nominalFace(@Nullable Direction face) { + nominalFace = face; + return this; + } + + @Override + public final MutableQuadViewImpl cullFace(@Nullable Direction face) { + data[baseIndex + HEADER_BITS] = EncodingFormat.cullFace(data[baseIndex + HEADER_BITS], face); + nominalFace(face); + return this; + } + + @Override + public MutableQuadViewImpl renderLayer(@Nullable ChunkSectionLayer renderLayer) { + data[baseIndex + HEADER_BITS] = EncodingFormat.renderLayer(data[baseIndex + HEADER_BITS], renderLayer); + return this; + } + + @Override + public MutableQuadViewImpl emissive(boolean emissive) { + data[baseIndex + HEADER_BITS] = EncodingFormat.emissive(data[baseIndex + HEADER_BITS], emissive); + return this; + } + + @Override + public MutableQuadViewImpl diffuseShade(boolean shade) { + data[baseIndex + HEADER_BITS] = EncodingFormat.diffuseShade(data[baseIndex + HEADER_BITS], shade); + return this; + } + + @Override + public MutableQuadViewImpl ambientOcclusion(TriState ao) { + Objects.requireNonNull(ao, "ambient occlusion TriState may not be null"); + data[baseIndex + HEADER_BITS] = EncodingFormat.ambientOcclusion(data[baseIndex + HEADER_BITS], ao); + return this; + } + + @Override + public MutableQuadViewImpl glint(@Nullable ItemStackRenderState.FoilType glint) { + data[baseIndex + HEADER_BITS] = EncodingFormat.glint(data[baseIndex + HEADER_BITS], glint); + return this; + } + + @Override + public MutableQuadViewImpl shadeMode(ShadeMode mode) { + Objects.requireNonNull(mode, "ShadeMode may not be null"); + data[baseIndex + HEADER_BITS] = EncodingFormat.shadeMode(data[baseIndex + HEADER_BITS], mode); + return this; + } + + @Override + public final MutableQuadViewImpl tintIndex(int tintIndex) { + data[baseIndex + HEADER_TINT_INDEX] = tintIndex; + return this; + } + + @Override + public final MutableQuadViewImpl tag(int tag) { + data[baseIndex + HEADER_TAG] = tag; + return this; + } + + @Override + public MutableQuadViewImpl copyFrom(QuadView quad) { + final QuadViewImpl q = (QuadViewImpl) quad; + System.arraycopy(q.data, q.baseIndex, data, baseIndex, EncodingFormat.TOTAL_STRIDE); + nominalFace = q.nominalFace; + isGeometryInvalid = q.isGeometryInvalid; + + if (!isGeometryInvalid) { + faceNormal.set(q.faceNormal); + } + + return this; + } + + @Override + public final MutableQuadViewImpl fromVanilla(int[] quadData, int startIndex) { + System.arraycopy(quadData, startIndex, data, baseIndex + HEADER_STRIDE, VANILLA_QUAD_STRIDE); + isGeometryInvalid = true; + + int normalFlags = 0; + int colorIndex = baseIndex + VERTEX_COLOR; + int normalIndex = baseIndex + VERTEX_NORMAL; + + for (int i = 0; i < 4; i++) { + data[colorIndex] = ColorHelper.fromVanillaColor(data[colorIndex]); + + // Set normal flag if normal is not zero, ignoring W component + if ((data[normalIndex] & 0xFFFFFF) != 0) { + normalFlags |= 1 << i; + } + + colorIndex += VERTEX_STRIDE; + normalIndex += VERTEX_STRIDE; + } + + normalFlags(normalFlags); + return this; + } + + @Override + public final MutableQuadViewImpl fromBakedQuad(BakedQuad quad) { + fromVanilla(quad.vertices(), 0); +// data[baseIndex + HEADER_BITS] = EncodingFormat.cullFace(0, cullFace); + nominalFace(quad.direction()); + diffuseShade(quad.shade()); + tintIndex(quad.tintIndex()); + +// tag(0); + + // Copy data from BakedQuad instead of calculating properties + ModelQuadView quadView = (ModelQuadView) (Object) quad; + int normal = quadView.getNormal(); + data[baseIndex + HEADER_FACE_NORMAL] = normal; + NormalHelper.unpackNormalTo(normal, faceNormal); + + Direction lightFace = quadView.lightFace(); + data[baseIndex + HEADER_BITS] = EncodingFormat.lightFace(data[baseIndex + HEADER_BITS], lightFace); + data[baseIndex + HEADER_BITS] = EncodingFormat.geometryFlags(data[baseIndex + HEADER_BITS], quadView.getFlags()); + + this.facing = quadView.getQuadFacing(); + this.isGeometryInvalid = false; + + int lightEmission = quad.lightEmission(); + + if (lightEmission > 0) { + for (int i = 0; i < 4; i++) { + lightmap(i, LightTexture.lightCoordsWithEmission(lightmap(i), lightEmission)); + } + } + + return this; + } + + @Override + public void pushTransform(QuadTransform transform) { + if (transform == null) { + throw new NullPointerException("QuadTransform cannot be null!"); + } + + transformStack.push(transform); + hasTransform = true; + + if (transformStack.size() == 1) { + activeTransform = transform; + } else if (transformStack.size() == 2) { + activeTransform = stackTransform; + } + } + + @Override + public void popTransform() { + transformStack.pop(); + + if (transformStack.size() == 0) { + activeTransform = NO_TRANSFORM; + hasTransform = false; + } else if (transformStack.size() == 1) { + activeTransform = transformStack.get(0); + } + } + + /** + * Emit the quad without applying transforms and without clearing the underlying data. + * Geometry is not guaranteed to be valid when called, but can be computed by calling {@link #computeGeometry()}. + */ + protected abstract void emitDirectly(); + + /** + * Apply transforms and then if transforms return true, emit the quad without clearing the underlying data. + */ + public final void transformAndEmit() { + if (activeTransform.transform(this)) { + emitDirectly(); + } + } + + @Override + public final MutableQuadViewImpl emit() { + transformAndEmit(); + clear(); + return this; + } +} \ No newline at end of file diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/mesh/QuadViewImpl.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/mesh/QuadViewImpl.java new file mode 100644 index 000000000..723e80792 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/mesh/QuadViewImpl.java @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.vulkanmod.render.chunk.build.frapi.mesh; + +import static net.vulkanmod.render.chunk.build.frapi.mesh.EncodingFormat.HEADER_BITS; +import static net.vulkanmod.render.chunk.build.frapi.mesh.EncodingFormat.HEADER_TINT_INDEX; +import static net.vulkanmod.render.chunk.build.frapi.mesh.EncodingFormat.HEADER_FACE_NORMAL; +import static net.vulkanmod.render.chunk.build.frapi.mesh.EncodingFormat.HEADER_STRIDE; +import static net.vulkanmod.render.chunk.build.frapi.mesh.EncodingFormat.HEADER_TAG; +import static net.vulkanmod.render.chunk.build.frapi.mesh.EncodingFormat.QUAD_STRIDE; +import static net.vulkanmod.render.chunk.build.frapi.mesh.EncodingFormat.VERTEX_COLOR; +import static net.vulkanmod.render.chunk.build.frapi.mesh.EncodingFormat.VERTEX_LIGHTMAP; +import static net.vulkanmod.render.chunk.build.frapi.mesh.EncodingFormat.VERTEX_NORMAL; +import static net.vulkanmod.render.chunk.build.frapi.mesh.EncodingFormat.VERTEX_STRIDE; +import static net.vulkanmod.render.chunk.build.frapi.mesh.EncodingFormat.VERTEX_U; +import static net.vulkanmod.render.chunk.build.frapi.mesh.EncodingFormat.VERTEX_V; +import static net.vulkanmod.render.chunk.build.frapi.mesh.EncodingFormat.VERTEX_X; +import static net.vulkanmod.render.chunk.build.frapi.mesh.EncodingFormat.VERTEX_Y; +import static net.vulkanmod.render.chunk.build.frapi.mesh.EncodingFormat.VERTEX_Z; + +import net.fabricmc.fabric.api.renderer.v1.mesh.ShadeMode; +import net.fabricmc.fabric.api.util.TriState; +import net.minecraft.client.renderer.chunk.ChunkSectionLayer; +import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.vulkanmod.render.chunk.cull.QuadFacing; +import net.vulkanmod.render.model.quad.ModelQuadFlags; +import net.vulkanmod.render.model.quad.ModelQuadView; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.joml.Vector2f; +import org.joml.Vector3f; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; +import net.vulkanmod.render.chunk.build.frapi.helper.ColorHelper; +import net.vulkanmod.render.chunk.build.frapi.helper.GeometryHelper; +import net.vulkanmod.render.chunk.build.frapi.helper.NormalHelper; +import net.minecraft.core.Direction; + +/** + * Base class for all quads / quad makers. Handles the ugly bits + * of maintaining and encoding the quad state. + */ +public class QuadViewImpl implements QuadView, ModelQuadView { + @Nullable + protected Direction nominalFace; + /** True when face normal, light face, or geometry flags may not match geometry. */ + protected boolean isGeometryInvalid = true; + protected final Vector3f faceNormal = new Vector3f(); + + /** Size and where it comes from will vary in subtypes. But in all cases quad is fully encoded to array. */ + protected int[] data; + + /** Beginning of the quad. Also the header index. */ + protected int baseIndex = 0; + + protected QuadFacing facing; + + /** + * Decodes necessary state from the backing data array. + * The encoded data must contain valid computed geometry. + */ + public void load() { + isGeometryInvalid = false; + nominalFace = lightFace(); + NormalHelper.unpackNormal(packedFaceNormal(), faceNormal); + facing = QuadFacing.fromNormal(faceNormal); + } + + protected void computeGeometry() { + if (isGeometryInvalid) { + isGeometryInvalid = false; + + NormalHelper.computeFaceNormal(faceNormal, this); + data[baseIndex + HEADER_FACE_NORMAL] = NormalHelper.packNormal(faceNormal); + + // depends on face normal + Direction lightFace = GeometryHelper.lightFace(this); + data[baseIndex + HEADER_BITS] = EncodingFormat.lightFace(data[baseIndex + HEADER_BITS], lightFace); + + // depends on light face + data[baseIndex + HEADER_BITS] = EncodingFormat.geometryFlags(data[baseIndex + HEADER_BITS], ModelQuadFlags.getQuadFlags(this, lightFace)); + + facing = QuadFacing.fromNormal(faceNormal); + } + } + + /** gets flags used for lighting - lazily computed via {@link GeometryHelper#computeShapeFlags(QuadView)}. */ + public int geometryFlags() { + computeGeometry(); + return EncodingFormat.geometryFlags(data[baseIndex + HEADER_BITS]); + } + + @Override + public float x(int vertexIndex) { + return Float.intBitsToFloat(data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_X]); + } + + @Override + public float y(int vertexIndex) { + return Float.intBitsToFloat(data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_Y]); + } + + @Override + public float z(int vertexIndex) { + return Float.intBitsToFloat(data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_Z]); + } + + @Override + public float posByIndex(int vertexIndex, int coordinateIndex) { + return Float.intBitsToFloat(data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_X + coordinateIndex]); + } + + @Override + public Vector3f copyPos(int vertexIndex, @Nullable Vector3f target) { + if (target == null) { + target = new Vector3f(); + } + + final int index = baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_X; + target.set(Float.intBitsToFloat(data[index]), Float.intBitsToFloat(data[index + 1]), Float.intBitsToFloat(data[index + 2])); + return target; + } + + @Override + public int color(int vertexIndex) { + return data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_COLOR]; + } + + @Override + public float u(int vertexIndex) { + return Float.intBitsToFloat(data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_U]); + } + + @Override + public float v(int vertexIndex) { + return Float.intBitsToFloat(data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_V]); + } + + @Override + public Vector2f copyUv(int vertexIndex, @Nullable Vector2f target) { + if (target == null) { + target = new Vector2f(); + } + + final int index = baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_U; + target.set(Float.intBitsToFloat(data[index]), Float.intBitsToFloat(data[index + 1])); + return target; + } + + @Override + public int lightmap(int vertexIndex) { + return data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_LIGHTMAP]; + } + + public final int normalFlags() { + return EncodingFormat.normalFlags(data[baseIndex + HEADER_BITS]); + } + + @Override + public final boolean hasNormal(int vertexIndex) { + return (normalFlags() & (1 << vertexIndex)) != 0; + } + + /** True if any vertex normal has been set. */ + public final boolean hasVertexNormals() { + return normalFlags() != 0; + } + + /** True if all vertex normals have been set. */ + public final boolean hasAllVertexNormals() { + return (normalFlags() & 0b1111) == 0b1111; + } + + protected final int normalIndex(int vertexIndex) { + return baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_NORMAL; + } + + @Override + public final float normalX(int vertexIndex) { + return hasNormal(vertexIndex) ? NormalHelper.unpackNormalX(data[normalIndex(vertexIndex)]) : Float.NaN; + } + + @Override + public final float normalY(int vertexIndex) { + return hasNormal(vertexIndex) ? NormalHelper.unpackNormalY(data[normalIndex(vertexIndex)]) : Float.NaN; + } + + @Override + public final float normalZ(int vertexIndex) { + return hasNormal(vertexIndex) ? NormalHelper.unpackNormalZ(data[normalIndex(vertexIndex)]) : Float.NaN; + } + + @Override + @Nullable + public final Vector3f copyNormal(int vertexIndex, @Nullable Vector3f target) { + if (hasNormal(vertexIndex)) { + if (target == null) { + target = new Vector3f(); + } + + final int normal = data[normalIndex(vertexIndex)]; + NormalHelper.unpackNormal(normal, target); + return target; + } else { + return null; + } + } + + @Override + @NotNull + public final Direction lightFace() { + computeGeometry(); + return EncodingFormat.lightFace(data[baseIndex + HEADER_BITS]); + } + + @Override + @Nullable + public final Direction nominalFace() { + return nominalFace; + } + + public final int packedFaceNormal() { + computeGeometry(); + return data[baseIndex + HEADER_FACE_NORMAL]; + } + + @Override + public final Vector3f faceNormal() { + computeGeometry(); + return faceNormal; + } + + @Override + @Nullable + public final Direction cullFace() { + return EncodingFormat.cullFace(data[baseIndex + HEADER_BITS]); + } + + @Override + @Nullable + public ChunkSectionLayer renderLayer() { + return EncodingFormat.renderLayer(data[baseIndex + HEADER_BITS]); + } + + @Override + public boolean emissive() { + return EncodingFormat.emissive(data[baseIndex + HEADER_BITS]); + } + + @Override + public boolean diffuseShade() { + return EncodingFormat.diffuseShade(data[baseIndex + HEADER_BITS]); + } + + @Override + public TriState ambientOcclusion() { + return EncodingFormat.ambientOcclusion(data[baseIndex + HEADER_BITS]); + } + + @Override + @Nullable + public ItemStackRenderState.FoilType glint() { + return EncodingFormat.glint(data[baseIndex + HEADER_BITS]); + } + + @Override + public ShadeMode shadeMode() { + return EncodingFormat.shadeMode(data[baseIndex + HEADER_BITS]); + } + + @Override + public final int tintIndex() { + return data[baseIndex + HEADER_TINT_INDEX]; + } + + @Override + public final int tag() { + return data[baseIndex + HEADER_TAG]; + } + + @Override + public final void toVanilla(int[] target, int targetIndex) { + System.arraycopy(data, baseIndex + HEADER_STRIDE, target, targetIndex, QUAD_STRIDE); + + int colorIndex = targetIndex + VERTEX_COLOR - HEADER_STRIDE; + + for (int i = 0; i < 4; i++) { + target[colorIndex] = ColorHelper.toVanillaColor(target[colorIndex]); + colorIndex += VANILLA_VERTEX_STRIDE; + } + } + + @Override + public int getFlags() { + return geometryFlags(); + } + + @Override + public float getX(int idx) { + return this.x(idx); + } + + @Override + public float getY(int idx) { + return this.y(idx); + } + + @Override + public float getZ(int idx) { + return this.z(idx); + } + + @Override + public int getColor(int idx) { + return this.color(idx); + } + + @Override + public float getU(int idx) { + return this.u(idx); + } + + @Override + public float getV(int idx) { + return this.v(idx); + } + + @Override + public int getColorIndex() { + return this.tintIndex(); + } + + @Override + public Direction getFacingDirection() { + return this.lightFace(); + } + + @Override + public int getNormal() { + return packedFaceNormal(); + } + + @Override + public QuadFacing getQuadFacing() { + return this.facing; + } +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/AbstractBlockRenderContext.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/AbstractBlockRenderContext.java new file mode 100644 index 000000000..9750c2f47 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/AbstractBlockRenderContext.java @@ -0,0 +1,295 @@ +package net.vulkanmod.render.chunk.build.frapi.render; + +import com.mojang.blaze3d.vertex.VertexConsumer; +import it.unimi.dsi.fastutil.objects.Object2ByteLinkedOpenHashMap; +import net.fabricmc.fabric.api.renderer.v1.Renderer; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; +import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper; +import net.minecraft.client.Minecraft; +import net.minecraft.client.color.block.BlockColor; +import net.minecraft.client.color.block.BlockColors; +import net.minecraft.client.renderer.ItemBlockRenderTypes; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.BlockModelPart; +import net.minecraft.client.renderer.block.model.BlockStateModel; +import net.minecraft.client.renderer.chunk.ChunkSectionLayer; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.phys.shapes.BooleanOp; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.vulkanmod.interfaces.color.BlockColorsExtended; +import net.vulkanmod.render.chunk.build.color.BlockColorRegistry; +import net.vulkanmod.render.chunk.build.frapi.VulkanModRenderer; +import net.vulkanmod.render.chunk.build.light.LightPipeline; +import net.vulkanmod.render.chunk.build.light.data.QuadLightData; +import org.jetbrains.annotations.Nullable; +import net.vulkanmod.render.chunk.build.frapi.helper.ColorHelper; +import net.vulkanmod.render.chunk.build.frapi.mesh.EncodingFormat; +import net.vulkanmod.render.chunk.build.frapi.mesh.MutableQuadViewImpl; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.BlockState; + +import java.util.List; +import java.util.function.Predicate; +import java.util.function.Supplier; + +public abstract class AbstractBlockRenderContext extends AbstractRenderContext { + private static final Renderer RENDERER = VulkanModRenderer.INSTANCE; + + protected final BlockColorRegistry blockColorRegistry; + + private final MutableQuadViewImpl editorQuad = new MutableQuadViewImpl() { + { + data = new int[EncodingFormat.TOTAL_STRIDE]; + clear(); + } + + @Override + public void emitDirectly() { + renderQuad(this); + } + +// @Override +// public void emitBlockQuads(QuadEmitter emitter, BakedModel model, BlockState state, +// Supplier randomSupplier, Predicate<@Nullable Direction> cullTest) { +// if (this.hasTransform) { +// super.emitBlockQuads(emitter, model, state, randomSupplier, cullTest); +// } else { +// AbstractBlockRenderContext.this.emitVanillaBlockQuads(model, state, randomSupplier, cullTest); +// } +// } + }; + + protected BlockState blockState; + protected BlockPos blockPos; + protected BlockPos.MutableBlockPos tempPos = new BlockPos.MutableBlockPos(); + protected ChunkSectionLayer defaultLayer; + + protected BlockAndTintGetter renderRegion; + + protected final Object2ByteLinkedOpenHashMap occlusionCache = new Object2ByteLinkedOpenHashMap<>(2048, 0.25F) { + protected void rehash(int i) { + } + }; + + protected final QuadLightData quadLightData = new QuadLightData(); + protected LightPipeline smoothLightPipeline; + protected LightPipeline flatLightPipeline; + + protected boolean useAO; + protected boolean defaultAO; + + protected RandomSource random; + + protected boolean enableCulling = true; + protected int cullCompletionFlags; + protected int cullResultFlags; + + protected AbstractBlockRenderContext() { + this.occlusionCache.defaultReturnValue((byte) 127); + + BlockColors blockColors = Minecraft.getInstance().getBlockColors(); + this.blockColorRegistry = BlockColorsExtended.from(blockColors).getColorResolverMap(); + } + + protected void setupLightPipelines(LightPipeline flatLightPipeline, LightPipeline smoothLightPipeline) { + this.flatLightPipeline = flatLightPipeline; + this.smoothLightPipeline = smoothLightPipeline; + } + + public void prepareForWorld(BlockAndTintGetter blockView, boolean enableCulling) { + this.renderRegion = blockView; + this.enableCulling = enableCulling; + } + + public void prepareForBlock(BlockState blockState, BlockPos blockPos, boolean modelAo) { + this.blockPos = blockPos; + this.blockState = blockState; + this.defaultLayer = ItemBlockRenderTypes.getChunkRenderType(blockState); + + this.useAO = Minecraft.useAmbientOcclusion(); + this.defaultAO = this.useAO && modelAo && blockState.getLightEmission() == 0; + + this.cullCompletionFlags = 0; + this.cullResultFlags = 0; + } + + public boolean isFaceCulled(@Nullable Direction face) { + return !this.shouldRenderFace(face); + } + + public boolean shouldRenderFace(Direction face) { + if (face == null || !enableCulling) { + return true; + } + + final int mask = 1 << face.get3DDataValue(); + + if ((cullCompletionFlags & mask) == 0) { + cullCompletionFlags |= mask; + + if (this.faceNotOccluded(blockState, face)) { + cullResultFlags |= mask; + return true; + } else { + return false; + } + } else { + return (cullResultFlags & mask) != 0; + } + } + + public boolean faceNotOccluded(BlockState blockState, Direction face) { + BlockGetter blockGetter = this.renderRegion; + + BlockPos adjPos = tempPos.setWithOffset(blockPos, face); + BlockState adjBlockState = blockGetter.getBlockState(adjPos); + + if (blockState.skipRendering(adjBlockState, face)) { + return false; + } + + if (adjBlockState.canOcclude()) { + VoxelShape shape = blockState.getFaceOcclusionShape(face); + + if (shape.isEmpty()) + return true; + + VoxelShape adjShape = adjBlockState.getFaceOcclusionShape(face.getOpposite()); + + if (adjShape.isEmpty()) + return true; + + if (shape == Shapes.block() && adjShape == Shapes.block()) { + return false; + } + + ShapePairKey blockStatePairKey = new ShapePairKey(shape, adjShape); + + byte b = occlusionCache.getAndMoveToFirst(blockStatePairKey); + if (b != 127) { + return b != 0; + } else { + boolean bl = Shapes.joinIsNotEmpty(shape, adjShape, BooleanOp.ONLY_FIRST); + + if (occlusionCache.size() == 2048) { + occlusionCache.removeLastByte(); + } + + occlusionCache.putAndMoveToFirst(blockStatePairKey, (byte) (bl ? 1 : 0)); + return bl; + } + } + + return true; + } + + public QuadEmitter getEmitter() { + editorQuad.clear(); + return editorQuad; + } + + @Override + protected void bufferQuad(MutableQuadViewImpl quadView) { + this.renderQuad(quadView); + } + + protected abstract VertexConsumer getVertexConsumer(ChunkSectionLayer layer); + + private void renderQuad(MutableQuadViewImpl quad) { + if (isFaceCulled(quad.cullFace())) { + return; + } + + endRenderQuad(quad); + } + + protected void endRenderQuad(MutableQuadViewImpl quad) {} + + /** handles block color, common to all renders. */ + protected void tintQuad(MutableQuadViewImpl quad) { + int tintIndex = quad.tintIndex(); + + if (tintIndex != -1) { + final int blockColor = getBlockColor(this.renderRegion, tintIndex); + + for (int i = 0; i < 4; i++) { + quad.color(i, ColorHelper.multiplyColor(blockColor, quad.color(i))); + } + } + } + + private int getBlockColor(BlockAndTintGetter region, int colorIndex) { + BlockColor blockColor = this.blockColorRegistry.getBlockColor(this.blockState.getBlock()); + + int color = blockColor != null ? blockColor.getColor(blockState, region, blockPos, colorIndex) : -1; + return 0xFF000000 | color; + } + + protected void shadeQuad(MutableQuadViewImpl quad, LightPipeline lightPipeline, boolean emissive, boolean vanillaShade) { + QuadLightData data = this.quadLightData; + + // TODO: enhanced AO + lightPipeline.calculate(quad, this.blockPos, data, quad.cullFace(), quad.lightFace(), quad.diffuseShade()); + + if (emissive) { + for (int i = 0; i < 4; i++) { + quad.color(i, ColorHelper.multiplyRGB(quad.color(i), data.br[i])); +// quad.lightmap(i, LightTexture.FULL_BRIGHT); + data.lm[i] = LightTexture.FULL_BRIGHT; + } + } else { + for (int i = 0; i < 4; i++) { + quad.color(i, ColorHelper.multiplyRGB(quad.color(i), data.br[i])); +// quad.lightmap(i, ColorHelper.maxBrightness(quad.lightmap(i), data.lm[i])); + data.lm[i] = ColorHelper.maxBrightness(quad.lightmap(i), data.lm[i]); + } + } + } + + public ChunkSectionLayer effectiveRenderLayer(@Nullable ChunkSectionLayer quadRenderLayer) { + return quadRenderLayer == null ? defaultLayer : quadRenderLayer; + } + + public void emitVanillaBlockQuads(BlockStateModel model, @Nullable BlockState state, Supplier randomSupplier, Predicate cullTest) { + MutableQuadViewImpl quad = this.editorQuad; +// final RenderMaterial defaultMaterial = state.getLightEmission() == 0 ? STANDARD_MATERIAL : NO_AO_MATERIAL; + + for (int i = 0; i <= ModelHelper.NULL_FACE_ID; i++) { + final Direction cullFace = ModelHelper.faceFromIndex(i); + + if (cullTest.test(cullFace)) { + // Skip entire quad list if possible. + continue; + } + + final List parts = ((BlockStateModel) this).collectParts(random); + final int partCount = parts.size(); + + for (int j = 0; j < partCount; j++) { + parts.get(j).emitQuads(quad, cullTest); + } + } + + } + + // TODO move elsewhere + record ShapePairKey(VoxelShape first, VoxelShape second) { + public boolean equals(Object object) { + if (object instanceof ShapePairKey shapePairKey && this.first == shapePairKey.first && this.second == shapePairKey.second) { + return true; + } + + return false; + } + + public int hashCode() { + return System.identityHashCode(this.first) * 31 + System.identityHashCode(this.second); + } + } + +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/AbstractRenderContext.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/AbstractRenderContext.java new file mode 100644 index 000000000..d98321876 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/AbstractRenderContext.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.vulkanmod.render.chunk.build.frapi.render; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; +import net.vulkanmod.render.chunk.build.frapi.mesh.EncodingFormat; +import net.vulkanmod.render.chunk.build.frapi.mesh.MutableQuadViewImpl; +import org.joml.Matrix3f; +import org.joml.Matrix4f; +import org.joml.Vector3f; +import org.joml.Vector4f; + + +public abstract class AbstractRenderContext { + private final MutableQuadViewImpl editorQuad = new MutableQuadViewImpl() { + { + data = new int[EncodingFormat.TOTAL_STRIDE]; + clear(); + } + + @Override + protected void emitDirectly() { + bufferQuad(this); + } + }; + + private final Vector4f posVec = new Vector4f(); + private final Vector3f normalVec = new Vector3f(); + + protected PoseStack.Pose matrices; + protected int overlay; + + protected QuadEmitter getEmitter() { + editorQuad.clear(); + return editorQuad; + } + + protected abstract void bufferQuad(MutableQuadViewImpl quadView); + + /** final output step, common to all renders. */ + protected void bufferQuad(MutableQuadViewImpl quad, VertexConsumer vertexConsumer) { + final Vector4f posVec = this.posVec; + final Vector3f normalVec = this.normalVec; + final PoseStack.Pose matrices = this.matrices; + final Matrix4f posMatrix = matrices.pose(); + final boolean useNormals = quad.hasVertexNormals(); + + if (useNormals) { + quad.populateMissingNormals(); + } else { + matrices.transformNormal(quad.faceNormal(), normalVec); + } + + for (int i = 0; i < 4; i++) { + posVec.set(quad.x(i), quad.y(i), quad.z(i), 1.0f); + posVec.mul(posMatrix); + + if (useNormals) { + quad.copyNormal(i, normalVec); + matrices.transformNormal(normalVec, normalVec); + } + + vertexConsumer.addVertex(posVec.x(), posVec.y(), posVec.z(), quad.color(i), quad.u(i), quad.v(i), overlay, quad.lightmap(i), normalVec.x(), normalVec.y(), normalVec.z()); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/BlockRenderContext.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/BlockRenderContext.java new file mode 100644 index 000000000..872671b4b --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/BlockRenderContext.java @@ -0,0 +1,101 @@ +package net.vulkanmod.render.chunk.build.frapi.render; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.fabricmc.fabric.api.renderer.v1.mesh.ShadeMode; +import net.fabricmc.fabric.api.renderer.v1.render.BlockVertexConsumerProvider; +import net.fabricmc.fabric.api.util.TriState; +import net.minecraft.client.renderer.ItemBlockRenderTypes; +import net.minecraft.client.renderer.block.model.BlockStateModel; +import net.minecraft.client.renderer.chunk.ChunkSectionLayer; +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.vulkanmod.Initializer; +import net.vulkanmod.render.chunk.build.frapi.mesh.MutableQuadViewImpl; +import net.vulkanmod.render.chunk.build.light.LightMode; +import net.vulkanmod.render.chunk.build.light.LightPipeline; +import net.vulkanmod.render.chunk.build.light.data.ArrayLightDataCache; +import net.vulkanmod.render.chunk.build.light.flat.FlatLightPipeline; +import net.vulkanmod.render.chunk.build.light.smooth.NewSmoothLightPipeline; +import net.vulkanmod.render.chunk.build.light.smooth.SmoothLightPipeline; + +/** + * Context for non-terrain block rendering. + */ +public class BlockRenderContext extends AbstractBlockRenderContext { + public static final ThreadLocal POOL = ThreadLocal.withInitial(BlockRenderContext::new); + + private BlockVertexConsumerProvider vertexConsumers; + private ChunkSectionLayer defaultRenderLayer; + + private final ArrayLightDataCache lightDataCache = new ArrayLightDataCache(); + + public BlockRenderContext() { + LightPipeline flatLightPipeline = new FlatLightPipeline(this.lightDataCache); + + LightPipeline smoothLightPipeline; + if (Initializer.CONFIG.ambientOcclusion == LightMode.SUB_BLOCK) { + smoothLightPipeline = new NewSmoothLightPipeline(lightDataCache); + } + else { + smoothLightPipeline = new SmoothLightPipeline(lightDataCache); + } + + this.setupLightPipelines(flatLightPipeline, smoothLightPipeline); + + random = RandomSource.create(); + } + + public void render(BlockAndTintGetter blockView, BlockStateModel model, BlockState state, BlockPos pos, PoseStack matrixStack, BlockVertexConsumerProvider buffers, boolean cull, long seed, int overlay) { + Vec3 offset = state.getOffset(pos); + matrixStack.translate(offset.x, offset.y, offset.z); + + this.blockPos = pos; + this.vertexConsumers = buffers; + this.defaultRenderLayer = ItemBlockRenderTypes.getChunkRenderType(state); + this.matrices = matrixStack.last(); + this.overlay = overlay; + this.random.setSeed(seed); + + this.lightDataCache.reset(blockView, pos); + + this.prepareForWorld(blockView, cull); + this.prepareForBlock(state, pos, state.getLightEmission() == 0); + + model.emitQuads(getEmitter(), blockView, pos, state, random, this::isFaceCulled); + + this.vertexConsumers = null; + } + + @Override + protected VertexConsumer getVertexConsumer(ChunkSectionLayer layer) { + return vertexConsumers.getBuffer(layer); + } + + protected void endRenderQuad(MutableQuadViewImpl quad) { + final TriState aoMode = quad.ambientOcclusion(); + final boolean ao = this.useAO && (aoMode == TriState.TRUE || (aoMode == TriState.DEFAULT && this.defaultAO)); + final boolean emissive = quad.emissive(); + final boolean vanillaShade = quad.shadeMode() == ShadeMode.VANILLA; + final ChunkSectionLayer quadRenderLayer = quad.renderLayer(); + final ChunkSectionLayer renderLayer = quadRenderLayer == null ? defaultRenderLayer : quadRenderLayer; + final VertexConsumer vertexConsumer = getVertexConsumer(renderLayer); + + LightPipeline lightPipeline = ao ? this.smoothLightPipeline : this.flatLightPipeline; + + tintQuad(quad); + shadeQuad(quad, lightPipeline, emissive, vanillaShade); + copyLightData(quad); + bufferQuad(quad, vertexConsumer); + } + + private void copyLightData(MutableQuadViewImpl quad) { + for (int i = 0; i < 4; i++) { + quad.lightmap(i, this.quadLightData.lm[i]); + } + } + +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/ItemRenderContext.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/ItemRenderContext.java new file mode 100644 index 000000000..3448ad0a9 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/ItemRenderContext.java @@ -0,0 +1,176 @@ +package net.vulkanmod.render.chunk.build.frapi.render; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.MatrixUtil; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Supplier; + +import net.fabricmc.fabric.api.renderer.v1.mesh.MeshView; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; +import net.fabricmc.fabric.api.renderer.v1.render.FabricLayerRenderState; +import net.fabricmc.fabric.api.renderer.v1.render.RenderLayerHelper; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.chunk.ChunkSectionLayer; +import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.vulkanmod.mixin.render.frapi.ItemRendererAccessor; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.Sheets; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.ItemDisplayContext; +import net.vulkanmod.render.chunk.build.frapi.helper.ColorHelper; +import net.vulkanmod.render.chunk.build.frapi.mesh.MutableQuadViewImpl; +import org.jetbrains.annotations.Nullable; + + +/** + * Used during item buffering to support geometry added through {@link FabricLayerRenderState#emitter()}. + */ +public class ItemRenderContext extends AbstractRenderContext { + private static final int GLINT_COUNT = ItemStackRenderState.FoilType.values().length; + + private ItemDisplayContext itemDisplayContext; + private PoseStack matrixStack; + private MultiBufferSource vertexConsumerProvider; + private int lightmap; + private int[] tints; + + private RenderType defaultLayer; + private ItemStackRenderState.FoilType defaultGlint; + private boolean ignoreQuadGlint; + + private PoseStack.Pose specialGlintEntry; + private final VertexConsumer[] vertexConsumerCache = new VertexConsumer[3 * GLINT_COUNT]; + + public void renderModel(ItemDisplayContext itemDisplayContext, PoseStack matrixStack, MultiBufferSource bufferSource, int lightmap, int overlay, int[] tints, List modelQuads, MeshView mesh, RenderType renderType, ItemStackRenderState.FoilType foilType, boolean ignoreQuadGlint) { + this.itemDisplayContext = itemDisplayContext; + this.matrixStack = matrixStack; + this.vertexConsumerProvider = bufferSource; + this.lightmap = lightmap; + this.overlay = overlay; + this.tints = tints; + + defaultLayer = renderType; + defaultGlint = foilType; + this.ignoreQuadGlint = ignoreQuadGlint; + + bufferQuads(modelQuads, mesh); + + this.matrixStack = null; + this.vertexConsumerProvider = null; + this.tints = null; + + specialGlintEntry = null; + Arrays.fill(vertexConsumerCache, null); + } + + private void bufferQuads(List vanillaQuads, MeshView mesh) { + QuadEmitter emitter = getEmitter(); + + final int vanillaQuadCount = vanillaQuads.size(); + + for (int i = 0; i < vanillaQuadCount; i++) { + final BakedQuad q = vanillaQuads.get(i); + emitter.fromBakedQuad(q); + emitter.emit(); + } + + mesh.outputTo(emitter); + } + + @Override + protected void bufferQuad(MutableQuadViewImpl quad) { + final VertexConsumer vertexConsumer = getVertexConsumer(quad.renderLayer(), quad.glint()); + + tintQuad(quad); + shadeQuad(quad, quad.emissive()); + bufferQuad(quad, vertexConsumer); + } + + private void tintQuad(MutableQuadViewImpl quad) { + int tintIndex = quad.tintIndex(); + + if (tintIndex != -1 && tintIndex < tints.length) { + final int tint = tints[tintIndex]; + + for (int i = 0; i < 4; i++) { + quad.color(i, ColorHelper.multiplyColor(tint, quad.color(i))); + } + } + } + + private void shadeQuad(MutableQuadViewImpl quad, boolean emissive) { + if (emissive) { + for (int i = 0; i < 4; i++) { + quad.lightmap(i, LightTexture.FULL_BRIGHT); + } + } else { + final int lightmap = this.lightmap; + + for (int i = 0; i < 4; i++) { + quad.lightmap(i, ColorHelper.maxBrightness(quad.lightmap(i), lightmap)); + } + } + } + + private VertexConsumer getVertexConsumer(@Nullable ChunkSectionLayer quadRenderLayer, @Nullable ItemStackRenderState.FoilType quadGlint) { + RenderType layer; + ItemStackRenderState.FoilType glint; + + if (quadRenderLayer == null) { + layer = defaultLayer; + } else { + layer = RenderLayerHelper.getEntityBlockLayer(quadRenderLayer); + } + + if (ignoreQuadGlint || quadGlint == null) { + glint = defaultGlint; + } else { + glint = quadGlint; + } + + int cacheIndex; + + if (layer == Sheets.translucentItemSheet()) { + cacheIndex = 0; + } else if (layer == Sheets.cutoutBlockSheet()) { + cacheIndex = GLINT_COUNT; + } else { + cacheIndex = 2 * GLINT_COUNT; + } + + cacheIndex += glint.ordinal(); + VertexConsumer vertexConsumer = vertexConsumerCache[cacheIndex]; + + if (vertexConsumer == null) { + vertexConsumer = createVertexConsumer(layer, glint); + vertexConsumerCache[cacheIndex] = vertexConsumer; + } + + return vertexConsumer; + } + + private VertexConsumer createVertexConsumer(RenderType layer, ItemStackRenderState.FoilType glint) { + if (glint == ItemStackRenderState.FoilType.SPECIAL) { + if (specialGlintEntry == null) { + specialGlintEntry = matrixStack.last().copy(); + + if (itemDisplayContext == ItemDisplayContext.GUI) { + MatrixUtil.mulComponentWise(specialGlintEntry.pose(), 0.5F); + } else if (itemDisplayContext.firstPerson()) { + MatrixUtil.mulComponentWise(specialGlintEntry.pose(), 0.75F); + } + } + + return ItemRendererAccessor.getSpecialFoilBuffer(vertexConsumerProvider, layer, specialGlintEntry); + } + + return ItemRenderer.getFoilBuffer(vertexConsumerProvider, layer, true, glint != ItemStackRenderState.FoilType.NONE); + } + +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/MeshItemCommand.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/MeshItemCommand.java new file mode 100644 index 000000000..52acc30b1 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/MeshItemCommand.java @@ -0,0 +1,12 @@ +package net.vulkanmod.render.chunk.build.frapi.render; + +import com.mojang.blaze3d.vertex.PoseStack; +import java.util.List; +import net.fabricmc.fabric.api.renderer.v1.mesh.MeshView; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.minecraft.world.item.ItemDisplayContext; + +public record MeshItemCommand(PoseStack.Pose positionMatrix, ItemDisplayContext displayContext, int lightCoords, int overlayCoords, int outlineColor, int[] tintLayers, List quads, RenderType renderLayer, ItemStackRenderState.FoilType glintType, MeshView mesh) { +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/QuadToPosPipe.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/QuadToPosPipe.java new file mode 100644 index 000000000..151d073c8 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/QuadToPosPipe.java @@ -0,0 +1,26 @@ +package net.vulkanmod.render.chunk.build.frapi.render; + +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; +import org.joml.Matrix4fc; +import org.joml.Vector3f; +import org.joml.Vector3fc; + +import java.util.function.Consumer; + +public class QuadToPosPipe implements Consumer { + private final Consumer posConsumer; + private final Vector3f vec; + public Matrix4fc matrix; + + public QuadToPosPipe(Consumer posConsumer, Vector3f vec) { + this.posConsumer = posConsumer; + this.vec = vec; + } + + @Override + public void accept(QuadView quad) { + for (int i = 0; i < 4; i++) { + posConsumer.accept(quad.copyPos(i, vec).mulPosition(matrix)); + } + } +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/SimpleBlockRenderContext.java b/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/SimpleBlockRenderContext.java new file mode 100644 index 000000000..275738cfb --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/frapi/render/SimpleBlockRenderContext.java @@ -0,0 +1,119 @@ +package net.vulkanmod.render.chunk.build.frapi.render; +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.fabricmc.fabric.api.renderer.v1.render.BlockVertexConsumerProvider; +import net.minecraft.client.renderer.ItemBlockRenderTypes; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.BlockStateModel; +import net.minecraft.client.renderer.chunk.ChunkSectionLayer; +import net.minecraft.core.BlockPos; +import net.minecraft.util.ARGB; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; +import net.vulkanmod.render.chunk.build.frapi.helper.ColorHelper; +import net.vulkanmod.render.chunk.build.frapi.mesh.MutableQuadViewImpl; +import org.jetbrains.annotations.Nullable; + +public class SimpleBlockRenderContext extends AbstractRenderContext { + public static final ThreadLocal POOL = ThreadLocal.withInitial(SimpleBlockRenderContext::new); + + private final RandomSource random = RandomSource.create(); + + private BlockVertexConsumerProvider vertexConsumers; + private ChunkSectionLayer defaultRenderLayer; + private float red; + private float green; + private float blue; + private int light; + + @Nullable + private ChunkSectionLayer lastRenderLayer; + @Nullable + private VertexConsumer lastVertexConsumer; + + @Override + protected void bufferQuad(MutableQuadViewImpl quad) { + final ChunkSectionLayer quadRenderLayer = quad.renderLayer(); + final ChunkSectionLayer renderLayer = quadRenderLayer == null ? defaultRenderLayer : quadRenderLayer; + final VertexConsumer vertexConsumer; + + if (renderLayer == lastRenderLayer) { + vertexConsumer = lastVertexConsumer; + } else { + lastVertexConsumer = vertexConsumer = vertexConsumers.getBuffer(renderLayer); + lastRenderLayer = renderLayer; + } + + tintQuad(quad); + shadeQuad(quad, quad.emissive()); + bufferQuad(quad, vertexConsumer); + } + + private void tintQuad(MutableQuadViewImpl quad) { + if (quad.tintIndex() != -1) { + final float red = this.red; + final float green = this.green; + final float blue = this.blue; + + for (int i = 0; i < 4; i++) { + quad.color(i, ARGB.scaleRGB(quad.color(i), red, green, blue)); + } + } + } + + private void shadeQuad(MutableQuadViewImpl quad, boolean emissive) { + if (emissive) { + for (int i = 0; i < 4; i++) { + quad.lightmap(i, LightTexture.FULL_BRIGHT); + } + } else { + final int light = this.light; + + for (int i = 0; i < 4; i++) { + quad.lightmap(i, ColorHelper.maxLight(quad.lightmap(i), light)); + } + } + } + + public void bufferModel(PoseStack.Pose entry, BlockVertexConsumerProvider vertexConsumers, BlockStateModel model, float red, float green, float blue, int light, int overlay, BlockAndTintGetter blockView, BlockPos pos, BlockState state) { + matrices = entry; + this.overlay = overlay; + + this.vertexConsumers = vertexConsumers; + this.defaultRenderLayer = ItemBlockRenderTypes.getChunkRenderType(state); + this.red = Mth.clamp(red, 0, 1); + this.green = Mth.clamp(green, 0, 1); + this.blue = Mth.clamp(blue, 0, 1); + this.light = light; + + random.setSeed(42L); + + model.emitQuads(getEmitter(), blockView, pos, state, random, cullFace -> false); + + matrices = null; + this.vertexConsumers = null; + lastRenderLayer = null; + lastVertexConsumer = null; + } +} + diff --git a/src/main/java/net/vulkanmod/render/chunk/build/light/LightPipeline.java b/src/main/java/net/vulkanmod/render/chunk/build/light/LightPipeline.java index ba0fa8a7b..69d3c184e 100644 --- a/src/main/java/net/vulkanmod/render/chunk/build/light/LightPipeline.java +++ b/src/main/java/net/vulkanmod/render/chunk/build/light/LightPipeline.java @@ -2,7 +2,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.vulkanmod.render.model.quad.QuadView; +import net.vulkanmod.render.model.quad.ModelQuadView; import net.vulkanmod.render.chunk.build.light.data.QuadLightData; /** @@ -19,5 +19,5 @@ public interface LightPipeline { * @param lightFace The light face of the quad * @param shade True if the block is shaded by ambient occlusion */ - void calculate(QuadView quad, BlockPos pos, QuadLightData out, Direction cullFace, Direction lightFace, boolean shade); + void calculate(ModelQuadView quad, BlockPos pos, QuadLightData out, Direction cullFace, Direction lightFace, boolean shade); } diff --git a/src/main/java/net/vulkanmod/render/chunk/build/light/data/ArrayLightDataCache.java b/src/main/java/net/vulkanmod/render/chunk/build/light/data/ArrayLightDataCache.java index 1fbde68f7..3e23dcc5c 100644 --- a/src/main/java/net/vulkanmod/render/chunk/build/light/data/ArrayLightDataCache.java +++ b/src/main/java/net/vulkanmod/render/chunk/build/light/data/ArrayLightDataCache.java @@ -25,7 +25,7 @@ public ArrayLightDataCache() { } public void reset(BlockAndTintGetter blockAndTintGetter, int x, int y, int z) { - this.world = blockAndTintGetter; + this.region = blockAndTintGetter; this.xOffset = x - NEIGHBOR_BLOCK_RADIUS; this.yOffset = y - NEIGHBOR_BLOCK_RADIUS; @@ -34,6 +34,16 @@ public void reset(BlockAndTintGetter blockAndTintGetter, int x, int y, int z) { Arrays.fill(this.light, 0); } + public void reset(BlockAndTintGetter blockAndTintGetter, BlockPos origin) { + this.region = blockAndTintGetter; + + this.xOffset = origin.getX() - NEIGHBOR_BLOCK_RADIUS; + this.yOffset = origin.getY() - NEIGHBOR_BLOCK_RADIUS; + this.zOffset = origin.getZ() - NEIGHBOR_BLOCK_RADIUS; + + Arrays.fill(this.light, 0); + } + public void reset(SectionPos origin) { this.xOffset = origin.minBlockX() - NEIGHBOR_BLOCK_RADIUS; this.yOffset = origin.minBlockY() - NEIGHBOR_BLOCK_RADIUS; diff --git a/src/main/java/net/vulkanmod/render/chunk/build/light/data/LightDataAccess.java b/src/main/java/net/vulkanmod/render/chunk/build/light/data/LightDataAccess.java index ff0ad86d4..d2e532738 100644 --- a/src/main/java/net/vulkanmod/render/chunk/build/light/data/LightDataAccess.java +++ b/src/main/java/net/vulkanmod/render/chunk/build/light/data/LightDataAccess.java @@ -5,7 +5,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.LightLayer; -import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.shapes.VoxelShape; import net.vulkanmod.Initializer; @@ -16,10 +15,10 @@ /** * The light data cache is used to make accessing the light data and occlusion properties of blocks cheaper. The data * for each block is stored as an integer with packed fields in order to work around the lack of value types in Java. - * + *

* This code is not very pretty, but it does perform significantly faster than the vanilla implementation and has * good cache locality. - * + *

* Each integer contains the following fields: * - BL: World block light, encoded as a 4-bit unsigned integer * - SL: World sky light, encoded as a 4-bit unsigned integer @@ -29,7 +28,7 @@ * - OP: Block opacity test, true if opaque * - FO: Full cube opacity test, true if opaque full cube * - FC: Full cube test, true if full cube - * + *

* You can use the various static pack/unpack methods to extract these values in a usable format. */ public abstract class LightDataAccess { @@ -45,7 +44,7 @@ public abstract class LightDataAccess { private static final float AO_INV = 1.0f / 2048.0f; private final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); - protected BlockAndTintGetter world; + protected BlockAndTintGetter region; final boolean subBlockLighting; @@ -55,14 +54,14 @@ protected LightDataAccess() { public int get(int x, int y, int z, SimpleDirection d1, SimpleDirection d2) { return this.get(x + d1.getStepX() + d2.getStepX(), - y + d1.getStepY() + d2.getStepY(), - z + d1.getStepZ() + d2.getStepZ()); + y + d1.getStepY() + d2.getStepY(), + z + d1.getStepZ() + d2.getStepZ()); } public int get(int x, int y, int z, SimpleDirection dir) { return this.get(x + dir.getStepX(), - y + dir.getStepY(), - z + dir.getStepZ()); + y + dir.getStepY(), + z + dir.getStepZ()); } public int get(BlockPos pos, SimpleDirection dir) { @@ -81,19 +80,18 @@ public int get(BlockPos pos) { protected int compute(int x, int y, int z) { BlockPos pos = this.pos.set(x, y, z); + BlockState state = region.getBlockState(pos); - BlockState state = world.getBlockState(pos); - - boolean em = state.emissiveRendering(world, pos); + boolean em = state.emissiveRendering(region, pos); boolean op; - if(this.subBlockLighting) + if (this.subBlockLighting) op = state.canOcclude(); else - op = state.isViewBlocking(world, pos) && state.getLightBlock(world, pos) != 0; + op = state.isViewBlocking(region, pos) && state.getLightBlock() != 0; - boolean fo = state.isSolidRender(world, pos); - boolean fc = state.isCollisionShapeFullBlock(world, pos); + boolean fo = state.isSolidRender(); + boolean fc = state.isCollisionShapeFullBlock(region, pos); int lu = state.getLightEmission(); @@ -103,16 +101,25 @@ protected int compute(int x, int y, int z) { if (fo && lu == 0) { bl = 0; sl = 0; - } else { - bl = world.getBrightness(LightLayer.BLOCK, pos); - sl = world.getBrightness(LightLayer.SKY, pos); + } + else { + if (em) { + bl = region.getBrightness(LightLayer.BLOCK, pos); + sl = region.getBrightness(LightLayer.SKY, pos); + } + else { + int light = LevelRenderer.getLightColor(LevelRenderer.BrightnessGetter.DEFAULT, region, state, pos); + bl = LightTexture.block(light); + sl = LightTexture.sky(light); + } } // FIX: Do not apply AO from blocks that emit light float ao; if (lu == 0) { - ao = state.getShadeBrightness(world, pos); - } else { + ao = state.getShadeBrightness(region, pos); + } + else { ao = 1.0f; } @@ -121,12 +128,12 @@ protected int compute(int x, int y, int z) { bl = Math.max(bl, lu); int crs = (fo || fc) && lu == 0 && useAo ? 0xFF : 0; - if(!fo && op) { - VoxelShape shape = state.getShape(world, pos); - crs = ((VoxelShapeExtended)(shape)).getCornerOcclusion(); + if (!fo && op) { + VoxelShape shape = state.getShape(region, pos); + crs = ((VoxelShapeExtended) (shape)).getCornerOcclusion(); } - return packFC(fc) | packFO(fo) | packOP(op) | packEM(em) | packCO(crs) | packAO(ao) | packSL(sl) | packBL(bl); + return packFC(fc) | packFO(fo) | packOP(op) | packEM(em) | packCO(crs) | packAO(ao) | packSL(sl) | packBL(bl); } public static int packBL(int blockLight) { @@ -215,7 +222,7 @@ public static int getEmissiveLightmap(int word) { } } - public BlockAndTintGetter getWorld() { - return this.world; + public BlockAndTintGetter getRegion() { + return this.region; } } \ No newline at end of file diff --git a/src/main/java/net/vulkanmod/render/chunk/build/light/flat/FlatLightPipeline.java b/src/main/java/net/vulkanmod/render/chunk/build/light/flat/FlatLightPipeline.java index 2472ac4b8..b11f4e352 100644 --- a/src/main/java/net/vulkanmod/render/chunk/build/light/flat/FlatLightPipeline.java +++ b/src/main/java/net/vulkanmod/render/chunk/build/light/flat/FlatLightPipeline.java @@ -4,7 +4,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.vulkanmod.render.chunk.util.SimpleDirection; -import net.vulkanmod.render.model.quad.QuadView; +import net.vulkanmod.render.model.quad.ModelQuadView; import net.vulkanmod.render.chunk.build.light.data.LightDataAccess; import net.vulkanmod.render.chunk.build.light.LightPipeline; import net.vulkanmod.render.chunk.build.light.data.QuadLightData; @@ -29,7 +29,7 @@ public FlatLightPipeline(LightDataAccess lightCache) { } @Override - public void calculate(QuadView quad, BlockPos pos, QuadLightData out, Direction cullFace, Direction lightFace, boolean shade) { + public void calculate(ModelQuadView quad, BlockPos pos, QuadLightData out, Direction cullFace, Direction lightFace, boolean shade) { int lightmap; // To match vanilla behavior, use the cull face if it exists/is available @@ -47,7 +47,7 @@ public void calculate(QuadView quad, BlockPos pos, QuadLightData out, Direction } Arrays.fill(out.lm, lightmap); - Arrays.fill(out.br, this.lightCache.getWorld().getShade(lightFace, shade)); + Arrays.fill(out.br, this.lightCache.getRegion().getShade(lightFace, shade)); } private int getLightmap(BlockPos pos, Direction face) { diff --git a/src/main/java/net/vulkanmod/render/chunk/build/light/smooth/NewSmoothLightPipeline.java b/src/main/java/net/vulkanmod/render/chunk/build/light/smooth/NewSmoothLightPipeline.java index 32cdabcb9..503d27ff9 100644 --- a/src/main/java/net/vulkanmod/render/chunk/build/light/smooth/NewSmoothLightPipeline.java +++ b/src/main/java/net/vulkanmod/render/chunk/build/light/smooth/NewSmoothLightPipeline.java @@ -4,7 +4,7 @@ import net.minecraft.core.Direction; import net.minecraft.util.Mth; import net.vulkanmod.render.chunk.util.SimpleDirection; -import net.vulkanmod.render.model.quad.QuadView; +import net.vulkanmod.render.model.quad.ModelQuadView; import net.vulkanmod.render.chunk.build.light.data.LightDataAccess; import net.vulkanmod.render.chunk.build.light.LightPipeline; import net.vulkanmod.render.chunk.build.light.data.QuadLightData; @@ -42,7 +42,7 @@ public NewSmoothLightPipeline(LightDataAccess cache) { } @Override - public void calculate(QuadView quad, BlockPos pos, QuadLightData out, Direction cullFace, Direction lightFaceO, boolean shade) { + public void calculate(ModelQuadView quad, BlockPos pos, QuadLightData out, Direction cullFace, Direction lightFaceO, boolean shade) { this.updateCachedData(pos.asLong()); int flags = quad.getFlags(); @@ -85,7 +85,7 @@ private void applyAlignedFullFace(AoNeighborInfo neighborInfo, BlockPos pos, Sim * Calculates the light data for a grid-aligned quad that does not cover the entire block volume's face. * Flags: IS_ALIGNED, IS_PARTIAL */ - private void applyAlignedPartialFace(AoNeighborInfo neighborInfo, QuadView quad, BlockPos pos, SimpleDirection dir, QuadLightData out) { + private void applyAlignedPartialFace(AoNeighborInfo neighborInfo, ModelQuadView quad, BlockPos pos, SimpleDirection dir, QuadLightData out) { // TODO stair lighting is inconsistent // A solution might be an interpolation grid // this.self.calculatePartialAlignedFace(this.lightCache, pos, dir); @@ -104,13 +104,13 @@ private void applyAlignedPartialFace(AoNeighborInfo neighborInfo, QuadView quad, } /** - * This method is the same as {@link #applyNonParallelFace(AoNeighborInfo, QuadView, BlockPos, SimpleDirection, + * This method is the same as {@link #applyNonParallelFace(AoNeighborInfo, ModelQuadView, BlockPos, SimpleDirection, * QuadLightData)} but with the check for a depth of approximately 0 removed. If the quad is parallel but not * aligned, all of its vertices will have the same depth and this depth must be approximately greater than 0, * meaning the check for 0 will always return false. * Flags: !IS_ALIGNED, IS_PARALLEL */ - private void applyParallelFace(AoNeighborInfo neighborInfo, QuadView quad, BlockPos pos, SimpleDirection dir, QuadLightData out) { + private void applyParallelFace(AoNeighborInfo neighborInfo, ModelQuadView quad, BlockPos pos, SimpleDirection dir, QuadLightData out) { this.self.calculateSelfOcclusion(this.lightCache, pos, dir); for (int i = 0; i < 4; i++) { @@ -139,7 +139,7 @@ private void applyParallelFace(AoNeighborInfo neighborInfo, QuadView quad, Block /** * Flags: !IS_ALIGNED, !IS_PARALLEL */ - private void applyNonParallelFace(AoNeighborInfo neighborInfo, QuadView quad, BlockPos pos, SimpleDirection dir, QuadLightData out) { + private void applyNonParallelFace(AoNeighborInfo neighborInfo, ModelQuadView quad, BlockPos pos, SimpleDirection dir, QuadLightData out) { for (int i = 0; i < 4; i++) { // Clamp the vertex positions to the block's boundaries to prevent weird errors in lighting float cx = clamp(quad.getX(i)); @@ -229,7 +229,7 @@ private void applyInsetPartialFaceVertexSO(BlockPos pos, SimpleDirection dir, fl } private void applySidedBrightness(QuadLightData out, Direction face, boolean shade) { - float brightness = this.lightCache.getWorld().getShade(face, shade); + float brightness = this.lightCache.getRegion().getShade(face, shade); float[] br = out.br; for (int i = 0; i < br.length; i++) { diff --git a/src/main/java/net/vulkanmod/render/chunk/build/light/smooth/SmoothLightPipeline.java b/src/main/java/net/vulkanmod/render/chunk/build/light/smooth/SmoothLightPipeline.java index 62993e312..154eb0518 100644 --- a/src/main/java/net/vulkanmod/render/chunk/build/light/smooth/SmoothLightPipeline.java +++ b/src/main/java/net/vulkanmod/render/chunk/build/light/smooth/SmoothLightPipeline.java @@ -4,7 +4,7 @@ import net.minecraft.core.Direction; import net.minecraft.util.Mth; import net.vulkanmod.render.chunk.util.SimpleDirection; -import net.vulkanmod.render.model.quad.QuadView; +import net.vulkanmod.render.model.quad.ModelQuadView; import net.vulkanmod.render.chunk.build.light.data.LightDataAccess; import net.vulkanmod.render.chunk.build.light.LightPipeline; import net.vulkanmod.render.chunk.build.light.data.QuadLightData; @@ -67,7 +67,7 @@ public SmoothLightPipeline(LightDataAccess cache) { } @Override - public void calculate(QuadView quad, BlockPos pos, QuadLightData out, Direction cullFace, Direction lightFaceO, boolean shade) { + public void calculate(ModelQuadView quad, BlockPos pos, QuadLightData out, Direction cullFace, Direction lightFaceO, boolean shade) { this.updateCachedData(pos.asLong()); int flags = quad.getFlags(); @@ -110,7 +110,7 @@ private void applyAlignedFullFace(AoNeighborInfo neighborInfo, BlockPos pos, Sim * Calculates the light data for a grid-aligned quad that does not cover the entire block volume's face. * Flags: IS_ALIGNED, IS_PARTIAL */ - private void applyAlignedPartialFace(AoNeighborInfo neighborInfo, QuadView quad, BlockPos pos, SimpleDirection dir, QuadLightData out) { + private void applyAlignedPartialFace(AoNeighborInfo neighborInfo, ModelQuadView quad, BlockPos pos, SimpleDirection dir, QuadLightData out) { for (int i = 0; i < 4; i++) { // Clamp the vertex positions to the block's boundaries to prevent weird errors in lighting float cx = clamp(quad.getX(i)); @@ -124,13 +124,13 @@ private void applyAlignedPartialFace(AoNeighborInfo neighborInfo, QuadView quad, } /** - * This method is the same as {@link #applyNonParallelFace(AoNeighborInfo, QuadView, BlockPos, SimpleDirection, + * This method is the same as {@link #applyNonParallelFace(AoNeighborInfo, ModelQuadView, BlockPos, SimpleDirection, * QuadLightData)} but with the check for a depth of approximately 0 removed. If the quad is parallel but not * aligned, all of its vertices will have the same depth and this depth must be approximately greater than 0, * meaning the check for 0 will always return false. * Flags: !IS_ALIGNED, IS_PARALLEL */ - private void applyParallelFace(AoNeighborInfo neighborInfo, QuadView quad, BlockPos pos, SimpleDirection dir, QuadLightData out) { + private void applyParallelFace(AoNeighborInfo neighborInfo, ModelQuadView quad, BlockPos pos, SimpleDirection dir, QuadLightData out) { for (int i = 0; i < 4; i++) { // Clamp the vertex positions to the block's boundaries to prevent weird errors in lighting float cx = clamp(quad.getX(i)); @@ -157,7 +157,7 @@ private void applyParallelFace(AoNeighborInfo neighborInfo, QuadView quad, Block /** * Flags: !IS_ALIGNED, !IS_PARALLEL */ - private void applyNonParallelFace(AoNeighborInfo neighborInfo, QuadView quad, BlockPos pos, SimpleDirection dir, QuadLightData out) { + private void applyNonParallelFace(AoNeighborInfo neighborInfo, ModelQuadView quad, BlockPos pos, SimpleDirection dir, QuadLightData out) { for (int i = 0; i < 4; i++) { // Clamp the vertex positions to the block's boundaries to prevent weird errors in lighting float cx = clamp(quad.getX(i)); @@ -220,7 +220,7 @@ private void applyInsetPartialFaceVertex(BlockPos pos, SimpleDirection dir, floa } private void applySidedBrightness(QuadLightData out, Direction face, boolean shade) { - float brightness = this.lightCache.getWorld().getShade(face, shade); + float brightness = this.lightCache.getRegion().getShade(face, shade); float[] br = out.br; for (int i = 0; i < br.length; i++) { diff --git a/src/main/java/net/vulkanmod/render/chunk/build/renderer/BlockRenderer.java b/src/main/java/net/vulkanmod/render/chunk/build/renderer/BlockRenderer.java new file mode 100644 index 000000000..0c3607e71 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/renderer/BlockRenderer.java @@ -0,0 +1,151 @@ +package net.vulkanmod.render.chunk.build.renderer; + +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.fabricmc.fabric.api.renderer.v1.mesh.ShadeMode; +import net.fabricmc.fabric.api.util.TriState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.ItemBlockRenderTypes; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.BlockStateModel; +import net.minecraft.client.renderer.chunk.ChunkSectionLayer; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.SingleThreadedRandomSource; +import net.minecraft.world.phys.Vec3; +import net.vulkanmod.Initializer; +import net.vulkanmod.render.chunk.build.frapi.mesh.MutableQuadViewImpl; +import net.vulkanmod.render.chunk.build.frapi.render.AbstractBlockRenderContext; +import net.vulkanmod.render.chunk.build.light.LightPipeline; +import net.vulkanmod.render.chunk.build.light.data.QuadLightData; +import net.vulkanmod.render.chunk.build.thread.BuilderResources; +import net.vulkanmod.render.chunk.cull.QuadFacing; +import net.vulkanmod.render.model.quad.QuadUtils; +import net.vulkanmod.render.model.quad.ModelQuadView; +import net.vulkanmod.render.vertex.TerrainBufferBuilder; +import net.vulkanmod.render.vertex.TerrainBuilder; +import net.vulkanmod.render.vertex.TerrainRenderType; +import net.vulkanmod.render.vertex.format.I32_SNorm; +import net.vulkanmod.vulkan.util.ColorUtil; +import org.joml.Vector3f; + +public class BlockRenderer extends AbstractBlockRenderContext { + private Vector3f pos; + + private BuilderResources resources; + private TerrainBuilder terrainBuilder; + + final boolean backFaceCulling = Initializer.CONFIG.backFaceCulling; + + private TerrainRenderType renderType; + + public void setResources(BuilderResources resources) { + this.resources = resources; + } + + public BlockRenderer(LightPipeline flatLightPipeline, LightPipeline smoothLightPipeline) { + super(); + this.setupLightPipelines(flatLightPipeline, smoothLightPipeline); + + this.random = new SingleThreadedRandomSource(42L); + } + + public void renderBlock(BlockState blockState, BlockPos blockPos, Vector3f pos) { + this.pos = pos; + this.blockPos = blockPos; + this.blockState = blockState; + this.random.setSeed(blockState.getSeed(blockPos)); + + TerrainRenderType renderType = TerrainRenderType.get(ItemBlockRenderTypes.getChunkRenderType(blockState)); + renderType = TerrainRenderType.getRemapped(renderType); + this.renderType = renderType; + this.terrainBuilder = this.resources.builderPack.builder(renderType); + this.terrainBuilder.setBlockAttributes(blockState); + + BlockStateModel model = Minecraft.getInstance().getBlockRenderer().getBlockModel(blockState); + + BlockAndTintGetter renderRegion = this.renderRegion; + Vec3 offset = blockState.getOffset(blockPos); + pos.add((float) offset.x, (float) offset.y, (float) offset.z); + + this.prepareForBlock(blockState, blockPos, blockState.getLightEmission() == 0); + + model.emitQuads(this.getEmitter(), renderRegion, blockPos, blockState, this.random, this::isFaceCulled); + } + + @Override + protected VertexConsumer getVertexConsumer(ChunkSectionLayer layer) { + return null; + } + + protected void endRenderQuad(MutableQuadViewImpl quad) { + final TriState aoMode = quad.ambientOcclusion(); + final boolean ao = this.useAO && (aoMode == TriState.TRUE || (aoMode == TriState.DEFAULT && this.defaultAO)); + final boolean emissive = quad.emissive(); + final boolean vanillaShade = quad.shadeMode() == ShadeMode.VANILLA; + + TerrainBuilder terrainBuilder = getBufferBuilder(quad.renderLayer()); + + LightPipeline lightPipeline = ao ? this.smoothLightPipeline : this.flatLightPipeline; + + tintQuad(quad); + shadeQuad(quad, lightPipeline, emissive, vanillaShade); + bufferQuad(terrainBuilder, this.pos, quad, this.quadLightData); + } + + private TerrainBuilder getBufferBuilder(ChunkSectionLayer layer) { + if (layer == null) { + return this.terrainBuilder; + } else { + TerrainRenderType renderType = TerrainRenderType.get(layer); + renderType = TerrainRenderType.getRemapped(renderType); + TerrainBuilder bufferBuilder = this.resources.builderPack.builder(renderType); + bufferBuilder.setBlockAttributes(this.blockState); + + return bufferBuilder; + } + } + + public void bufferQuad(TerrainBuilder terrainBuilder, Vector3f pos, ModelQuadView quad, QuadLightData quadLightData) { + QuadFacing quadFacing = quad.getQuadFacing(); + + if (renderType == TerrainRenderType.TRANSLUCENT || !this.backFaceCulling) { + quadFacing = QuadFacing.UNDEFINED; + } + + TerrainBufferBuilder bufferBuilder = terrainBuilder.getBufferBuilder(quadFacing.ordinal()); + + int packedNormal = quad.getNormal(); + + float[] brightnessArr = quadLightData.br; + int[] lights = quadLightData.lm; + + // Rotate triangles if needed to fix AO anisotropy + int idx = QuadUtils.getIterationStartIdx(brightnessArr, lights); + + bufferBuilder.ensureCapacity(); + + for (byte i = 0; i < 4; ++i) { + final float x = pos.x() + quad.getX(idx); + final float y = pos.y() + quad.getY(idx); + final float z = pos.z() + quad.getZ(idx); + + final int quadColor = quad.getColor(idx); + + int color = ColorUtil.ARGB.toRGBA(quadColor); + + final int light = lights[idx]; + final float u = quad.getU(idx); + final float v = quad.getV(idx); + + bufferBuilder.vertex(x, y, z, color, u, v, light, packedNormal); + + idx = (idx + 1) & 0b11; + } + + } + +} + diff --git a/src/main/java/net/vulkanmod/render/chunk/build/renderer/DefaultFluidRenderers.java b/src/main/java/net/vulkanmod/render/chunk/build/renderer/DefaultFluidRenderers.java new file mode 100644 index 000000000..0fbbe5415 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/renderer/DefaultFluidRenderers.java @@ -0,0 +1,17 @@ +package net.vulkanmod.render.chunk.build.renderer; + +import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; +import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler; + +public abstract class DefaultFluidRenderers { + + private static final ReferenceOpenHashSet set = new ReferenceOpenHashSet<>(); + + public static void add(FluidRenderHandler handler) { + set.add(handler); + } + + public static boolean has(FluidRenderHandler handler) { + return set.contains(handler); + } +} diff --git a/src/main/java/net/vulkanmod/render/chunk/build/LiquidRenderer.java b/src/main/java/net/vulkanmod/render/chunk/build/renderer/FluidRenderer.java similarity index 83% rename from src/main/java/net/vulkanmod/render/chunk/build/LiquidRenderer.java rename to src/main/java/net/vulkanmod/render/chunk/build/renderer/FluidRenderer.java index 4ae8eca4a..f29acae11 100644 --- a/src/main/java/net/vulkanmod/render/chunk/build/LiquidRenderer.java +++ b/src/main/java/net/vulkanmod/render/chunk/build/renderer/FluidRenderer.java @@ -1,8 +1,11 @@ -package net.vulkanmod.render.chunk.build; +package net.vulkanmod.render.chunk.build.renderer; +import com.mojang.blaze3d.vertex.VertexConsumer; import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler; import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry; +import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRendering; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -20,16 +23,18 @@ import net.vulkanmod.render.chunk.build.light.LightPipeline; import net.vulkanmod.render.chunk.build.light.data.QuadLightData; import net.vulkanmod.render.chunk.build.thread.BuilderResources; +import net.vulkanmod.render.chunk.cull.QuadFacing; import net.vulkanmod.render.chunk.util.Util; import net.vulkanmod.render.model.quad.ModelQuad; import net.vulkanmod.render.model.quad.ModelQuadFlags; import net.vulkanmod.render.model.quad.QuadUtils; import net.vulkanmod.render.vertex.TerrainBufferBuilder; -import net.vulkanmod.render.vertex.VertexUtil; +import net.vulkanmod.render.vertex.TerrainRenderType; +import net.vulkanmod.render.vertex.format.I32_SNorm; import net.vulkanmod.vulkan.util.ColorUtil; import org.joml.Vector3f; -public class LiquidRenderer { +public class FluidRenderer implements FluidRendering.DefaultRenderer { private static final float MAX_FLUID_HEIGHT = 0.8888889F; private final BlockPos.MutableBlockPos mBlockPos = new BlockPos.MutableBlockPos(); @@ -38,21 +43,41 @@ public class LiquidRenderer { BuilderResources resources; + private final LightPipeline smoothLightPipeline; + private final LightPipeline flatLightPipeline; + private final int[] quadColors = new int[4]; + public FluidRenderer(LightPipeline flatLightPipeline, LightPipeline smoothLightPipeline) { + this.smoothLightPipeline = smoothLightPipeline; + this.flatLightPipeline = flatLightPipeline; + } + public void setResources(BuilderResources resources) { this.resources = resources; } - public void renderLiquid(BlockState blockState, FluidState fluidState, BlockPos blockPos, TerrainBufferBuilder vertexConsumer) { - tessellate(blockState, fluidState, blockPos, vertexConsumer); + public void renderLiquid(BlockState blockState, FluidState fluidState, BlockPos blockPos) { + FluidRenderHandler handler = FluidRenderHandlerRegistry.INSTANCE.get(fluidState.getType()); + + TerrainRenderType renderType = TerrainRenderType.get(ItemBlockRenderTypes.getRenderLayer(fluidState)); + renderType = TerrainRenderType.getRemapped(renderType); + TerrainBufferBuilder bufferBuilder = this.resources.builderPack.builder(renderType).getBufferBuilder(QuadFacing.UNDEFINED.ordinal()); + + // Fallback to water/lava in case there's no handler + if (handler == null) { + boolean isLava = fluidState.is(FluidTags.LAVA); + handler = FluidRenderHandlerRegistry.INSTANCE.get(isLava ? Fluids.LAVA : Fluids.WATER); + } + + FluidRendering.render(handler, this.resources.getRegion(),blockPos, bufferBuilder, blockState, fluidState, this); } private boolean isFaceOccludedByState(BlockGetter blockGetter, float h, Direction direction, BlockPos blockPos, BlockState blockState) { - mBlockPos.set(blockPos).offset(Direction.DOWN.getNormal()); + mBlockPos.set(blockPos).offset(Direction.DOWN.getUnitVec3i()); if (blockState.canOcclude()) { - VoxelShape occlusionShape = blockState.getOcclusionShape(blockGetter, mBlockPos); + VoxelShape occlusionShape = blockState.getOcclusionShape(); if (occlusionShape == Shapes.block()) { return direction != Direction.UP; @@ -61,7 +86,7 @@ private boolean isFaceOccludedByState(BlockGetter blockGetter, float h, Directio } VoxelShape voxelShape = Shapes.box(0.0, 0.0, 0.0, 1.0, h, 1.0); - return Shapes.blockOccudes(voxelShape, occlusionShape, direction); + return Shapes.blockOccludes(voxelShape, occlusionShape, direction); } else { return false; } @@ -85,12 +110,14 @@ public BlockState getAdjBlockState(BlockAndTintGetter blockAndTintGetter, int x, return blockAndTintGetter.getBlockState(mBlockPos); } - public void tessellate(BlockState blockState, FluidState fluidState, BlockPos blockPos, TerrainBufferBuilder vertexConsumer) { - BlockAndTintGetter region = this.resources.region; + public void render(FluidRenderHandler handler, BlockAndTintGetter world, BlockPos pos, VertexConsumer vertexConsumer, BlockState blockState, FluidState fluidState) { + render(handler, blockState, fluidState, pos, (TerrainBufferBuilder) vertexConsumer); + } - final FluidRenderHandler handler = getFluidRenderHandler(fluidState); - int color = handler.getFluidColor(region, blockPos, fluidState); + public void render(FluidRenderHandler handler, BlockState blockState, FluidState fluidState, BlockPos blockPos, TerrainBufferBuilder bufferBuilder) { + BlockAndTintGetter region = this.resources.getRegion(); + int color = handler.getFluidColor(region, blockPos, fluidState); TextureAtlasSprite[] sprites = handler.getFluidSprites(region, blockPos, fluidState); float r = ColorUtil.ARGB.unpackR(color); @@ -102,7 +129,7 @@ public void tessellate(BlockState blockState, FluidState fluidState, BlockPos bl final int posZ = blockPos.getZ(); boolean useAO = blockState.getLightEmission() == 0 && Minecraft.useAmbientOcclusion(); - LightPipeline lightPipeline = useAO ? this.resources.smoothLightPipeline : this.resources.flatLightPipeline; + LightPipeline lightPipeline = useAO ? this.smoothLightPipeline : this.flatLightPipeline; BlockState downState = getAdjBlockState(region, posX, posY, posZ, Direction.DOWN); BlockState upState = getAdjBlockState(region, posX, posY, posZ, Direction.UP); @@ -137,14 +164,14 @@ public void tessellate(BlockState blockState, FluidState fluidState, BlockPos bl seHeight = 1.0F; swHeight = 1.0F; } else { - float s = this.getHeight(region, fluid, mBlockPos.set(blockPos).offset(Direction.NORTH.getNormal()), northState); - float t = this.getHeight(region, fluid, mBlockPos.set(blockPos).offset(Direction.SOUTH.getNormal()), southState); - float u = this.getHeight(region, fluid, mBlockPos.set(blockPos).offset(Direction.EAST.getNormal()), eastState); - float v = this.getHeight(region, fluid, mBlockPos.set(blockPos).offset(Direction.WEST.getNormal()), westState); - neHeight = this.calculateAverageHeight(region, fluid, height, s, u, mBlockPos.set(blockPos).offset(Direction.NORTH.getNormal()).offset(Direction.EAST.getNormal())); - nwHeight = this.calculateAverageHeight(region, fluid, height, s, v, mBlockPos.set(blockPos).offset(Direction.NORTH.getNormal()).offset(Direction.WEST.getNormal())); - seHeight = this.calculateAverageHeight(region, fluid, height, t, u, mBlockPos.set(blockPos).offset(Direction.SOUTH.getNormal()).offset(Direction.EAST.getNormal())); - swHeight = this.calculateAverageHeight(region, fluid, height, t, v, mBlockPos.set(blockPos).offset(Direction.SOUTH.getNormal()).offset(Direction.WEST.getNormal())); + float s = this.getHeight(region, fluid, mBlockPos.set(blockPos).offset(Direction.NORTH.getUnitVec3i()), northState); + float t = this.getHeight(region, fluid, mBlockPos.set(blockPos).offset(Direction.SOUTH.getUnitVec3i()), southState); + float u = this.getHeight(region, fluid, mBlockPos.set(blockPos).offset(Direction.EAST.getUnitVec3i()), eastState); + float v = this.getHeight(region, fluid, mBlockPos.set(blockPos).offset(Direction.WEST.getUnitVec3i()), westState); + neHeight = this.calculateAverageHeight(region, fluid, height, s, u, mBlockPos.set(blockPos).offset(Direction.NORTH.getUnitVec3i()).offset(Direction.EAST.getUnitVec3i())); + nwHeight = this.calculateAverageHeight(region, fluid, height, s, v, mBlockPos.set(blockPos).offset(Direction.NORTH.getUnitVec3i()).offset(Direction.WEST.getUnitVec3i())); + seHeight = this.calculateAverageHeight(region, fluid, height, t, u, mBlockPos.set(blockPos).offset(Direction.SOUTH.getUnitVec3i()).offset(Direction.EAST.getUnitVec3i())); + swHeight = this.calculateAverageHeight(region, fluid, height, t, v, mBlockPos.set(blockPos).offset(Direction.SOUTH.getUnitVec3i()).offset(Direction.WEST.getUnitVec3i())); } float x0 = (posX & 15); @@ -214,10 +241,10 @@ public void tessellate(BlockState blockState, FluidState fluidState, BlockPos bl updateQuad(this.modelQuad, blockPos, lightPipeline, Direction.UP); updateColor(r, g, b, brightness); - putQuad(modelQuad, vertexConsumer, x0, y0, z0, false); + putQuad(modelQuad, bufferBuilder, x0, y0, z0, false); if (fluidState.shouldRenderBackwardUpFace(region, blockPos.above())) { - putQuad(modelQuad, vertexConsumer, x0, y0, z0, true); + putQuad(modelQuad, bufferBuilder, x0, y0, z0, true); } } @@ -240,8 +267,7 @@ public void tessellate(BlockState blockState, FluidState fluidState, BlockPos bl updateQuad(this.modelQuad, blockPos, lightPipeline, Direction.DOWN); updateColor(r, g, b, brightness); - putQuad(modelQuad, vertexConsumer, x0, y0, z0, false); - + putQuad(modelQuad, bufferBuilder, x0, y0, z0, false); } modelQuad.setFlags(ModelQuadFlags.IS_PARALLEL | ModelQuadFlags.IS_ALIGNED); @@ -347,26 +373,15 @@ public void tessellate(BlockState blockState, FluidState fluidState, BlockPos bl updateQuad(this.modelQuad, blockPos, lightPipeline, direction); updateColor(r, g, b, brightness); - putQuad(modelQuad, vertexConsumer, x0, y0, z0, false); + putQuad(modelQuad, bufferBuilder, x0, y0, z0, false); if (!isOverlay) { - putQuad(modelQuad, vertexConsumer, x0, y0, z0, true); + putQuad(modelQuad, bufferBuilder, x0, y0, z0, true); } } } - private static FluidRenderHandler getFluidRenderHandler(FluidState fluidState) { - FluidRenderHandler handler = FluidRenderHandlerRegistry.INSTANCE.get(fluidState.getType()); - - // Fallback to water in case no handler was found - if (handler == null) { - handler = FluidRenderHandlerRegistry.INSTANCE.get(Fluids.WATER); - } - - return handler; - } - private float calculateAverageHeight(BlockAndTintGetter blockAndTintGetter, Fluid fluid, float f, float g, float h, BlockPos blockPos) { if (!(h >= 1.0F) && !(g >= 1.0F)) { float[] fs = new float[2]; @@ -407,7 +422,7 @@ private float getHeight(BlockAndTintGetter blockAndTintGetter, Fluid fluid, Bloc private float getHeight(BlockAndTintGetter blockAndTintGetter, Fluid fluid, BlockPos blockPos, BlockState adjBlockState) { FluidState adjFluidState = adjBlockState.getFluidState(); if (fluid.isSame(adjFluidState.getType())) { - BlockState blockState2 = blockAndTintGetter.getBlockState(blockPos.offset(Direction.UP.getNormal())); + BlockState blockState2 = blockAndTintGetter.getBlockState(blockPos.offset(Direction.UP.getUnitVec3i())); return fluid.isSame(blockState2.getFluidState().getType()) ? 1.0F : adjFluidState.getOwnHeight(); } else { return !adjBlockState.isSolid() ? 0.0F : -1.0f; @@ -420,7 +435,7 @@ private int calculateNormal(ModelQuad quad) { .cross(quad.getX(3), quad.getY(3), quad.getZ(3)); normal.normalize(); - return VertexUtil.packNormal(normal.x(), normal.y(), normal.z()); + return I32_SNorm.packNormal(normal.x(), normal.y(), normal.z()); } private void putQuad(ModelQuad quad, TerrainBufferBuilder bufferBuilder, float xOffset, float yOffset, float zOffset, boolean flip) { @@ -455,11 +470,8 @@ private void setVertex(ModelQuad quad, int i, float x, float y, float z, float u quad.setV(i, v); } - private void updateQuad(ModelQuad quad, BlockPos blockPos, - LightPipeline lightPipeline, Direction dir) { - + private void updateQuad(ModelQuad quad, BlockPos blockPos, LightPipeline lightPipeline, Direction dir) { lightPipeline.calculate(quad, blockPos, resources.quadLightData, null, dir, false); - } private void updateColor(float r, float g, float b, float brightness) { diff --git a/src/main/java/net/vulkanmod/render/chunk/build/task/BuildTask.java b/src/main/java/net/vulkanmod/render/chunk/build/task/BuildTask.java index 6c104faa9..0da19e2e1 100644 --- a/src/main/java/net/vulkanmod/render/chunk/build/task/BuildTask.java +++ b/src/main/java/net/vulkanmod/render/chunk/build/task/BuildTask.java @@ -1,8 +1,8 @@ package net.vulkanmod.render.chunk.build.task; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.client.renderer.blockentity.state.BlockEntityRenderState; import net.minecraft.client.renderer.chunk.VisGraph; import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.RenderShape; @@ -13,13 +13,14 @@ import net.vulkanmod.Initializer; import net.vulkanmod.render.chunk.RenderSection; import net.vulkanmod.render.chunk.WorldRenderer; -import net.vulkanmod.render.chunk.build.BlockRenderer; -import net.vulkanmod.render.chunk.build.LiquidRenderer; +import net.vulkanmod.render.chunk.build.renderer.BlockRenderer; +import net.vulkanmod.render.chunk.build.renderer.FluidRenderer; import net.vulkanmod.render.chunk.build.RenderRegion; import net.vulkanmod.render.chunk.build.UploadBuffer; import net.vulkanmod.render.chunk.build.thread.BuilderResources; import net.vulkanmod.render.chunk.build.thread.ThreadBuilderPack; -import net.vulkanmod.render.vertex.TerrainBufferBuilder; +import net.vulkanmod.render.chunk.cull.QuadFacing; +import net.vulkanmod.render.vertex.TerrainBuilder; import net.vulkanmod.render.vertex.TerrainRenderType; import org.jetbrains.annotations.Nullable; import org.joml.Vector3f; @@ -94,7 +95,7 @@ private CompileResult compile(float camX, float camY, float camZ, BuilderResourc BlockRenderer blockRenderer = builderResources.blockRenderer; - LiquidRenderer liquidRenderer = builderResources.liquidRenderer; + FluidRenderer fluidRenderer = builderResources.fluidRenderer; BlockPos.MutableBlockPos blockPos = new BlockPos.MutableBlockPos(); @@ -104,7 +105,7 @@ private CompileResult compile(float camX, float camY, float camZ, BuilderResourc blockPos.set(section.xOffset() + x, section.yOffset() + y, section.zOffset() + z); BlockState blockState = this.region.getBlockState(blockPos); - if (blockState.isSolidRender(this.region, blockPos)) { + if (blockState.isSolidRender()) { visGraph.setOpaque(blockPos); } @@ -116,44 +117,34 @@ private CompileResult compile(float camX, float camY, float camZ, BuilderResourc } FluidState fluidState = blockState.getFluidState(); - TerrainRenderType renderType; - TerrainBufferBuilder bufferBuilder; if (!fluidState.isEmpty()) { - renderType = TerrainRenderType.get(ItemBlockRenderTypes.getRenderLayer(fluidState)); - - bufferBuilder = getBufferBuilder(bufferBuilders, renderType); - bufferBuilder.setBlockAttributes(blockState); - - liquidRenderer.renderLiquid(blockState, fluidState, blockPos, bufferBuilder); + fluidRenderer.renderLiquid(blockState, fluidState, blockPos); } if (blockState.getRenderShape() == RenderShape.MODEL) { - renderType = TerrainRenderType.get(ItemBlockRenderTypes.getChunkRenderType(blockState)); - - bufferBuilder = getBufferBuilder(bufferBuilders, renderType); - bufferBuilder.setBlockAttributes(blockState); - pos.set(blockPos.getX() & 15, blockPos.getY() & 15, blockPos.getZ() & 15); - blockRenderer.renderBlock(blockState, blockPos, pos, bufferBuilder); + blockRenderer.renderBlock(blockState, blockPos, pos); } } } } - TerrainBufferBuilder translucentBufferBuilder = bufferBuilders.builder(TerrainRenderType.TRANSLUCENT); - if (!translucentBufferBuilder.isCurrentBatchEmpty()) { - translucentBufferBuilder.setupQuadSortingPoints(); - translucentBufferBuilder.setupQuadSorting(camX - (float) startBlockPos.getX(), camY - (float) startBlockPos.getY(), camZ - (float) startBlockPos.getZ()); - compileResult.transparencyState = translucentBufferBuilder.getSortState(); + TerrainBuilder trasnlucentTerrainBuilder = bufferBuilders.builder(TerrainRenderType.TRANSLUCENT); + if (trasnlucentTerrainBuilder.getBufferBuilder(QuadFacing.UNDEFINED.ordinal()).getVertices() > 0) { + trasnlucentTerrainBuilder.setupQuadSortingPoints(); + trasnlucentTerrainBuilder.setupQuadSorting(camX - (float) startBlockPos.getX(), camY - (float) startBlockPos.getY(), camZ - (float) startBlockPos.getZ()); + compileResult.transparencyState = trasnlucentTerrainBuilder.getSortState(); } for (TerrainRenderType renderType : TerrainRenderType.VALUES) { - TerrainBufferBuilder.RenderedBuffer renderedBuffer = bufferBuilders.builder(renderType).end(); - if (renderedBuffer != null) { - UploadBuffer uploadBuffer = new UploadBuffer(renderedBuffer); - compileResult.renderedLayers.put(renderType, uploadBuffer); - renderedBuffer.release(); - } + TerrainBuilder builder = bufferBuilders.builder(renderType); + + TerrainBuilder.DrawState drawState = builder.endDrawing(); + + UploadBuffer uploadBuffer = new UploadBuffer(builder, drawState); + compileResult.renderedLayers.put(renderType, uploadBuffer); + + builder.clear(); } compileResult.visibilitySet = visGraph.resolve(); @@ -163,12 +154,12 @@ private CompileResult compile(float camX, float camY, float camZ, BuilderResourc private void setupBufferBuilders(ThreadBuilderPack builderPack) { for (TerrainRenderType renderType : TerrainRenderType.VALUES) { - TerrainBufferBuilder bufferBuilder = builderPack.builder(renderType); + TerrainBuilder bufferBuilder = builderPack.builder(renderType); bufferBuilder.begin(); } } - private TerrainBufferBuilder getBufferBuilder(ThreadBuilderPack bufferBuilders, TerrainRenderType renderType) { + private TerrainBuilder getTerrainBuilder(ThreadBuilderPack bufferBuilders, TerrainRenderType renderType) { renderType = compactRenderTypes(renderType); return bufferBuilders.builder(renderType); } @@ -191,10 +182,10 @@ private TerrainRenderType compactRenderTypes(TerrainRenderType renderType) { } private void handleBlockEntity(CompileResult compileResult, E blockEntity) { - BlockEntityRenderer blockEntityRenderer = Minecraft.getInstance().getBlockEntityRenderDispatcher().getRenderer(blockEntity); + BlockEntityRenderer blockEntityRenderer = Minecraft.getInstance().getBlockEntityRenderDispatcher().getRenderer(blockEntity); if (blockEntityRenderer != null) { compileResult.blockEntities.add(blockEntity); - if (blockEntityRenderer.shouldRenderOffScreen(blockEntity)) { + if (blockEntityRenderer.shouldRenderOffScreen()) { compileResult.globalBlockEntities.add(blockEntity); } } diff --git a/src/main/java/net/vulkanmod/render/chunk/build/task/ChunkTask.java b/src/main/java/net/vulkanmod/render/chunk/build/task/ChunkTask.java index 13d416da6..c1acc33df 100644 --- a/src/main/java/net/vulkanmod/render/chunk/build/task/ChunkTask.java +++ b/src/main/java/net/vulkanmod/render/chunk/build/task/ChunkTask.java @@ -2,7 +2,6 @@ import net.vulkanmod.render.chunk.RenderSection; import net.vulkanmod.render.chunk.build.RenderRegion; -import net.vulkanmod.render.chunk.build.TaskDispatcher; import net.vulkanmod.render.chunk.build.thread.BuilderResources; import java.util.concurrent.atomic.AtomicBoolean; diff --git a/src/main/java/net/vulkanmod/render/chunk/build/task/CompiledSection.java b/src/main/java/net/vulkanmod/render/chunk/build/task/CompiledSection.java index c93de3a3c..e233ab0a2 100644 --- a/src/main/java/net/vulkanmod/render/chunk/build/task/CompiledSection.java +++ b/src/main/java/net/vulkanmod/render/chunk/build/task/CompiledSection.java @@ -3,7 +3,6 @@ import com.google.common.collect.Lists; import net.minecraft.world.level.block.entity.BlockEntity; import net.vulkanmod.render.vertex.QuadSorter; -import net.vulkanmod.render.vertex.TerrainBufferBuilder; import org.jetbrains.annotations.Nullable; import java.util.List; diff --git a/src/main/java/net/vulkanmod/render/chunk/build/task/SortTransparencyTask.java b/src/main/java/net/vulkanmod/render/chunk/build/task/SortTransparencyTask.java index 5f804c1a5..f6d1a72d6 100644 --- a/src/main/java/net/vulkanmod/render/chunk/build/task/SortTransparencyTask.java +++ b/src/main/java/net/vulkanmod/render/chunk/build/task/SortTransparencyTask.java @@ -7,7 +7,7 @@ import net.vulkanmod.render.chunk.build.thread.BuilderResources; import net.vulkanmod.render.chunk.build.thread.ThreadBuilderPack; import net.vulkanmod.render.vertex.QuadSorter; -import net.vulkanmod.render.vertex.TerrainBufferBuilder; +import net.vulkanmod.render.vertex.TerrainBuilder; import net.vulkanmod.render.vertex.TerrainRenderType; public class SortTransparencyTask extends ChunkTask { @@ -35,21 +35,24 @@ public Result runTask(BuilderResources context) { CompiledSection compiledSection = this.section.getCompiledSection(); QuadSorter.SortState transparencyState = compiledSection.transparencyState; - TerrainBufferBuilder bufferBuilder = builderPack.builder(TerrainRenderType.TRANSLUCENT); + TerrainBuilder bufferBuilder = builderPack.builder(TerrainRenderType.TRANSLUCENT); bufferBuilder.begin(); bufferBuilder.restoreSortState(transparencyState); bufferBuilder.setupQuadSorting(x - (float) this.section.xOffset(), y - (float) this.section.yOffset(), z - (float) this.section.zOffset()); - TerrainBufferBuilder.RenderedBuffer renderedBuffer = bufferBuilder.end(); + TerrainBuilder.DrawState drawState = bufferBuilder.endDrawing(); CompileResult compileResult = new CompileResult(this.section, false); - UploadBuffer uploadBuffer = new UploadBuffer(renderedBuffer); + UploadBuffer uploadBuffer = new UploadBuffer(bufferBuilder, drawState); compileResult.renderedLayers.put(TerrainRenderType.TRANSLUCENT, uploadBuffer); - renderedBuffer.release(); + + bufferBuilder.reset(); if (this.cancelled.get()) { + compileResult.renderedLayers.values().forEach(UploadBuffer::release); return Result.CANCELLED; } + taskDispatcher.scheduleSectionUpdate(compileResult); return Result.SUCCESSFUL; } diff --git a/src/main/java/net/vulkanmod/render/chunk/build/TaskDispatcher.java b/src/main/java/net/vulkanmod/render/chunk/build/task/TaskDispatcher.java similarity index 80% rename from src/main/java/net/vulkanmod/render/chunk/build/TaskDispatcher.java rename to src/main/java/net/vulkanmod/render/chunk/build/task/TaskDispatcher.java index ae43f3544..e78146d83 100644 --- a/src/main/java/net/vulkanmod/render/chunk/build/TaskDispatcher.java +++ b/src/main/java/net/vulkanmod/render/chunk/build/task/TaskDispatcher.java @@ -1,4 +1,4 @@ -package net.vulkanmod.render.chunk.build; +package net.vulkanmod.render.chunk.build.task; import com.google.common.collect.Queues; import net.vulkanmod.render.chunk.ChunkArea; @@ -6,12 +6,10 @@ import net.vulkanmod.render.chunk.RenderSection; import net.vulkanmod.render.chunk.WorldRenderer; import net.vulkanmod.render.chunk.buffer.DrawBuffers; -import net.vulkanmod.render.chunk.build.task.ChunkTask; -import net.vulkanmod.render.chunk.build.task.CompileResult; -import net.vulkanmod.render.chunk.build.thread.ThreadBuilderPack; +import net.vulkanmod.render.chunk.build.UploadBuffer; import net.vulkanmod.render.chunk.build.thread.BuilderResources; +import net.vulkanmod.render.chunk.build.thread.ThreadBuilderPack; import net.vulkanmod.render.vertex.TerrainRenderType; - import org.jetbrains.annotations.Nullable; import java.util.Queue; @@ -39,25 +37,30 @@ public void createThreads() { } public void createThreads(int n) { - if(!this.stopThreads) { + if (!this.stopThreads) { this.stopThreads(); } this.stopThreads = false; - if(this.resources != null) { + if (this.resources != null) { for (BuilderResources resources : this.resources) { - resources.clear(); + resources.free(); } } + // Auto select thread count + if (n == 0) { + n = Math.max((Runtime.getRuntime().availableProcessors() - 1) / 2, 1); + } + this.threads = new Thread[n]; this.resources = new BuilderResources[n]; for (int i = 0; i < n; i++) { BuilderResources builderResources = new BuilderResources(); Thread thread = new Thread(() -> runTaskThread(builderResources), - "Builder-" + i); + "Builder-" + i); thread.setPriority(Thread.NORM_PRIORITY); this.threads[i] = thread; @@ -67,10 +70,10 @@ public void createThreads(int n) { } private void runTaskThread(BuilderResources builderResources) { - while(!this.stopThreads) { + while (!this.stopThreads) { ChunkTask task = this.pollTask(); - if(task == null) + if (task == null) synchronized (this) { try { this.idleThreads++; @@ -81,7 +84,7 @@ private void runTaskThread(BuilderResources builderResources) { this.idleThreads--; } - if(task == null) + if (task == null) continue; task.runTask(builderResources); @@ -89,12 +92,13 @@ private void runTaskThread(BuilderResources builderResources) { } public void schedule(ChunkTask chunkTask) { - if(chunkTask == null) + if (chunkTask == null) return; if (chunkTask.highPriority) { this.highPriorityTasks.offer(chunkTask); - } else { + } + else { this.lowPriorityTasks.offer(chunkTask); } @@ -107,14 +111,14 @@ public void schedule(ChunkTask chunkTask) { private ChunkTask pollTask() { ChunkTask task = this.highPriorityTasks.poll(); - if(task == null) + if (task == null) task = this.lowPriorityTasks.poll(); return task; } public void stopThreads() { - if(this.stopThreads) + if (this.stopThreads) return; this.stopThreads = true; @@ -136,7 +140,7 @@ public void stopThreads() { public boolean updateSections() { CompileResult result; boolean flag = false; - while((result = this.compileResults.poll()) != null) { + while ((result = this.compileResults.poll()) != null) { flag = true; doSectionUpdate(result); } @@ -155,18 +159,22 @@ private void doSectionUpdate(CompileResult compileResult) { // Check if area has been dismissed before uploading ChunkAreaManager chunkAreaManager = WorldRenderer.getInstance().getChunkAreaManager(); - if (chunkAreaManager.getChunkArea(renderArea.index) != renderArea) + if (chunkAreaManager.getChunkArea(renderArea.index) != renderArea) { + compileResult.renderedLayers.values() + .forEach(UploadBuffer::release); return; + } - if(compileResult.fullUpdate) { + if (compileResult.fullUpdate) { var renderLayers = compileResult.renderedLayers; - for(TerrainRenderType renderType : TerrainRenderType.VALUES) { + for (TerrainRenderType renderType : TerrainRenderType.VALUES) { UploadBuffer uploadBuffer = renderLayers.get(renderType); - if(uploadBuffer != null) { + if (uploadBuffer != null) { drawBuffers.upload(section, uploadBuffer, renderType); - } else { - section.getDrawParameters(renderType).reset(renderArea, renderType); + } + else { + section.resetDrawParameters(renderType); } } @@ -178,17 +186,19 @@ private void doSectionUpdate(CompileResult compileResult) { } } - public boolean isIdle() { return this.idleThreads == this.threads.length && this.compileResults.isEmpty(); } + public boolean isIdle() { + return this.idleThreads == this.threads.length && this.compileResults.isEmpty(); + } public void clearBatchQueue() { - while(!this.highPriorityTasks.isEmpty()) { + while (!this.highPriorityTasks.isEmpty()) { ChunkTask chunkTask = this.highPriorityTasks.poll(); if (chunkTask != null) { chunkTask.cancel(); } } - while(!this.lowPriorityTasks.isEmpty()) { + while (!this.lowPriorityTasks.isEmpty()) { ChunkTask chunkTask = this.lowPriorityTasks.poll(); if (chunkTask != null) { chunkTask.cancel(); diff --git a/src/main/java/net/vulkanmod/render/chunk/build/thread/BuilderResources.java b/src/main/java/net/vulkanmod/render/chunk/build/thread/BuilderResources.java index 41a05af95..83418108e 100644 --- a/src/main/java/net/vulkanmod/render/chunk/build/thread/BuilderResources.java +++ b/src/main/java/net/vulkanmod/render/chunk/build/thread/BuilderResources.java @@ -2,10 +2,10 @@ import net.vulkanmod.Initializer; import net.vulkanmod.render.chunk.RenderSection; -import net.vulkanmod.render.chunk.build.BlockRenderer; -import net.vulkanmod.render.chunk.build.LiquidRenderer; +import net.vulkanmod.render.chunk.build.renderer.BlockRenderer; +import net.vulkanmod.render.chunk.build.renderer.FluidRenderer; import net.vulkanmod.render.chunk.build.RenderRegion; -import net.vulkanmod.render.chunk.build.TintCache; +import net.vulkanmod.render.chunk.build.color.TintCache; import net.vulkanmod.render.chunk.build.light.LightMode; import net.vulkanmod.render.chunk.build.light.LightPipeline; import net.vulkanmod.render.chunk.build.light.data.ArrayLightDataCache; @@ -16,41 +16,45 @@ public class BuilderResources { public final ThreadBuilderPack builderPack = new ThreadBuilderPack(); - public final BlockRenderer blockRenderer = new BlockRenderer(); - public final LiquidRenderer liquidRenderer = new LiquidRenderer(); - public final TintCache tintCache = new TintCache(); - public RenderRegion region; + public final BlockRenderer blockRenderer; + public final FluidRenderer fluidRenderer; public final ArrayLightDataCache lightDataCache = new ArrayLightDataCache(); public final QuadLightData quadLightData = new QuadLightData(); - public final LightPipeline smoothLightPipeline; - public final LightPipeline flatLightPipeline; + private RenderRegion region; private int totalBuildTime = 0, buildCount = 0; public BuilderResources() { - this.flatLightPipeline = new FlatLightPipeline(lightDataCache); + LightPipeline flatLightPipeline = new FlatLightPipeline(this.lightDataCache); + + LightPipeline smoothLightPipeline; + if (Initializer.CONFIG.ambientOcclusion == LightMode.SUB_BLOCK) { + smoothLightPipeline = new NewSmoothLightPipeline(lightDataCache); + } + else { + smoothLightPipeline = new SmoothLightPipeline(lightDataCache); + } + + this.blockRenderer = new BlockRenderer(flatLightPipeline, smoothLightPipeline); + this.fluidRenderer = new FluidRenderer(flatLightPipeline, smoothLightPipeline); - if(Initializer.CONFIG.ambientOcclusion == LightMode.SUB_BLOCK) - this.smoothLightPipeline = new NewSmoothLightPipeline(lightDataCache); - else - this.smoothLightPipeline = new SmoothLightPipeline(lightDataCache); + this.blockRenderer.setResources(this); + this.fluidRenderer.setResources(this); } public void update(RenderRegion region, RenderSection renderSection) { this.region = region; + this.blockRenderer.prepareForWorld(region, true); - lightDataCache.reset(region, renderSection.xOffset(), renderSection.yOffset(), renderSection.zOffset()); - - blockRenderer.setResources(this); - liquidRenderer.setResources(this); + this.lightDataCache.reset(region, renderSection.xOffset(), renderSection.yOffset(), renderSection.zOffset()); } - public void clear() { - builderPack.clearAll(); + public void free() { + builderPack.freeAll(); } public void updateBuildStats(int buildTime) { @@ -58,6 +62,10 @@ public void updateBuildStats(int buildTime) { this.totalBuildTime += buildTime; } + public RenderRegion getRegion() { + return region; + } + public int getTotalBuildTime() { return totalBuildTime; } diff --git a/src/main/java/net/vulkanmod/render/chunk/build/thread/ThreadBuilderPack.java b/src/main/java/net/vulkanmod/render/chunk/build/thread/ThreadBuilderPack.java index 5517ce4ea..86ca915a6 100644 --- a/src/main/java/net/vulkanmod/render/chunk/build/thread/ThreadBuilderPack.java +++ b/src/main/java/net/vulkanmod/render/chunk/build/thread/ThreadBuilderPack.java @@ -1,7 +1,11 @@ package net.vulkanmod.render.chunk.build.thread; -import net.vulkanmod.render.vertex.TerrainBufferBuilder; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import net.vulkanmod.render.PipelineManager; +import net.vulkanmod.render.vertex.CustomVertexFormat; +import net.vulkanmod.render.vertex.TerrainBuilder; import net.vulkanmod.render.vertex.TerrainRenderType; +import net.vulkanmod.render.vertex.VertexBuilder; import java.util.Arrays; import java.util.EnumMap; @@ -9,20 +13,27 @@ import java.util.function.Function; public class ThreadBuilderPack { - private static Function terrainBuilderConstructor; + private static Function terrainBuilderConstructor; public static void defaultTerrainBuilderConstructor() { - terrainBuilderConstructor = renderType -> new TerrainBufferBuilder(TerrainRenderType.getRenderType(renderType).bufferSize()); + terrainBuilderConstructor = renderType -> { + int size = TerrainRenderType.getLayer(renderType) + .bufferSize() / DefaultVertexFormat.BLOCK.getVertexSize(); + + boolean compressedFormat = PipelineManager.terrainVertexFormat == CustomVertexFormat.COMPRESSED_TERRAIN; + VertexBuilder vertexBuilder = compressedFormat ? new VertexBuilder.CompressedVertexBuilder() : new VertexBuilder.DefaultVertexBuilder(); + return new TerrainBuilder(size, vertexBuilder); + }; } - public static void setTerrainBuilderConstructor(Function constructor) { + public static void setTerrainBuilderConstructor(Function constructor) { terrainBuilderConstructor = constructor; } - private final Map builders; + private final Map builders; public ThreadBuilderPack() { - var map = new EnumMap(TerrainRenderType.class); + var map = new EnumMap(TerrainRenderType.class); Arrays.stream(TerrainRenderType.values()).forEach( terrainRenderType -> map.put(terrainRenderType, terrainBuilderConstructor.apply(terrainRenderType)) @@ -30,12 +41,12 @@ public ThreadBuilderPack() { builders = map; } - public TerrainBufferBuilder builder(TerrainRenderType renderType) { + public TerrainBuilder builder(TerrainRenderType renderType) { return this.builders.get(renderType); } - public void clearAll() { - this.builders.values().forEach(TerrainBufferBuilder::clear); + public void freeAll() { + this.builders.values().forEach(TerrainBuilder::free); } } diff --git a/src/main/java/net/vulkanmod/render/chunk/cull/QuadFacing.java b/src/main/java/net/vulkanmod/render/chunk/cull/QuadFacing.java new file mode 100644 index 000000000..292b69fd1 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/cull/QuadFacing.java @@ -0,0 +1,66 @@ +package net.vulkanmod.render.chunk.cull; + +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.vulkanmod.render.vertex.format.I32_SNorm; +import org.joml.Vector3f; + +public enum QuadFacing { + X_POS, + Y_POS, + Z_POS, + X_NEG, + Z_NEG, + UNDEFINED, + Y_NEG; + + public static final QuadFacing[] VALUES = QuadFacing.values(); + public static final int COUNT = VALUES.length; + + public static QuadFacing fromDirection(Direction direction) { + return switch (direction) { + case DOWN -> Y_NEG; + case UP -> Y_POS; + case NORTH -> Z_NEG; + case SOUTH -> Z_POS; + case WEST -> X_NEG; + case EAST -> X_POS; + }; + } + + public static QuadFacing fromNormal(int packedNormal) { + final float x = I32_SNorm.unpackX(packedNormal); + final float y = I32_SNorm.unpackY(packedNormal); + final float z = I32_SNorm.unpackZ(packedNormal); + + return fromNormal(x, y, z); + } + + public static QuadFacing fromNormal(Vector3f normal) { + return fromNormal(normal.x(), normal.y(), normal.z()); + } + + public static QuadFacing fromNormal(float x, float y, float z) { + final float absX = Math.abs(x); + final float absY = Math.abs(y); + final float absZ = Math.abs(z); + + float sum = absX + absY + absZ; + + if (Mth.equal(sum, 1.0f)) { + if (Mth.equal(absX, 1.0f)) { + return x > 0.0f ? QuadFacing.X_POS : QuadFacing.X_NEG; + } + + if (Mth.equal(absY, 1.0f)) { + return y > 0.0f ? QuadFacing.Y_POS : QuadFacing.Y_NEG; + } + + if (Mth.equal(absZ, 1.0f)) { + return z > 0.0f ? QuadFacing.Z_POS : QuadFacing.Z_NEG; + } + } + + return QuadFacing.UNDEFINED; + } +} diff --git a/src/main/java/net/vulkanmod/render/chunk/graph/SectionGraph.java b/src/main/java/net/vulkanmod/render/chunk/graph/SectionGraph.java index f3758feda..58b2d156e 100644 --- a/src/main/java/net/vulkanmod/render/chunk/graph/SectionGraph.java +++ b/src/main/java/net/vulkanmod/render/chunk/graph/SectionGraph.java @@ -7,13 +7,14 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.SectionPos; import net.minecraft.util.Mth; +import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import net.vulkanmod.Initializer; import net.vulkanmod.interfaces.FrustumMixed; import net.vulkanmod.render.chunk.*; import net.vulkanmod.render.chunk.build.RenderRegionBuilder; -import net.vulkanmod.render.chunk.build.TaskDispatcher; +import net.vulkanmod.render.chunk.build.task.TaskDispatcher; import net.vulkanmod.render.chunk.frustum.VFrustum; import net.vulkanmod.render.chunk.util.AreaSetQueue; import net.vulkanmod.render.chunk.util.ResettableQueue; @@ -55,13 +56,14 @@ public SectionGraph(Level level, SectionGrid sectionGrid, TaskDispatcher taskDis public void update(Camera camera, Frustum frustum, boolean spectator) { Profiler profiler = Profiler.getMainProfiler(); + ProfilerFiller mcProfiler = net.minecraft.util.profiling.Profiler.get(); BlockPos blockpos = camera.getBlockPosition(); - this.minecraft.getProfiler().popPush("update"); + mcProfiler.popPush("update"); boolean flag = this.minecraft.smartCull; - if (spectator && this.level.getBlockState(blockpos).isSolidRender(this.level, blockpos)) { + if (spectator && this.level.getBlockState(blockpos).isSolidRender()) { flag = false; } @@ -70,7 +72,7 @@ public void update(Camera camera, Frustum frustum, boolean spectator) { this.sectionGrid.updateFrustumVisibility(this.frustum); profiler.pop(); - this.minecraft.getProfiler().push("partial_update"); + mcProfiler.push("partial_update"); this.initUpdate(); this.initializeQueueForFullUpdate(camera); @@ -82,7 +84,7 @@ public void update(Camera camera, Frustum frustum, boolean spectator) { this.scheduleRebuilds(); - this.minecraft.getProfiler().pop(); + mcProfiler.pop(); } private void initializeQueueForFullUpdate(Camera camera) { @@ -91,8 +93,8 @@ private void initializeQueueForFullUpdate(Camera camera) { RenderSection renderSection = this.sectionGrid.getSectionAtBlockPos(blockpos); if (renderSection == null) { - boolean flag = blockpos.getY() > this.level.getMinBuildHeight(); - int y = flag ? this.level.getMaxBuildHeight() - 8 : this.level.getMinBuildHeight() + 8; + boolean flag = blockpos.getY() > this.level.getMinY(); + int y = flag ? this.level.getMaxY() - 8 : this.level.getMinY() + 8; int x = Mth.floor(vec3.x / 16.0D) * 16; int z = Mth.floor(vec3.z / 16.0D) * 16; diff --git a/src/main/java/net/vulkanmod/render/chunk/util/CircularIntList.java b/src/main/java/net/vulkanmod/render/chunk/util/CircularIntList.java index e81145a91..d8964eaa9 100644 --- a/src/main/java/net/vulkanmod/render/chunk/util/CircularIntList.java +++ b/src/main/java/net/vulkanmod/render/chunk/util/CircularIntList.java @@ -1,78 +1,67 @@ package net.vulkanmod.render.chunk.util; import org.apache.commons.lang3.Validate; -import org.jetbrains.annotations.NotNull; import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Spliterator; -import java.util.function.Consumer; public class CircularIntList { - private int[] list; - private final int startIndex; + private final int size; + private final int[] list; + private int startIndex; - private int[] previous; - private int[] next; + private final OwnIterator iterator; + private final RangeIterator rangeIterator; - private OwnIterator iterator; + public CircularIntList(int size) { + this.size = size; + this.list = new int[size + 2]; - public CircularIntList(int size, int startIndex) { - this.startIndex = startIndex; - - this.generateList(size); + this.iterator = new OwnIterator(); + this.rangeIterator = new RangeIterator(); } - private void generateList(int size) { - int[] list = new int[size]; + public void updateStartIdx(int startIndex) { + int[] list = this.list; + this.startIndex = startIndex; - this.previous = new int[size]; - this.next = new int[size]; + list[0] = -1; + list[size + 1] = -1; - int k = 0; + int k = 1; for(int i = startIndex; i < size; ++i) { list[k] = i; - ++k; } for(int i = 0; i < startIndex; ++i) { list[k] = i; ++k; } - - this.previous[0] = -1; - System.arraycopy(list, 0, this.previous, 1, size - 1); - - this.next[size - 1] = -1; - System.arraycopy(list, 1, this.next, 0, size - 1); - - this.list = list; } public int getNext(int i) { - return this.next[i]; + return this.list[i + 1]; } public int getPrevious(int i) { - return this.previous[i]; + return this.list[i - 1]; } public OwnIterator iterator() { - return new OwnIterator(); + return this.iterator; } - public RangeIterator rangeIterator(int startIndex, int endIndex) { - return new RangeIterator(startIndex, endIndex); + public RangeIterator getRangeIterator(int startIndex, int endIndex) { + this.rangeIterator.update(startIndex, endIndex); + return this.rangeIterator; } - public void restartIterator() { - this.iterator.restart(); + public RangeIterator createRangeIterator() { + return new RangeIterator(); } public class OwnIterator implements Iterator { - private int currentIndex = -1; - private final int maxIndex = list.length - 1; + private int currentIndex = 0; + private final int maxIndex = size; @Override public boolean hasNext() { @@ -90,38 +79,32 @@ public int getCurrentIndex() { } public void restart() { - this.currentIndex = -1; + this.currentIndex = 0; } } public class RangeIterator implements Iterator { private int currentIndex; - private final int startIndex; - private final int maxIndex; + private int startIndex; + private int endIndex; - public RangeIterator(int startIndex, int endIndex) { - this.startIndex = startIndex; - this.maxIndex = endIndex; - Validate.isTrue(this.maxIndex < list.length, "Beyond max size"); + public void update(int startIndex, int endIndex) { + Validate.isTrue(endIndex < list.length, "Beyond max size"); + this.startIndex = startIndex + 1; + this.endIndex = endIndex + 1; this.restart(); } @Override public boolean hasNext() { - return currentIndex < maxIndex; + return currentIndex < endIndex; } @Override public Integer next() { currentIndex++; - try { - return list[currentIndex]; - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(); - } - + return list[currentIndex]; } public int getCurrentIndex() { diff --git a/src/main/java/net/vulkanmod/render/chunk/util/Util.java b/src/main/java/net/vulkanmod/render/chunk/util/Util.java index c37ddd0ff..caa063410 100644 --- a/src/main/java/net/vulkanmod/render/chunk/util/Util.java +++ b/src/main/java/net/vulkanmod/render/chunk/util/Util.java @@ -44,11 +44,11 @@ public static int flooredLog(int v) { return log; } - public static int align(int i, int alignment) { + public static long align(long l, int alignment) { if (alignment == 0) - return i; + return l; - int r = i % alignment; - return r != 0 ? i + alignment - r : i; + long r = l % alignment; + return r != 0 ? l + alignment - r : l; } } diff --git a/src/main/java/net/vulkanmod/render/engine/EGlProgram.java b/src/main/java/net/vulkanmod/render/engine/EGlProgram.java new file mode 100644 index 000000000..11613d4f3 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/engine/EGlProgram.java @@ -0,0 +1,86 @@ +package net.vulkanmod.render.engine; + +import com.google.common.collect.Sets; +import com.mojang.blaze3d.opengl.*; +import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.logging.LogUtils; +import net.vulkanmod.vulkan.shader.Pipeline; +import net.vulkanmod.vulkan.shader.descriptor.UBO; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; + +import java.util.*; + +public class EGlProgram { + private static final Logger LOGGER = LogUtils.getLogger(); + public static Set BUILT_IN_UNIFORMS = Sets.newHashSet("Projection", "Lighting", "Fog", "Globals"); + public static EGlProgram INVALID_PROGRAM = new EGlProgram(-1, "invalid"); + private final Map uniformsByName = new HashMap(); + private final int programId; + private final String debugLabel; + + public EGlProgram(int i, String string) { + this.programId = i; + this.debugLabel = string; + } + + public void setupUniforms(Pipeline pipeline, List uniformDescriptions, List samplers) { + int i = 0; + int j = 0; + + for (RenderPipeline.UniformDescription uniformDescription : uniformDescriptions) { + String name = uniformDescription.name(); + + Uniform uniform = switch (uniformDescription.type()) { + case UNIFORM_BUFFER -> { + UBO ubo = pipeline.getUBO(name); + + if (ubo == null) { + yield null; + } + + int binding = ubo.binding; + yield new Uniform.Ubo(binding); + } + case TEXEL_BUFFER -> { + int binding = i++; + yield new Uniform.Utb(binding, 0, Objects.requireNonNull(uniformDescription.textureFormat())); + } + }; + + this.uniformsByName.put(name, uniform); + } + + for (String samplerName : samplers) { + var imageDescriptor = pipeline.getImageDescriptor(samplerName); + int binding = imageDescriptor.getBinding(); + int imageIdx = imageDescriptor.imageIdx; + this.uniformsByName.put(samplerName, new Uniform.Sampler(binding, imageIdx)); + } + + } + + @Nullable + public Uniform getUniform(String string) { + RenderSystem.assertOnRenderThread(); + return this.uniformsByName.get(string); + } + + public int getProgramId() { + return this.programId; + } + + public String toString() { + return this.debugLabel; + } + + public String getDebugLabel() { + return this.debugLabel; + } + + public Map getUniforms() { + return this.uniformsByName; + } + +} diff --git a/src/main/java/net/vulkanmod/render/engine/VkCommandEncoder.java b/src/main/java/net/vulkanmod/render/engine/VkCommandEncoder.java new file mode 100644 index 000000000..94d1e64e5 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/engine/VkCommandEncoder.java @@ -0,0 +1,909 @@ +package net.vulkanmod.render.engine; + +import com.mojang.blaze3d.buffers.GpuBuffer; +import com.mojang.blaze3d.buffers.GpuBufferSlice; +import com.mojang.blaze3d.buffers.GpuFence; +import com.mojang.blaze3d.opengl.*; +import com.mojang.blaze3d.pipeline.BlendFunction; +import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.blaze3d.platform.DepthTestFunction; +import com.mojang.blaze3d.platform.NativeImage; +import com.mojang.blaze3d.systems.CommandEncoder; +import com.mojang.blaze3d.systems.RenderPass; +import com.mojang.blaze3d.textures.GpuTexture; +import com.mojang.blaze3d.textures.GpuTextureView; +import com.mojang.blaze3d.vertex.VertexFormat; +import com.mojang.logging.LogUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.util.ARGB; +import net.vulkanmod.gl.VkGlFramebuffer; +import net.vulkanmod.gl.VkGlTexture; +import net.vulkanmod.interfaces.shader.ExtendedRenderPipeline; +import net.vulkanmod.vulkan.Renderer; +import net.vulkanmod.vulkan.Synchronization; +import net.vulkanmod.vulkan.VRenderSystem; +import net.vulkanmod.vulkan.Vulkan; +import net.vulkanmod.vulkan.device.DeviceManager; +import net.vulkanmod.vulkan.framebuffer.Framebuffer; +import net.vulkanmod.vulkan.memory.buffer.StagingBuffer; +import net.vulkanmod.vulkan.queue.GraphicsQueue; +import net.vulkanmod.vulkan.shader.GraphicsPipeline; +import net.vulkanmod.vulkan.shader.Pipeline; +import net.vulkanmod.vulkan.shader.descriptor.ImageDescriptor; +import net.vulkanmod.vulkan.shader.descriptor.UBO; +import net.vulkanmod.vulkan.texture.ImageUtil; +import net.vulkanmod.vulkan.texture.VTextureSelector; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.opengl.*; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.system.MemoryUtil; +import org.lwjgl.vulkan.*; +import org.slf4j.Logger; + +import java.nio.ByteBuffer; +import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.Supplier; + +import static org.lwjgl.system.MemoryStack.stackPush; +import static org.lwjgl.vulkan.VK10.*; + +public class VkCommandEncoder implements CommandEncoder { + private static final Logger LOGGER = LogUtils.getLogger(); + private final VkGpuDevice device; + + @Nullable + private RenderPipeline lastPipeline; + private boolean inRenderPass; + + @Nullable + private EGlProgram lastProgram; + + private int framebufferId = VkGlFramebuffer.genFramebufferId(); + + protected VkCommandEncoder(VkGpuDevice glDevice) { + this.device = glDevice; + } + + @Override + public RenderPass createRenderPass(Supplier supplier, GpuTextureView gpuTexture, OptionalInt optionalInt) { + return this.createRenderPass(supplier, gpuTexture, optionalInt, null, OptionalDouble.empty()); + } + + @Override + public RenderPass createRenderPass(Supplier supplier, GpuTextureView colorTexture, OptionalInt optionalInt, @Nullable GpuTextureView depthTexture, OptionalDouble optionalDouble) { + if (this.inRenderPass) { + throw new IllegalStateException("Close the existing render pass before creating a new one!"); + } else { + if (optionalDouble.isPresent() && depthTexture == null) { + LOGGER.warn("Depth clear value was provided but no depth texture is being used"); + } + + if (Minecraft.getInstance().getMainRenderTarget().getColorTexture() == colorTexture.texture()) { + Renderer.getInstance().getMainPass().rebindMainTarget(); + + int j = 0; + if (optionalInt.isPresent()) { + int k = optionalInt.getAsInt(); + GL11.glClearColor(ARGB.redFloat(k), ARGB.greenFloat(k), ARGB.blueFloat(k), ARGB.alphaFloat(k)); + j |= 16384; + } + + if (depthTexture != null && optionalDouble.isPresent()) { + GL11.glClearDepth(optionalDouble.getAsDouble()); + j |= 256; + } + + if (j != 0) { + GlStateManager._disableScissorTest(); + GlStateManager._depthMask(true); + GlStateManager._colorMask(true, true, true, true); + GlStateManager._clear(j); + } + + return new VkRenderPass(this, depthTexture != null); + } + + if (colorTexture.isClosed()) { + throw new IllegalStateException("Color texture is closed"); + } else if (depthTexture != null && depthTexture.isClosed()) { + throw new IllegalStateException("Depth texture is closed"); + } else { + this.inRenderPass = true; + GpuTexture depthTexture1 = depthTexture != null ? depthTexture.texture() : null; + VkFbo fbo = ((VkGpuTexture)colorTexture.texture()).getFbo(depthTexture1); + fbo.bind(); + + int j = 0; + if (optionalInt.isPresent()) { + int k = optionalInt.getAsInt(); + GL11.glClearColor(ARGB.redFloat(k), ARGB.greenFloat(k), ARGB.blueFloat(k), ARGB.alphaFloat(k)); + j |= 16384; + } + + if (depthTexture != null && optionalDouble.isPresent()) { + GL11.glClearDepth(optionalDouble.getAsDouble()); + j |= 256; + } + + if (j != 0) { + GlStateManager._disableScissorTest(); + GlStateManager._depthMask(true); + GlStateManager._colorMask(true, true, true, true); + GlStateManager._clear(j); + } + + GlStateManager._viewport(0, 0, colorTexture.getWidth(0), colorTexture.getHeight(0)); + this.lastPipeline = null; + return new VkRenderPass(this, depthTexture != null); + } + } + + } + + @Override + public void clearColorTexture(GpuTexture colorAttachment, int clearColor) { + if (this.inRenderPass) { + throw new IllegalStateException("Close the existing render pass before creating a new one!"); + } + else if (Renderer.isRecording()) { + if (Minecraft.getInstance().getMainRenderTarget().getColorTexture() == colorAttachment) { + Renderer.getInstance().getMainPass().rebindMainTarget(); + + VRenderSystem.setClearColor(ARGB.redFloat(clearColor), ARGB.greenFloat(clearColor), ARGB.blueFloat(clearColor), ARGB.alphaFloat(clearColor)); + Renderer.clearAttachments(0x4000); + } + else { + VkGpuTexture vkGpuTexture = (VkGpuTexture) colorAttachment; + VkGlFramebuffer.bindFramebuffer(GL30.GL_FRAMEBUFFER, framebufferId); + VkGlFramebuffer.framebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL11.GL_TEXTURE_2D, vkGpuTexture.glId(), 0); + + VkGlFramebuffer.beginRendering(VkGlFramebuffer.getFramebuffer(framebufferId)); + VRenderSystem.setClearColor(ARGB.redFloat(clearColor), ARGB.greenFloat(clearColor), ARGB.blueFloat(clearColor), ARGB.alphaFloat(clearColor)); + Renderer.clearAttachments(0x4000); + Renderer.getInstance().endRenderPass(); + + VkFbo fbo = ((VkGpuTexture)colorAttachment).getFbo(null); + + ((VkGpuTexture) colorAttachment).setClearColor(clearColor); + + Framebuffer boundFramebuffer = Renderer.getInstance().getBoundFramebuffer(); + if (boundFramebuffer != null && boundFramebuffer.getColorAttachment() == ((VkGpuTexture) colorAttachment).getVulkanImage()) { + fbo.clearAttachments(); + } + } + } + else { + GraphicsQueue graphicsQueue = DeviceManager.getGraphicsQueue(); + var commandBuffer = graphicsQueue.getCommandBuffer(); + VkGpuTexture vkGpuTexture = (VkGpuTexture) colorAttachment; + + VkGlFramebuffer glFramebuffer = VkGlFramebuffer.getFramebuffer(this.framebufferId); + glFramebuffer.setAttachmentTexture(GL30.GL_COLOR_ATTACHMENT0, vkGpuTexture.glId()); + glFramebuffer.create(); + + Framebuffer framebuffer = glFramebuffer.getFramebuffer(); + var renderPass = glFramebuffer.getRenderPass(); + try (MemoryStack stack = stackPush()) { + framebuffer.beginRenderPass(commandBuffer.handle, renderPass, stack); + } + + VRenderSystem.setClearColor(ARGB.redFloat(clearColor), ARGB.greenFloat(clearColor), ARGB.blueFloat(clearColor), ARGB.alphaFloat(clearColor)); + Renderer.clearAttachments(commandBuffer.handle, 0x4000, 0, 0, framebuffer.getWidth(), framebuffer.getHeight()); + renderPass.endRenderPass(commandBuffer.handle); + + long fence = graphicsQueue.submitCommands(commandBuffer); + Synchronization.waitFence(fence); + } + } + + @Override + public void clearColorAndDepthTextures(GpuTexture colorAttachment, int clearColor, GpuTexture depthAttachment, double clearDepth) { + if (this.inRenderPass) { + throw new IllegalStateException("Close the existing render pass before creating a new one!"); + } + else { + if (Minecraft.getInstance().getMainRenderTarget().getColorTexture() == colorAttachment) { + Renderer.getInstance().getMainPass().rebindMainTarget(); + + VRenderSystem.clearDepth(clearDepth); + VRenderSystem.setClearColor(ARGB.redFloat(clearColor), ARGB.greenFloat(clearColor), ARGB.blueFloat(clearColor), ARGB.alphaFloat(clearColor)); + Renderer.clearAttachments(0x4100); + } + else { + VkFbo fbo = ((VkGpuTexture)colorAttachment).getFbo(depthAttachment); + + ((VkGpuTexture) colorAttachment).setClearColor(clearColor); + ((VkGpuTexture) depthAttachment).setDepthClearValue((float) clearDepth); + + Framebuffer boundFramebuffer = Renderer.getInstance().getBoundFramebuffer(); + if (boundFramebuffer != null && boundFramebuffer.getColorAttachment() == ((VkGpuTexture) colorAttachment).getVulkanImage() + && boundFramebuffer.getDepthAttachment() == ((VkGpuTexture) depthAttachment).getVulkanImage()) + { + fbo.clearAttachments(); + } + } + } + } + + @Override + public void clearColorAndDepthTextures(GpuTexture colorAttachment, int clearColor, GpuTexture depthAttachment, double clearDepth, int x0, int y0, int width, int height) { + if (this.inRenderPass) { + throw new IllegalStateException("Close the existing render pass before creating a new one!"); + } else { + VRenderSystem.clearDepth(clearDepth); + VRenderSystem.setClearColor(ARGB.redFloat(clearColor), ARGB.greenFloat(clearColor), ARGB.blueFloat(clearColor), ARGB.alphaFloat(clearColor)); + + int framebufferHeight = colorAttachment.getHeight(0); + y0 = framebufferHeight - height - y0; + + Framebuffer boundFramebuffer = Renderer.getInstance().getBoundFramebuffer(); + if (boundFramebuffer != null && boundFramebuffer.getColorAttachment() == ((VkGpuTexture) colorAttachment).getVulkanImage() + && boundFramebuffer.getDepthAttachment() == ((VkGpuTexture) depthAttachment).getVulkanImage()) + { + Renderer.clearAttachments(0x4100, x0, y0, width, height); + } + else { + // TODO +// throw new IllegalStateException(); + } + } + } + + @Override + public void clearDepthTexture(GpuTexture depthAttachment, double clearDepth) { + if (this.inRenderPass) { + throw new IllegalStateException("Close the existing render pass before creating a new one!"); + } + else { + Framebuffer boundFramebuffer = Renderer.getInstance().getBoundFramebuffer(); + if (boundFramebuffer != null && boundFramebuffer.getDepthAttachment() == ((VkGpuTexture) depthAttachment).getVulkanImage()) { + VRenderSystem.clearDepth(clearDepth); + Renderer.clearAttachments(0x100); + } + else { + ((VkGpuTexture) depthAttachment).setDepthClearValue((float) clearDepth); + } + } + } + + @Override + public void writeToBuffer(GpuBufferSlice gpuBufferSlice, ByteBuffer byteBuffer) { + if (this.inRenderPass) { + throw new IllegalStateException("Close the existing render pass before performing additional commands"); + } else { + VkGpuBuffer vkGpuBuffer = (VkGpuBuffer) gpuBufferSlice.buffer(); + if (vkGpuBuffer.closed) { + throw new IllegalStateException("Buffer already closed"); + } + else { + int size = byteBuffer.remaining(); + if (size + gpuBufferSlice.offset() > vkGpuBuffer.size()) { + throw new IllegalArgumentException( + "Cannot write more data than this buffer can hold (attempting to write " + size + " bytes at offset " + gpuBufferSlice.offset() + " to " + gpuBufferSlice.length() + " slice size)" + ); + } else { + int dstOffset = gpuBufferSlice.offset(); + + var commandBuffer = Renderer.getInstance().getTransferCb(); + + StagingBuffer stagingBuffer = Vulkan.getStagingBuffer(); + stagingBuffer.copyBuffer(size, byteBuffer); + + long srcOffset = stagingBuffer.getOffset(); + + try (MemoryStack stack = MemoryStack.stackPush()) { + if (!commandBuffer.isRecording()) { + commandBuffer.begin(stack); + } + + VkBufferCopy.Buffer copyRegion = VkBufferCopy.calloc(1, stack); + copyRegion.size(size); + copyRegion.srcOffset(srcOffset); + copyRegion.dstOffset(dstOffset); + + vkCmdCopyBuffer(commandBuffer.handle, stagingBuffer.getId(), vkGpuBuffer.buffer.getId(), copyRegion); + } + } + } + } + } + + @Override + public GpuBuffer.MappedView mapBuffer(GpuBuffer gpuBuffer, boolean readable, boolean writable) { + return this.mapBuffer(gpuBuffer.slice(), readable, writable); + } + + @Override + public GpuBuffer.MappedView mapBuffer(GpuBufferSlice gpuBufferSlice, boolean readable, boolean writable) { + if (this.inRenderPass) { + throw new IllegalStateException("Close the existing render pass before performing additional commands"); + } else { + VkGpuBuffer gpuBuffer = (VkGpuBuffer)(gpuBufferSlice.buffer()); + if (gpuBuffer.closed) { + throw new IllegalStateException("Buffer already closed"); + } else if (!readable && !writable) { + throw new IllegalArgumentException("At least read or write must be true"); + } else if (readable && (gpuBuffer.usage() & 1) == 0) { + throw new IllegalStateException("Buffer is not readable"); + } else if (writable && (gpuBuffer.usage() & 2) == 0) { + throw new IllegalStateException("Buffer is not writable"); + } else if (gpuBufferSlice.offset() + gpuBufferSlice.length() > gpuBuffer.size()) { + throw new IllegalArgumentException( + "Cannot map more data than this buffer can hold (attempting to map " + + gpuBufferSlice.length() + + " bytes at offset " + + gpuBufferSlice.offset() + + " from " + + gpuBuffer.size() + + " size buffer)" + ); + } else { + int i = 0; + if (readable) { + i |= 1; + } + + if (writable) { + i |= 34; + } + + ByteBuffer byteBuffer = MemoryUtil.memByteBuffer(gpuBuffer.getBuffer().getDataPtr() + gpuBufferSlice.offset(), gpuBufferSlice.length()); + return new VkGpuBuffer.MappedView(0, byteBuffer); + } + } + } + + public void copyToBuffer(GpuBufferSlice gpuBufferSlice, GpuBufferSlice gpuBufferSlice2) { + if (this.inRenderPass) { + throw new IllegalStateException("Close the existing render pass before performing additional commands"); + } else { + VkGpuBuffer vkGpuBuffer = (VkGpuBuffer) gpuBufferSlice.buffer(); + if (vkGpuBuffer.closed) { + throw new IllegalStateException("Source buffer already closed"); + } else if ((vkGpuBuffer.usage() & 8) == 0) { + throw new IllegalStateException("Source buffer needs USAGE_COPY_DST to be a destination for a copy"); + } else { + VkGpuBuffer vkGpuBuffer2 = (VkGpuBuffer) gpuBufferSlice2.buffer(); + if (vkGpuBuffer2.closed) { + throw new IllegalStateException("Target buffer already closed"); + } else if ((vkGpuBuffer2.usage() & 8) == 0) { + throw new IllegalStateException("Target buffer needs USAGE_COPY_DST to be a destination for a copy"); + } else if (gpuBufferSlice.length() != gpuBufferSlice2.length()) { + int var6 = gpuBufferSlice.length(); + throw new IllegalArgumentException("Cannot copy from slice of size " + var6 + " to slice of size " + gpuBufferSlice2.length() + ", they must be equal"); + } else if (gpuBufferSlice.offset() + gpuBufferSlice.length() > vkGpuBuffer.size()) { + int var5 = gpuBufferSlice.length(); + throw new IllegalArgumentException("Cannot copy more data than the source buffer holds (attempting to copy " + var5 + " bytes at offset " + gpuBufferSlice.offset() + " from " + vkGpuBuffer.size() + " size buffer)"); + } else if (gpuBufferSlice2.offset() + gpuBufferSlice2.length() > vkGpuBuffer2.size()) { + int var10002 = gpuBufferSlice2.length(); + throw new IllegalArgumentException("Cannot copy more data than the target buffer can hold (attempting to copy " + var10002 + " bytes at offset " + gpuBufferSlice2.offset() + " to " + vkGpuBuffer2.size() + " size buffer)"); + } else { +// this.device.directStateAccess().copyBufferSubData(vkGpuBuffer.handle, vkGpuBuffer2.handle, gpuBufferSlice.offset(), gpuBufferSlice2.offset(), gpuBufferSlice.length()); +// vkGpuBuffer.buffer.copyBuffer(byteBuffer, byteBuffer.remaining(), gpuBufferSlice.offset()); + + // TODO + throw new UnsupportedOperationException(); + } + } + } + } + + @Override + public void writeToTexture(GpuTexture gpuTexture, NativeImage nativeImage) { + int i = gpuTexture.getWidth(0); + int j = gpuTexture.getHeight(0); + if (nativeImage.getWidth() != i || nativeImage.getHeight() != j) { + throw new IllegalArgumentException( + "Cannot replace texture of size " + i + "x" + j + " with image of size " + nativeImage.getWidth() + "x" + nativeImage.getHeight() + ); + } else if (gpuTexture.isClosed()) { + throw new IllegalStateException("Destination texture is closed"); + } else { + this.writeToTexture(gpuTexture, nativeImage, 0, 0, 0, 0, i, j, 0, 0); + } + } + + @Override + public void writeToTexture(GpuTexture gpuTexture, NativeImage nativeImage, int level, int arrayLayer, int xOffset, int yOffset, int width, int height, int unpackSkipPixels, int unpackSkipRows) { + if (this.inRenderPass) { + throw new IllegalStateException("Close the existing render pass before performing additional commands"); + } else if (level >= 0 && level < gpuTexture.getMipLevels()) { + if (unpackSkipPixels + width > nativeImage.getWidth() || unpackSkipRows + height > nativeImage.getHeight()) { + throw new IllegalArgumentException( + "Copy source (" + + nativeImage.getWidth() + + "x" + + nativeImage.getHeight() + + ") is not large enough to read a rectangle of " + + width + + "x" + + height + + " from " + + unpackSkipPixels + + "x" + + unpackSkipRows + ); + } else if (xOffset + width > gpuTexture.getWidth(level) || yOffset + height > gpuTexture.getHeight(level)) { + throw new IllegalArgumentException( + "Dest texture (" + width + "x" + height + ") is not large enough to write a rectangle of " + width + "x" + height + " at " + xOffset + "x" + yOffset + " (at mip level " + level + ")" + ); + } else if (gpuTexture.isClosed()) { + throw new IllegalStateException("Destination texture is closed"); + } else { + VTextureSelector.setActiveTexture(0); + var glTexture = VkGlTexture.getTexture(((GlTexture) gpuTexture).glId()); +// VTextureSelector.bindTexture(((VkGpuTexture) gpuTexture).getVulkanImage()); + VTextureSelector.bindTexture(glTexture.getVulkanImage()); + VTextureSelector.uploadSubTexture(level, arrayLayer, width, height, xOffset, yOffset, unpackSkipRows, unpackSkipPixels, nativeImage.getWidth(), nativeImage.getPointer()); + } + } else { + throw new IllegalArgumentException("Invalid mipLevel " + level + ", must be >= 0 and < " + gpuTexture.getMipLevels()); + } + } + + @Override + public void writeToTexture(GpuTexture gpuTexture, ByteBuffer byteBuffer, NativeImage.Format format, int level, int j, int xOffset, int yOffset, int width, int height) { + if (this.inRenderPass) { + throw new IllegalStateException("Close the existing render pass before performing additional commands"); + } else if (level >= 0 && level < gpuTexture.getMipLevels()) { + if (width * height * format.components() > byteBuffer.remaining()) { + throw new IllegalArgumentException( + "Copy would overrun the source buffer (remaining length of " + byteBuffer.remaining() + ", but copy is " + width + "x" + height + " of format " + format + ")" + ); + } else if (xOffset + width > gpuTexture.getWidth(level) || yOffset + height > gpuTexture.getHeight(level)) { + throw new IllegalArgumentException( + "Dest texture (" + + gpuTexture.getWidth(level) + + "x" + + gpuTexture.getHeight(level) + + ") is not large enough to write a rectangle of " + + width + + "x" + + height + + " at " + + xOffset + + "x" + + yOffset + ); + } else if (gpuTexture.isClosed()) { + throw new IllegalStateException("Destination texture is closed"); + } else if ((gpuTexture.usage() & 1) == 0) { + throw new IllegalStateException("Color texture must have USAGE_COPY_DST to be a destination for a write"); + } else if (j >= gpuTexture.getDepthOrLayers()) { + throw new UnsupportedOperationException("Depth or layer is out of range, must be >= 0 and < " + gpuTexture.getDepthOrLayers()); + } + else { + GlStateManager._bindTexture(((VkGpuTexture)gpuTexture).id); + + GlStateManager._pixelStore(3314, width); + GlStateManager._pixelStore(3316, 0); + GlStateManager._pixelStore(3315, 0); + GlStateManager._pixelStore(3317, format.components()); + GlStateManager._texSubImage2D(3553, level, xOffset, yOffset, width, height, GlConst.toGl(format), 5121, byteBuffer); + } + } else { + throw new IllegalArgumentException("Invalid mipLevel, must be >= 0 and < " + gpuTexture.getMipLevels()); + } + } + + @Override + public void copyTextureToBuffer(GpuTexture gpuTexture, GpuBuffer gpuBuffer, int i, Runnable runnable, int j) { + if (this.inRenderPass) { + throw new IllegalStateException("Close the existing render pass before performing additional commands"); + } else { + this.copyTextureToBuffer(gpuTexture, gpuBuffer, i, runnable, j, 0, 0, gpuTexture.getWidth(j), gpuTexture.getHeight(j)); + } + } + + @Override + public void copyTextureToBuffer(GpuTexture gpuTexture, GpuBuffer gpuBuffer, int dstOffset, Runnable runnable, int mipLevel, int xOffset, int yOffset, int width, int height) { + VkGpuBuffer vkGpuBuffer = (VkGpuBuffer) gpuBuffer; + VkGpuTexture vkGpuTexture = (VkGpuTexture) gpuTexture; + + if (this.inRenderPass) { + throw new IllegalStateException("Close the existing render pass before performing additional commands"); + } else if (mipLevel >= 0 && mipLevel < gpuTexture.getMipLevels()) { + if (gpuTexture.getWidth(mipLevel) * gpuTexture.getHeight(mipLevel) * vkGpuTexture.getVulkanImage().formatSize + dstOffset > gpuBuffer.size()) { + throw new IllegalArgumentException( + "Buffer of size " + + gpuBuffer.size() + + " is not large enough to hold " + + width + + "x" + + height + + " pixels (" + + vkGpuTexture.getVulkanImage().formatSize + + " bytes each) starting from offset " + + dstOffset + ); + } + else if (xOffset + width > gpuTexture.getWidth(mipLevel) || yOffset + height > gpuTexture.getHeight(mipLevel)) { + throw new IllegalArgumentException( + "Copy source texture (" + + gpuTexture.getWidth(mipLevel) + + "x" + + gpuTexture.getHeight(mipLevel) + + ") is not large enough to read a rectangle of " + + width + + "x" + + height + + " from " + + xOffset + + "," + + yOffset + ); + } else if (gpuTexture.isClosed()) { + throw new IllegalStateException("Source texture is closed"); + } else if (gpuBuffer.isClosed()) { + throw new IllegalStateException("Destination buffer is closed"); + } else { + ImageUtil.copyImageToBuffer(vkGpuTexture.getVulkanImage(), vkGpuBuffer.getBuffer(), mipLevel, width, height, xOffset, yOffset, dstOffset, width, height); + + runnable.run(); + } + } else { + throw new IllegalArgumentException("Invalid mipLevel " + mipLevel + ", must be >= 0 and < " + gpuTexture.getMipLevels()); + } + } + + @Override + public void copyTextureToTexture(GpuTexture gpuTexture, GpuTexture gpuTexture2, int mipLevel, int j, int k, int l, int m, int n, int o) { + if (this.inRenderPass) { + throw new IllegalStateException("Close the existing render pass before performing additional commands"); + } else if (mipLevel >= 0 && mipLevel < gpuTexture.getMipLevels() && mipLevel < gpuTexture2.getMipLevels()) { + if (j + n > gpuTexture2.getWidth(mipLevel) || k + o > gpuTexture2.getHeight(mipLevel)) { + throw new IllegalArgumentException( + "Dest texture (" + + gpuTexture2.getWidth(mipLevel) + + "x" + + gpuTexture2.getHeight(mipLevel) + + ") is not large enough to write a rectangle of " + + n + + "x" + + o + + " at " + + j + + "x" + + k + ); + } else if (l + n > gpuTexture.getWidth(mipLevel) || m + o > gpuTexture.getHeight(mipLevel)) { + throw new IllegalArgumentException( + "Source texture (" + + gpuTexture.getWidth(mipLevel) + + "x" + + gpuTexture.getHeight(mipLevel) + + ") is not large enough to read a rectangle of " + + n + + "x" + + o + + " at " + + l + + "x" + + m + ); + } else if (gpuTexture.isClosed()) { + throw new IllegalStateException("Source texture is closed"); + } else if (gpuTexture2.isClosed()) { + throw new IllegalStateException("Destination texture is closed"); + } else { + // TODO implement + } + } else { + throw new IllegalArgumentException("Invalid mipLevel " + mipLevel + ", must be >= 0 and < " + gpuTexture.getMipLevels() + " and < " + gpuTexture2.getMipLevels()); + } + } + + @Override + public GpuFence createFence() { + if (this.inRenderPass) { + throw new IllegalStateException("Close the existing render pass before performing additional commands"); + } else { +// throw new UnsupportedOperationException(); + // TODO + return new GpuFence() { + @Override + public void close() { + + } + + @Override + public boolean awaitCompletion(long l) { + return true; + } + }; + } + } + + @Override + public void presentTexture(GpuTextureView gpuTexture) { + throw new UnsupportedOperationException(); + } + + protected void executeDrawMultiple( + VkRenderPass renderPass, + Collection> collection, + @Nullable GpuBuffer gpuBuffer, + @Nullable VertexFormat.IndexType indexType, + Collection collection2, + T object + ) { + if (this.trySetup(renderPass)) { + if (indexType == null) { + indexType = VertexFormat.IndexType.SHORT; + } + + Pipeline pipeline = ExtendedRenderPipeline.of(renderPass.getPipeline()).getPipeline(); + + for (RenderPass.Draw draw : collection) { + VertexFormat.IndexType indexType2 = draw.indexType() == null ? indexType : draw.indexType(); + renderPass.setIndexBuffer(draw.indexBuffer() == null ? gpuBuffer : draw.indexBuffer(), indexType2); + renderPass.setVertexBuffer(draw.slot(), draw.vertexBuffer()); + + if (GlRenderPass.VALIDATION) { + if (renderPass.indexBuffer == null) { + throw new IllegalStateException("Missing index buffer"); + } + + if (renderPass.indexBuffer.isClosed()) { + throw new IllegalStateException("Index buffer has been closed!"); + } + + if (renderPass.vertexBuffers[0] == null) { + throw new IllegalStateException("Missing vertex buffer at slot 0"); + } + + if (renderPass.vertexBuffers[0].isClosed()) { + throw new IllegalStateException("Vertex buffer at slot 0 has been closed!"); + } + } + + BiConsumer biConsumer = draw.uniformUploaderConsumer(); + if (biConsumer != null) { + biConsumer.accept(object, (string, gpuBufferSlice) -> { + EGlProgram glProgram = ExtendedRenderPipeline.of(renderPass.pipeline).getProgram(); + if (glProgram.getUniform(string) instanceof Uniform.Ubo ubo) { + + int blockBinding; + try { + blockBinding = ubo.blockBinding(); + } catch (Throwable var7) { + throw new MatchException(var7.toString(), var7); + } + + // TODO +// GL32.glBindBufferRange(35345, blockBinding, ((GlBuffer)gpuBufferSlice.buffer()).handle, (long)gpuBufferSlice.offset(), (long)gpuBufferSlice.length()); + } + }); + + Renderer.getInstance().uploadAndBindUBOs(pipeline); + } + + this.drawFromBuffers(renderPass, 0, draw.firstIndex(), draw.indexCount(), indexType2, renderPass.pipeline, 1); + } + } + } + + protected void executeDraw(VkRenderPass renderPass, int i, int j, int k, @Nullable VertexFormat.IndexType indexType, int l) { + if (this.trySetup(renderPass)) { + if (GlRenderPass.VALIDATION) { + if (indexType != null) { + if (renderPass.indexBuffer == null) { + throw new IllegalStateException("Missing index buffer"); + } + + if (renderPass.indexBuffer.isClosed()) { + throw new IllegalStateException("Index buffer has been closed!"); + } + } + + if (renderPass.vertexBuffers[0] == null) { + throw new IllegalStateException("Missing vertex buffer at slot 0"); + } + + if (renderPass.vertexBuffers[0].isClosed()) { + throw new IllegalStateException("Vertex buffer at slot 0 has been closed!"); + } + } + + this.drawFromBuffers(renderPass, i, j, k, indexType, renderPass.pipeline, l); + } + } + + public void drawFromBuffers(VkRenderPass renderPass, int vertexOffset, int firstIndex, int vertexCount, + @Nullable VertexFormat.IndexType indexType, RenderPipeline renderPipeline, int instanceCount) + { + if (instanceCount < 1) { + instanceCount = 1; + } + if (vertexOffset < 0) { + vertexOffset = 0; + } + + VkCommandBuffer vkCommandBuffer = Renderer.getCommandBuffer(); + VkGpuBuffer vertexBuffer = (VkGpuBuffer)renderPass.vertexBuffers[0]; + try (MemoryStack stack = stackPush()) { + if (vertexBuffer != null) { + VK11.vkCmdBindVertexBuffers(vkCommandBuffer, 0, stack.longs(vertexBuffer.buffer.getId()), stack.longs(0)); + } + + if (renderPass.indexBuffer != null) { + VkGpuBuffer indexBuffer = (VkGpuBuffer)renderPass.indexBuffer; + + int vkIndexType = switch (indexType) { + case SHORT -> VK_INDEX_TYPE_UINT16; + case INT -> VK_INDEX_TYPE_UINT32; + }; + + VK11.vkCmdBindIndexBuffer(vkCommandBuffer, indexBuffer.buffer.getId(), 0, vkIndexType); + VK11.vkCmdDrawIndexed(vkCommandBuffer, vertexCount, instanceCount, firstIndex, vertexOffset, 0); + } + else { + var autoIndexBuffer = Renderer.getDrawer().getAutoIndexBuffer(renderPipeline.getVertexFormatMode(), vertexCount); + if (autoIndexBuffer != null) { + int indexCount = autoIndexBuffer.getIndexCount(vertexCount); + VK11.vkCmdBindIndexBuffer(vkCommandBuffer, autoIndexBuffer.getIndexBuffer().getId(), 0, autoIndexBuffer.getIndexBuffer().indexType.value); + VK11.vkCmdDrawIndexed(vkCommandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, 0); + } + else { + VK11.vkCmdDraw(vkCommandBuffer, vertexCount, instanceCount, vertexOffset, 0); + } + } + } + } + + public boolean trySetup(VkRenderPass renderPass) { + if (VkRenderPass.VALIDATION) { + if (renderPass.pipeline == null) { + throw new IllegalStateException("Can't draw without a render pipeline"); + } + + for (RenderPipeline.UniformDescription uniformDescription : renderPass.pipeline.getUniforms()) { + Object object = renderPass.uniforms.get(uniformDescription.name()); + if (object == null && !GlProgram.BUILT_IN_UNIFORMS.contains(uniformDescription.name())) { + throw new IllegalStateException("Missing uniform " + uniformDescription.name() + " (should be " + uniformDescription.type() + ")"); + } + } + + } + + applyPipelineState(renderPass.pipeline); + setupUniforms(renderPass); + + if (renderPass.isScissorEnabled()) { + GlStateManager._enableScissorTest(); + GlStateManager._scissorBox( + renderPass.getScissorX(), renderPass.getScissorY(), renderPass.getScissorWidth(), renderPass.getScissorHeight() + ); + } else { + GlStateManager._disableScissorTest(); + } + + return bindPipeline(renderPass.pipeline); + } + + public void setupUniforms(VkRenderPass renderPass) { + RenderPipeline renderPipeline = renderPass.pipeline; + EGlProgram glProgram = ExtendedRenderPipeline.of(renderPass.pipeline).getProgram(); + Pipeline pipeline = ExtendedRenderPipeline.of(renderPass.pipeline).getPipeline(); + + for (UBO ubo : pipeline.getBuffers()) { + String uniformName = ubo.name; + Uniform uniform = glProgram.getUniform(uniformName); + + GpuBufferSlice gpuBufferSlice = renderPass.uniforms.get(uniformName); + + // In case uniform buffer is not set, fallback to global buffer + if (gpuBufferSlice == null) { + ubo.setUseGlobalBuffer(true); + ubo.setUpdate(true); + continue; + } + + VkGpuBuffer gpuBuffer = (VkGpuBuffer) gpuBufferSlice.buffer(); + + assert ubo != null; + ubo.setUseGlobalBuffer(false); + ubo.getBufferSlice().set(gpuBuffer.buffer, gpuBufferSlice.offset(), gpuBufferSlice.length()); + } + + for (ImageDescriptor imageDescriptor : pipeline.getImageDescriptors()) { + String uniformName = imageDescriptor.name; + int samplerIndex = imageDescriptor.imageIdx; + + VkTextureView textureView = (VkTextureView) renderPass.samplers.get(uniformName); + if (textureView == null) { + continue; + } + + VkGpuTexture gpuTexture = textureView.texture(); + if (gpuTexture.isClosed()) { + continue; + } + + GlStateManager._activeTexture(33984 + samplerIndex); + GlStateManager._bindTexture(gpuTexture.id); + + GlStateManager._texParameter(GL11.GL_TEXTURE_2D, 33084, textureView.baseMipLevel()); + GlStateManager._texParameter(GL11.GL_TEXTURE_2D, 33085, textureView.baseMipLevel() + textureView.mipLevels() - 1); + gpuTexture.flushModeChanges(); + } + + } + + public boolean bindPipeline(RenderPipeline renderPipeline) { + Pipeline pipeline = ExtendedRenderPipeline.of(renderPipeline).getPipeline(); + + if (pipeline == null) { + return false; + } + + Renderer renderer = Renderer.getInstance(); + renderer.bindGraphicsPipeline((GraphicsPipeline) pipeline); +// VTextureSelector.bindShaderTextures(pipeline); + + renderer.uploadAndBindUBOs(pipeline); + + return true; + } + + public void applyPipelineState(RenderPipeline renderPipeline) { + if (this.lastPipeline != renderPipeline) { + this.lastPipeline = renderPipeline; + if (renderPipeline.getDepthTestFunction() != DepthTestFunction.NO_DEPTH_TEST) { + GlStateManager._enableDepthTest(); + GlStateManager._depthFunc(GlConst.toGl(renderPipeline.getDepthTestFunction())); + } else { + GlStateManager._disableDepthTest(); + } + + if (renderPipeline.isCull()) { + GlStateManager._enableCull(); + } else { + GlStateManager._disableCull(); + } + + if (renderPipeline.getBlendFunction().isPresent()) { + GlStateManager._enableBlend(); + BlendFunction blendFunction = renderPipeline.getBlendFunction().get(); + GlStateManager._blendFuncSeparate( + GlConst.toGl(blendFunction.sourceColor()), + GlConst.toGl(blendFunction.destColor()), + GlConst.toGl(blendFunction.sourceAlpha()), + GlConst.toGl(blendFunction.destAlpha()) + ); + } else { + GlStateManager._disableBlend(); + } + + GlStateManager._polygonMode(1032, GlConst.toGl(renderPipeline.getPolygonMode())); + GlStateManager._depthMask(renderPipeline.isWriteDepth()); + GlStateManager._colorMask(renderPipeline.isWriteColor(), renderPipeline.isWriteColor(), renderPipeline.isWriteColor(), renderPipeline.isWriteAlpha()); + if (renderPipeline.getDepthBiasConstant() == 0.0F && renderPipeline.getDepthBiasScaleFactor() == 0.0F) { + GlStateManager._disablePolygonOffset(); + } else { + GlStateManager._polygonOffset(renderPipeline.getDepthBiasScaleFactor(), renderPipeline.getDepthBiasConstant()); + GlStateManager._enablePolygonOffset(); + } + + switch (renderPipeline.getColorLogic()) { + case NONE: + GlStateManager._disableColorLogicOp(); + break; + case OR_REVERSE: + GlStateManager._enableColorLogicOp(); + GlStateManager._logicOp(5387); + } + + VRenderSystem.setPrimitiveTopologyGL(GlConst.toGl(renderPipeline.getVertexFormatMode())); + } + } + + public void finishRenderPass() { + this.inRenderPass = false; + } + + protected VkGpuDevice getDevice() { + return this.device; + } +} diff --git a/src/main/java/net/vulkanmod/render/engine/VkDebugLabel.java b/src/main/java/net/vulkanmod/render/engine/VkDebugLabel.java new file mode 100644 index 000000000..60ac40491 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/engine/VkDebugLabel.java @@ -0,0 +1,40 @@ +package net.vulkanmod.render.engine; + +import com.mojang.blaze3d.opengl.*; +import com.mojang.logging.LogUtils; +import java.util.Set; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import org.slf4j.Logger; + +@Environment(EnvType.CLIENT) +public class VkDebugLabel { + private static final Logger LOGGER = LogUtils.getLogger(); + + public void applyLabel(VkGpuBuffer glBuffer) { + } + + public void applyLabel(VkGpuTexture glTexture) { + } + + public void applyLabel(GlShaderModule glShaderModule) { + } + + public void applyLabel(GlProgram glProgram) { + } + + public void applyLabel(VertexArrayCache.VertexArray vertexArray) { + } + + public static VkDebugLabel create(boolean bl, Set set) { + return new VkDebugLabel(); + } + + public boolean exists() { + return true; + } + + +} + diff --git a/src/main/java/net/vulkanmod/render/engine/VkFbo.java b/src/main/java/net/vulkanmod/render/engine/VkFbo.java new file mode 100644 index 000000000..1b61c1f49 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/engine/VkFbo.java @@ -0,0 +1,69 @@ +package net.vulkanmod.render.engine; + +import com.mojang.blaze3d.opengl.GlStateManager; +import net.minecraft.util.ARGB; +import net.vulkanmod.gl.VkGlFramebuffer; +import net.vulkanmod.vulkan.Renderer; +import net.vulkanmod.vulkan.VRenderSystem; +import org.lwjgl.opengl.GL33; + +public class VkFbo { + final int glId; + final VkGpuTexture colorAttachment; + final VkGpuTexture depthAttachment; + + protected VkFbo(VkGpuTexture colorAttachment, VkGpuTexture depthAttachment) { + this.glId = GlStateManager.glGenFramebuffers(); + this.colorAttachment = colorAttachment; + this.depthAttachment = depthAttachment; + + // Direct access + VkGlFramebuffer fbo = VkGlFramebuffer.getFramebuffer(this.glId); + + fbo.setAttachmentTexture(GL33.GL_COLOR_ATTACHMENT0, colorAttachment.id); + if (depthAttachment != null) { + fbo.setAttachmentTexture(GL33.GL_DEPTH_ATTACHMENT, depthAttachment.id); + } + } + + public void bind() { + VkGlFramebuffer.bindFramebuffer(GL33.GL_FRAMEBUFFER, this.glId); + clearAttachments(); + } + + protected void clearAttachments() { + int clear = 0; + float clearDepth; + int clearColor; + + if (colorAttachment.needsClear()) { + clear |= 0x4000; + clearColor = colorAttachment.clearColor; + + VRenderSystem.setClearColor(ARGB.redFloat(clearColor), ARGB.greenFloat(clearColor), ARGB.blueFloat(clearColor), ARGB.alphaFloat(clearColor)); + + colorAttachment.needsClear = false; + } + + if (depthAttachment != null && depthAttachment.needsClear()) { + clear |= 0x100; + clearDepth = depthAttachment.depthClearValue; + + VRenderSystem.clearDepth(clearDepth); + + depthAttachment.needsClear = false; + } + + if (clear != 0) { + Renderer.clearAttachments(clear); + } + } + + protected void close() { + VkGlFramebuffer.deleteFramebuffer(this.glId); + } + + public boolean needsClear() { + return this.colorAttachment.needsClear() || (this.depthAttachment != null && this.depthAttachment.needsClear()); + } +} diff --git a/src/main/java/net/vulkanmod/render/engine/VkGpuBuffer.java b/src/main/java/net/vulkanmod/render/engine/VkGpuBuffer.java new file mode 100644 index 000000000..1c672841e --- /dev/null +++ b/src/main/java/net/vulkanmod/render/engine/VkGpuBuffer.java @@ -0,0 +1,111 @@ +package net.vulkanmod.render.engine; + +import com.mojang.blaze3d.buffers.GpuBuffer; + +import java.nio.ByteBuffer; +import java.util.function.Supplier; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.vulkanmod.vulkan.memory.MemoryManager; +import net.vulkanmod.vulkan.memory.MemoryType; +import net.vulkanmod.vulkan.memory.MemoryTypes; +import net.vulkanmod.vulkan.memory.buffer.Buffer; +import org.jetbrains.annotations.Nullable; + +import static org.lwjgl.vulkan.VK10.*; + +@Environment(EnvType.CLIENT) +public class VkGpuBuffer extends GpuBuffer { + protected boolean closed; + @Nullable protected final Supplier label; + + Buffer buffer; + + protected VkGpuBuffer(VkDebugLabel glDebugLabel, @Nullable Supplier supplier, int usage, int size) { + super(usage, size); + this.label = supplier; + + int vkUsage = 0; + if ((usage & GpuBuffer.USAGE_COPY_SRC) != 0) { + vkUsage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + } + if ((usage & GpuBuffer.USAGE_COPY_DST) != 0) { + vkUsage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; + } + if ((usage & GpuBuffer.USAGE_VERTEX) != 0) { + vkUsage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + } + if ((usage & GpuBuffer.USAGE_INDEX) != 0) { + vkUsage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + } + if ((usage & GpuBuffer.USAGE_UNIFORM) != 0) { + vkUsage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; + } + if ((usage & GpuBuffer.USAGE_UNIFORM_TEXEL_BUFFER) != 0) { + vkUsage |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; + } + + boolean mappable = (usage & GpuBuffer.USAGE_MAP_READ) != 0 | + (usage & GpuBuffer.USAGE_MAP_WRITE) != 0 | + (usage & GpuBuffer.USAGE_HINT_CLIENT_STORAGE) != 0; + + MemoryType memoryType = mappable ? MemoryTypes.HOST_MEM : MemoryTypes.GPU_MEM; + + this.buffer = new Buffer(vkUsage, memoryType); + this.buffer.createBuffer(this.size()); + } + + @Override + public boolean isClosed() { + return this.closed; + } + + @Override + public void close() { + if (!this.closed) { + this.closed = true; + + MemoryManager.getInstance().addToFreeable(this.buffer); + } + } + + public Buffer getBuffer() { + return buffer; + } + + public static int bufferUsageToGlEnum(int i) { + boolean stream = (i & 4) != 0; + // Draw + if ((i & 2) != 0) { + return stream ? 35040 : 35044; + } + // Read + else if ((i & 1) != 0) { + return stream ? 35041 : 35045; + } else { + return 35044; + } + } + + @Environment(EnvType.CLIENT) + public static class MappedView implements GpuBuffer.MappedView { + private final int target; + private final ByteBuffer data; + + protected MappedView(int i, ByteBuffer byteBuffer) { + this.target = i; + this.data = byteBuffer; + } + + @Override + public ByteBuffer data() { + return this.data; + } + + @Override + public void close() { +// GlStateManager._glUnmapBuffer(this.target); + } + } +} + diff --git a/src/main/java/net/vulkanmod/render/engine/VkGpuDevice.java b/src/main/java/net/vulkanmod/render/engine/VkGpuDevice.java new file mode 100644 index 000000000..6d5ec560d --- /dev/null +++ b/src/main/java/net/vulkanmod/render/engine/VkGpuDevice.java @@ -0,0 +1,404 @@ +package net.vulkanmod.render.engine; + +import com.mojang.blaze3d.buffers.GpuBuffer; +import com.mojang.blaze3d.opengl.*; +import com.mojang.blaze3d.pipeline.CompiledRenderPipeline; +import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.blaze3d.preprocessor.GlslPreprocessor; +import com.mojang.blaze3d.shaders.ShaderType; +import com.mojang.blaze3d.systems.CommandEncoder; +import com.mojang.blaze3d.systems.GpuDevice; +import com.mojang.blaze3d.textures.GpuTexture; +import com.mojang.blaze3d.textures.GpuTextureView; +import com.mojang.blaze3d.textures.TextureFormat; +import com.mojang.logging.LogUtils; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.renderer.ShaderDefines; +import net.minecraft.resources.ResourceLocation; +import net.vulkanmod.Initializer; +import net.vulkanmod.gl.VkGlTexture; +import net.vulkanmod.interfaces.shader.ExtendedRenderPipeline; +import net.vulkanmod.render.shader.ShaderLoadUtil; +import net.vulkanmod.vulkan.VRenderSystem; +import net.vulkanmod.vulkan.Vulkan; +import net.vulkanmod.vulkan.device.DeviceManager; +import net.vulkanmod.vulkan.shader.GraphicsPipeline; +import net.vulkanmod.vulkan.shader.Pipeline; +import net.vulkanmod.vulkan.shader.converter.GLSLParser; +import net.vulkanmod.vulkan.shader.converter.Lexer; +import net.vulkanmod.vulkan.shader.descriptor.UBO; +import net.vulkanmod.vulkan.texture.VulkanImage; +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.vulkan.VK10; +import org.slf4j.Logger; + +import java.nio.ByteBuffer; +import java.util.*; +import java.util.function.BiFunction; +import java.util.function.Supplier; + +@SuppressWarnings("NullableProblems") +public class VkGpuDevice implements GpuDevice { + private static final Logger LOGGER = LogUtils.getLogger(); + + private final VkCommandEncoder encoder; + private final VkDebugLabel debugLabels; + private final int maxSupportedTextureSize; + private final int uniformOffsetAlignment; + private final BiFunction defaultShaderSource; + private final Map pipelineCache = new IdentityHashMap<>(); + private final Map shaderCache = new HashMap<>(); + private final Set enabledExtensions = new HashSet<>(); + + private final Map shaderSrcCache = new HashMap<>(); + + public VkGpuDevice(long l, int i, boolean bl, BiFunction shaderSource, boolean bl2) { + this.debugLabels = VkDebugLabel.create(bl2, this.enabledExtensions); + this.maxSupportedTextureSize = VRenderSystem.maxSupportedTextureSize(); + this.uniformOffsetAlignment = (int) DeviceManager.deviceProperties.limits().minUniformBufferOffsetAlignment(); + this.defaultShaderSource = shaderSource; + + this.encoder = new VkCommandEncoder(this); + } + + public VkDebugLabel debugLabels() { + return this.debugLabels; + } + + @Override + public CommandEncoder createCommandEncoder() { + return this.encoder; + } + + @Override + public GpuTexture createTexture(@Nullable Supplier supplier, int usage, TextureFormat textureFormat, int width, int height, int layers, int mipLevels) { + return this.createTexture(this.debugLabels.exists() && supplier != null ? supplier.get() : null, usage, textureFormat, width, height, layers, mipLevels); + } + + @Override + public GpuTexture createTexture(@Nullable String string, int usage, TextureFormat textureFormat, int width, int height, int layers, int mipLevels) { + if (mipLevels < 1) { + throw new IllegalArgumentException("mipLevels must be at least 1"); + } else { + int id = VkGlTexture.genTextureId(); + if (string == null) { + string = String.valueOf(id); + } + + int format = VkGpuTexture.vkFormat(textureFormat); + int viewType = VkGpuTexture.vkImageViewType(usage); + boolean depthFormat = VulkanImage.isDepthFormat(format); + int attachmentUsage = depthFormat ? VK10.VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : VK10.VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + VulkanImage texture = VulkanImage.builder(width, height) + .setName(string) + .setFormat(format) + .setArrayLayers(layers) + .setMipLevels(mipLevels) + .addUsage(attachmentUsage) + .setViewType(viewType) + .createVulkanImage(); + + VkGlTexture vGlTexture = VkGlTexture.getTexture(id); + vGlTexture.setVulkanImage(texture); + VkGlTexture.bindTexture(id); + + VkGpuTexture glTexture = new VkGpuTexture(usage, string, textureFormat, width, height, layers, mipLevels, id, vGlTexture); + this.debugLabels.applyLabel(glTexture); + return glTexture; + } + } + + public VkGpuTexture gpuTextureFromVulkanImage(VulkanImage image) { + int id = VkGlTexture.genTextureId(); + VkGlTexture glTexture = VkGlTexture.getTexture(id); + glTexture.setVulkanImage(image); + TextureFormat textureFormat = VkGpuTexture.textureFormat(image.format); + VkGpuTexture gpuTexture = new VkGpuTexture(0, image.name, textureFormat, image.width, image.height, 1, image.mipLevels, id, glTexture); + this.debugLabels.applyLabel(gpuTexture); + return gpuTexture; + } + + @Override + public GpuTextureView createTextureView(GpuTexture gpuTexture) { + return this.createTextureView(gpuTexture, 0, gpuTexture.getMipLevels()); + } + + @Override + public GpuTextureView createTextureView(GpuTexture gpuTexture, int startLevel, int levels) { + if (gpuTexture.isClosed()) { + throw new IllegalArgumentException("Can't create texture view with closed texture"); + } else if (startLevel >= 0 && startLevel + levels <= gpuTexture.getMipLevels()) { + + // Try to convert gpuTexture to VkGpuTexture in case it's not + if (gpuTexture.getClass() != VkGpuTexture.class) { + gpuTexture = VkGpuTexture.fromGlTexture((GlTexture) gpuTexture); + } + + return new VkTextureView((VkGpuTexture) gpuTexture, startLevel, levels); + } else { + throw new IllegalArgumentException( + levels + " mip levels starting from " + startLevel + " would be out of range for texture with only " + gpuTexture.getMipLevels() + " mip levels" + ); + } + } + + @Override + public GpuBuffer createBuffer(@Nullable Supplier supplier, int usage, int size) { + if (size <= 0) { + throw new IllegalArgumentException("Buffer size must be greater than zero"); + } else { + return new VkGpuBuffer(this.debugLabels, supplier, usage, size); + } + } + + @Override + public GpuBuffer createBuffer(@Nullable Supplier supplier, int usage, ByteBuffer byteBuffer) { + if (!byteBuffer.hasRemaining()) { + throw new IllegalArgumentException("Buffer source must not be empty"); + } else { + VkGpuBuffer glBuffer = new VkGpuBuffer(this.debugLabels, supplier, usage, byteBuffer.remaining()); + this.encoder.writeToBuffer(glBuffer.slice(), byteBuffer); + return glBuffer; + } + } + + @Override + public String getImplementationInformation() { + return "Vulkan " + Vulkan.getDevice().vkVersion + ", " + Vulkan.getDevice().vendorIdString; + } + + @Override + public List getLastDebugMessages() { + return Collections.emptyList(); + } + + @Override + public boolean isDebuggingEnabled() { + return false; + } + + @Override + public String getRenderer() { + return DeviceManager.device.deviceName; + } + + @Override + public String getVendor() { + return Vulkan.getDevice().vendorIdString; + } + + @Override + public String getBackendName() { + return "Vulkan"; + } + + @Override + public String getVersion() { + return Vulkan.getDevice().vkVersion; + } + + private static int getMaxSupportedTextureSize() { + int i = GlStateManager._getInteger(3379); + + for (int j = Math.max(32768, i); j >= 1024; j >>= 1) { + GlStateManager._texImage2D(32868, 0, 6408, j, j, 0, 6408, 5121, null); + int k = GlStateManager._getTexLevelParameter(32868, 0, 4096); + if (k != 0) { + return j; + } + } + + int jx = Math.max(i, 1024); + LOGGER.info("Failed to determine maximum texture size by probing, trying GL_MAX_TEXTURE_SIZE = {}", jx); + return jx; + } + + @Override + public int getMaxTextureSize() { + return this.maxSupportedTextureSize; + } + + @Override + public int getUniformOffsetAlignment() { + return this.uniformOffsetAlignment; + } + + @Override + public void clearPipelineCache() { + for (GlRenderPipeline glRenderPipeline : this.pipelineCache.values()) { + if (glRenderPipeline.program() != GlProgram.INVALID_PROGRAM) { + glRenderPipeline.program().close(); + } + } + + this.pipelineCache.clear(); + + for (GlShaderModule glShaderModule : this.shaderCache.values()) { + if (glShaderModule != GlShaderModule.INVALID_SHADER) { + glShaderModule.close(); + } + } + + this.shaderCache.clear(); + } + + @Override + public List getEnabledExtensions() { + return new ArrayList(this.enabledExtensions); + } + + @Override + public void close() { + this.clearPipelineCache(); + } + + protected GlShaderModule getOrCompileShader( + ResourceLocation resourceLocation, ShaderType shaderType, ShaderDefines shaderDefines, BiFunction biFunction + ) { + ShaderCompilationKey shaderCompilationKey = new ShaderCompilationKey(resourceLocation, shaderType, shaderDefines); + return this.shaderCache.computeIfAbsent(shaderCompilationKey, shaderCompilationKey2 -> this.compileShader(shaderCompilationKey, biFunction)); + } + + protected String getCachedShaderSrc(ResourceLocation resourceLocation, ShaderType shaderType, ShaderDefines shaderDefines, BiFunction shaderSourceGetter) { + ShaderCompilationKey shaderCompilationKey = new ShaderCompilationKey(resourceLocation, shaderType, shaderDefines); + + return this.shaderSrcCache.computeIfAbsent(shaderCompilationKey, compilationKey -> { + String shaderExtension = switch (shaderType) { + case VERTEX -> ".vsh"; + case FRAGMENT -> ".fsh"; + }; + + String shaderName = resourceLocation.getPath() + shaderExtension; + + if (ShaderLoadUtil.REMAPPED_SHADERS.contains(shaderName)) { + String src = ShaderLoadUtil.getShaderSource(resourceLocation, shaderType); + + if (src == null) { + throw new RuntimeException("shader: (%s) not found."); + } + + return src; + } + + return shaderSourceGetter.apply(compilationKey.id, compilationKey.type); + }); + } + + public CompiledRenderPipeline precompilePipeline(RenderPipeline renderPipeline, @Nullable BiFunction shaderSourceGetter) { + shaderSourceGetter = shaderSourceGetter == null ? this.defaultShaderSource : shaderSourceGetter; + compilePipeline(renderPipeline, shaderSourceGetter); + + return new VkRenderPipeline(renderPipeline); + } + + public void compilePipeline(RenderPipeline renderPipeline) { + this.compilePipeline(renderPipeline, this.defaultShaderSource); + } + + private GlShaderModule compileShader(ShaderCompilationKey shaderCompilationKey, BiFunction biFunction) { + String string = biFunction.apply(shaderCompilationKey.id, shaderCompilationKey.type); + if (string == null) { + LOGGER.error("Couldn't find source for {} shader ({})", shaderCompilationKey.type, shaderCompilationKey.id); + return GlShaderModule.INVALID_SHADER; + } else { + String string2 = GlslPreprocessor.injectDefines(string, shaderCompilationKey.defines); + int i = GlStateManager.glCreateShader(GlConst.toGl(shaderCompilationKey.type)); + GlStateManager.glShaderSource(i, string2); + GlStateManager.glCompileShader(i); + if (GlStateManager.glGetShaderi(i, 35713) == 0) { + String string3 = StringUtils.trim(GlStateManager.glGetShaderInfoLog(i, 32768)); + LOGGER.error("Couldn't compile {} shader ({}): {}", shaderCompilationKey.type.getName(), shaderCompilationKey.id, string3); + return GlShaderModule.INVALID_SHADER; + } else { + GlShaderModule glShaderModule = new GlShaderModule(i, shaderCompilationKey.id, shaderCompilationKey.type); + this.debugLabels.applyLabel(glShaderModule); + return glShaderModule; + } + } + } + + private void compilePipeline(RenderPipeline renderPipeline, BiFunction shaderSrcGetter) { + String locationPath = renderPipeline.getLocation().getPath(); + + String configName; + if (locationPath.contains("core")) { + configName = locationPath.split("/")[1]; + } else { + configName = locationPath; + } + + Pipeline.Builder builder = new Pipeline.Builder(renderPipeline.getVertexFormat(), configName); + GraphicsPipeline pipeline; + ExtendedRenderPipeline extPipeline = ExtendedRenderPipeline.of(renderPipeline); + + ResourceLocation vertexShaderLocation = renderPipeline.getVertexShader(); + ResourceLocation fragmentShaderLocation = renderPipeline.getFragmentShader(); + + ShaderDefines shaderDefines = renderPipeline.getShaderDefines(); + + String vshSrc = this.getCachedShaderSrc(vertexShaderLocation, ShaderType.VERTEX, shaderDefines, shaderSrcGetter); + String fshSrc = this.getCachedShaderSrc(fragmentShaderLocation, ShaderType.FRAGMENT, shaderDefines, shaderSrcGetter); + + vshSrc = GlslPreprocessor.injectDefines(vshSrc, shaderDefines); + fshSrc = GlslPreprocessor.injectDefines(fshSrc, shaderDefines); + + Lexer lexer = new Lexer(vshSrc); + GLSLParser parser = new GLSLParser(); + parser.setVertexFormat(renderPipeline.getVertexFormat()); + + try { + parser.parse(lexer, GLSLParser.Stage.VERTEX); + + lexer = new Lexer(fshSrc); + parser.parse(lexer, GLSLParser.Stage.FRAGMENT); + } catch (Exception e) { + throw new RuntimeException("Caught exception while parsing: %s".formatted(renderPipeline.toString()), e); + } + + UBO[] ubos = parser.createUBOs(); + + String vshProcessed = parser.getOutput(GLSLParser.Stage.VERTEX); + String fshProcessed = parser.getOutput(GLSLParser.Stage.FRAGMENT); + + builder.setUniforms(List.of(ubos), parser.getSamplerList()); + builder.compileShaders(configName, vshProcessed, fshProcessed); + + try { + pipeline = builder.createGraphicsPipeline(); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Exception while compiling pipeline %s".formatted(renderPipeline)); + } + + EGlProgram eGlProgram = new EGlProgram(1, configName); + eGlProgram.setupUniforms(pipeline, renderPipeline.getUniforms(), renderPipeline.getSamplers()); + extPipeline.setProgram(eGlProgram); + + extPipeline.setPipeline(pipeline); + } + + @Environment(EnvType.CLIENT) + record ShaderCompilationKey(ResourceLocation id, ShaderType type, ShaderDefines defines) { + + public String toString() { + String string = this.id + " (" + this.type + ")"; + return !this.defines.isEmpty() ? string + " with " + this.defines : string; + } + } + + private static class VkRenderPipeline implements CompiledRenderPipeline { + final RenderPipeline renderPipeline; + + public VkRenderPipeline(RenderPipeline renderPipeline) { + this.renderPipeline = renderPipeline; + } + + @Override + public boolean isValid() { + return true; + } + } +} diff --git a/src/main/java/net/vulkanmod/render/engine/VkGpuTexture.java b/src/main/java/net/vulkanmod/render/engine/VkGpuTexture.java new file mode 100644 index 000000000..142769f0c --- /dev/null +++ b/src/main/java/net/vulkanmod/render/engine/VkGpuTexture.java @@ -0,0 +1,165 @@ +package net.vulkanmod.render.engine; + +import com.mojang.blaze3d.opengl.GlStateManager; +import com.mojang.blaze3d.opengl.GlTexture; +import com.mojang.blaze3d.textures.AddressMode; +import com.mojang.blaze3d.textures.FilterMode; +import com.mojang.blaze3d.textures.GpuTexture; +import com.mojang.blaze3d.textures.TextureFormat; +import it.unimi.dsi.fastutil.ints.*; +import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.vulkanmod.gl.VkGlTexture; +import net.vulkanmod.vulkan.texture.SamplerManager; +import net.vulkanmod.vulkan.texture.VulkanImage; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.vulkan.VK10; + +@Environment(EnvType.CLIENT) +public class VkGpuTexture extends GlTexture { + private static final Reference2ReferenceOpenHashMap glToVkMap = new Reference2ReferenceOpenHashMap<>(); + + protected VkGlTexture glTexture; + protected final int id; + private final Int2ReferenceMap fboCache = new Int2ReferenceOpenHashMap<>(); + protected boolean closed; + protected boolean modesDirty = true; + + boolean needsClear = false; + int clearColor = 0; + float depthClearValue = 1.0f; + + protected VkGpuTexture(int usage, String string, TextureFormat textureFormat, int width, int height, int layers, int mipLevel, int id, VkGlTexture glTexture) { + super(usage, string, textureFormat, width, height, layers, mipLevel, id); + this.id = id; + this.glTexture = glTexture; + } + + @Override + public void close() { + if (!this.closed) { + this.closed = true; + GlStateManager._deleteTexture(this.id); + + for (VkFbo fbo : this.fboCache.values()) { + fbo.close(); + } + } + } + + @Override + public boolean isClosed() { + return this.closed; + } + + public void flushModeChanges() { + if (this.modesDirty) { + int maxLod = this.useMipmaps ? this.getMipLevels() - 1 : 0; + + int magFilterVk = magFilter == FilterMode.LINEAR ? VK10.VK_FILTER_LINEAR : VK10.VK_FILTER_NEAREST; + int minFilterVk = minFilter == FilterMode.LINEAR ? VK10.VK_FILTER_LINEAR : VK10.VK_FILTER_NEAREST; + + int addressModeUVk = this.addressModeU == AddressMode.REPEAT ? VK10.VK_SAMPLER_ADDRESS_MODE_REPEAT : VK10.VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + int addressModeVVk = this.addressModeV == AddressMode.REPEAT ? VK10.VK_SAMPLER_ADDRESS_MODE_REPEAT : VK10.VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + + long sampler = SamplerManager.getSampler(addressModeUVk, addressModeVVk, + minFilterVk, magFilterVk, VK10.VK_SAMPLER_MIPMAP_MODE_LINEAR, + maxLod, false, 0, -1); + + glTexture.getVulkanImage().setSampler(sampler); + + this.modesDirty = false; + } + } + + public int glId() { + return this.id; + } + + @Override + public void setAddressMode(AddressMode addressMode, AddressMode addressMode2) { + super.setAddressMode(addressMode, addressMode2); + this.modesDirty = true; + } + + @Override + public void setTextureFilter(FilterMode filterMode, FilterMode filterMode2, boolean bl) { + super.setTextureFilter(filterMode, filterMode2, bl); + this.modesDirty = true; + } + + @Override + public void setUseMipmaps(boolean bl) { + super.setUseMipmaps(bl); + this.modesDirty = true; + } + + public void setClearColor(int clearColor) { + this.needsClear = true; + this.clearColor = clearColor; + } + + public void setDepthClearValue(float depthClearValue) { + this.needsClear = true; + this.depthClearValue = depthClearValue; + } + + public boolean needsClear() { + return needsClear; + } + + public VkFbo getFbo(@Nullable GpuTexture depthAttachment) { + int depthAttachmentId = depthAttachment == null ? 0 : ((VkGpuTexture)depthAttachment).id; + return this.fboCache.computeIfAbsent(depthAttachmentId, j -> new VkFbo(this, (VkGpuTexture) depthAttachment)); + } + + public VulkanImage getVulkanImage() { + return glTexture.getVulkanImage(); + } + + public static VkGpuTexture fromGlTexture(GlTexture glTexture) { + return glToVkMap.computeIfAbsent(glTexture, glTexture1 -> { + var name = glTexture.getLabel(); + int id = glTexture.glId(); + VkGlTexture vglTexture = VkGlTexture.getTexture(id); + VkGpuTexture gpuTexture = new VkGpuTexture(0, name, glTexture.getFormat(), + glTexture.getWidth(0), glTexture.getHeight(0), + 1, glTexture.getMipLevels(), + glTexture.glId(), vglTexture); + + return gpuTexture; + }); + } + + public static TextureFormat textureFormat(int format) { + return switch (format) { + case VK10.VK_FORMAT_R8G8B8A8_UNORM, VK10.VK_FORMAT_B8G8R8A8_UNORM, VK10.VK_FORMAT_R8G8B8A8_SRGB -> TextureFormat.RGBA8; + case VK10.VK_FORMAT_R8_UNORM -> TextureFormat.RED8; + case VK10.VK_FORMAT_D32_SFLOAT -> TextureFormat.DEPTH32; + default -> null; + }; + } + + public static int vkFormat(TextureFormat textureFormat) { + return switch (textureFormat) { + case RGBA8 -> VK10.VK_FORMAT_R8G8B8A8_UNORM; + case RED8 -> VK10.VK_FORMAT_R8_UNORM; + case RED8I -> VK10.VK_FORMAT_R8_SINT; + case DEPTH32 -> VK10.VK_FORMAT_D32_SFLOAT; + }; + } + + public static int vkImageViewType(int usage) { + int viewType; + if ((usage & GpuTexture.USAGE_CUBEMAP_COMPATIBLE) != 0) { + viewType = VK10.VK_IMAGE_VIEW_TYPE_CUBE; + } + else { + viewType = VK10.VK_IMAGE_VIEW_TYPE_2D; + } + + return viewType; + } +} + diff --git a/src/main/java/net/vulkanmod/render/engine/VkRenderPass.java b/src/main/java/net/vulkanmod/render/engine/VkRenderPass.java new file mode 100644 index 000000000..8d9c039bc --- /dev/null +++ b/src/main/java/net/vulkanmod/render/engine/VkRenderPass.java @@ -0,0 +1,212 @@ +package net.vulkanmod.render.engine; + +import com.mojang.blaze3d.buffers.GpuBuffer; +import com.mojang.blaze3d.buffers.GpuBufferSlice; +import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.blaze3d.systems.RenderPass; +import com.mojang.blaze3d.systems.ScissorState; +import com.mojang.blaze3d.textures.GpuTexture; +import com.mojang.blaze3d.textures.GpuTextureView; +import com.mojang.blaze3d.vertex.VertexFormat; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; +import java.util.function.Supplier; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.SharedConstants; +import net.vulkanmod.interfaces.shader.ExtendedRenderPipeline; +import org.jetbrains.annotations.Nullable; +import org.joml.Matrix4f; + +@Environment(EnvType.CLIENT) +public class VkRenderPass implements RenderPass { + protected static final int MAX_VERTEX_BUFFERS = 1; + public static final boolean VALIDATION = SharedConstants.IS_RUNNING_IN_IDE; + private final VkCommandEncoder encoder; + private final boolean hasDepthTexture; + private boolean closed; + @Nullable + protected RenderPipeline pipeline; + protected final GpuBuffer[] vertexBuffers = new GpuBuffer[1]; + @Nullable + protected GpuBuffer indexBuffer; + protected VertexFormat.IndexType indexType = VertexFormat.IndexType.INT; + private final ScissorState scissorState = new ScissorState(); + protected final HashMap uniforms = new HashMap<>(); + protected final HashMap samplers = new HashMap<>(); + protected final Set dirtyUniforms = new HashSet<>(); + protected int pushedDebugGroups; + + public VkRenderPass(VkCommandEncoder commandEncoder, boolean bl) { + this.encoder = commandEncoder; + this.hasDepthTexture = bl; + } + + public boolean hasDepthTexture() { + return this.hasDepthTexture; + } + + @Override + public void pushDebugGroup(Supplier supplier) { + if (this.closed) { + throw new IllegalStateException("Can't use a closed render pass"); + } else { + this.pushedDebugGroups++; +// this.encoder.getDevice().debugLabels().pushDebugGroup(supplier); + } + } + + @Override + public void popDebugGroup() { + if (this.closed) { + throw new IllegalStateException("Can't use a closed render pass"); + } else if (this.pushedDebugGroups == 0) { + throw new IllegalStateException("Can't pop more debug groups than was pushed!"); + } else { + this.pushedDebugGroups--; +// this.encoder.getDevice().debugLabels().popDebugGroup(); + } + } + + @Override + public void setPipeline(RenderPipeline renderPipeline) { + if (this.pipeline == null || this.pipeline != renderPipeline) { + this.dirtyUniforms.addAll(this.uniforms.keySet()); + } + + + this.pipeline = renderPipeline; + + if (ExtendedRenderPipeline.of(renderPipeline).getPipeline() == null) { + this.encoder.getDevice().compilePipeline(renderPipeline); + } + } + + @Override + public void bindSampler(String string, @Nullable GpuTextureView gpuTextureView) { + if (gpuTextureView == null) { + this.samplers.remove(string); + } else { + this.samplers.put(string, gpuTextureView); + } + + this.dirtyUniforms.add(string); + } + + @Override + public void setUniform(String string, GpuBuffer gpuBuffer) { + this.uniforms.put(string, gpuBuffer.slice()); + this.dirtyUniforms.add(string); + } + + @Override + public void setUniform(String string, GpuBufferSlice gpuBufferSlice) { + int i = this.encoder.getDevice().getUniformOffsetAlignment(); + if (gpuBufferSlice.offset() % i > 0) { + throw new IllegalArgumentException("Uniform buffer offset must be aligned to " + i); + } else { + this.uniforms.put(string, gpuBufferSlice); + this.dirtyUniforms.add(string); + } + } + + @Override + public void enableScissor(int i, int j, int k, int l) { + this.scissorState.enable(i, j, k, l); + } + + @Override + public void disableScissor() { + this.scissorState.disable(); + } + + public boolean isScissorEnabled() { + return this.scissorState.enabled(); + } + + public int getScissorX() { + return this.scissorState.x(); + } + + public int getScissorY() { + return this.scissorState.y(); + } + + public int getScissorWidth() { + return this.scissorState.width(); + } + + public int getScissorHeight() { + return this.scissorState.height(); + } + + public ScissorState getScissorState() { return this.scissorState; } + + @Override + public void setVertexBuffer(int i, GpuBuffer gpuBuffer) { + if (i >= 0 && i < 1) { + this.vertexBuffers[i] = gpuBuffer; + } else { + throw new IllegalArgumentException("Vertex buffer slot is out of range: " + i); + } + } + + @Override + public void setIndexBuffer(@Nullable GpuBuffer gpuBuffer, VertexFormat.IndexType indexType) { + this.indexBuffer = gpuBuffer; + this.indexType = indexType; + } + + @Override + public void drawIndexed(int i, int j, int k, int l) { + if (this.closed) { + throw new IllegalStateException("Can't use a closed render pass"); + } else { + this.encoder.executeDraw(this, i, j, k, this.indexType, l); + } + } + + @Override + public void drawMultipleIndexed( + Collection> collection, + @Nullable GpuBuffer gpuBuffer, + @Nullable VertexFormat.IndexType indexType, + Collection collection2, + T object + ) { + if (this.closed) { + throw new IllegalStateException("Can't use a closed render pass"); + } else { + this.encoder.executeDrawMultiple(this, collection, gpuBuffer, indexType, collection2, object); + } + } + + @Override + public void draw(int i, int j) { + if (this.closed) { + throw new IllegalStateException("Can't use a closed render pass"); + } else { + this.encoder.executeDraw(this, i, 0, j, null, 1); + } + } + + @Override + public void close() { + if (!this.closed) { + if (this.pushedDebugGroups > 0) { + throw new IllegalStateException("Render pass had debug groups left open!"); + } + + this.closed = true; + this.encoder.finishRenderPass(); + } + } + + public @Nullable RenderPipeline getPipeline() { + return pipeline; + } +} + diff --git a/src/main/java/net/vulkanmod/render/engine/VkTextureView.java b/src/main/java/net/vulkanmod/render/engine/VkTextureView.java new file mode 100644 index 000000000..8ad3c6b79 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/engine/VkTextureView.java @@ -0,0 +1,29 @@ +package net.vulkanmod.render.engine; + +import com.mojang.blaze3d.textures.GpuTextureView; + +public class VkTextureView extends GpuTextureView { + private boolean closed; + + protected VkTextureView(VkGpuTexture gpuTexture, int i, int j) { + super(gpuTexture, i, j); + gpuTexture.addViews(); + } + + @Override + public boolean isClosed() { + return this.closed; + } + + @Override + public void close() { + if (!this.closed) { + this.closed = true; + this.texture().removeViews(); + } + } + + public VkGpuTexture texture() { + return (VkGpuTexture) super.texture(); + } +} diff --git a/src/main/java/net/vulkanmod/render/gui/GuiBatchRenderer.java b/src/main/java/net/vulkanmod/render/gui/GuiBatchRenderer.java deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/main/java/net/vulkanmod/render/model/CubeModel.java b/src/main/java/net/vulkanmod/render/model/CubeModel.java index da988f39d..ef5bb5548 100644 --- a/src/main/java/net/vulkanmod/render/model/CubeModel.java +++ b/src/main/java/net/vulkanmod/render/model/CubeModel.java @@ -1,15 +1,15 @@ package net.vulkanmod.render.model; -import net.minecraft.client.model.geom.ModelPart; import net.minecraft.core.Direction; import org.joml.Matrix4f; import org.joml.Vector3f; +import org.joml.Vector3fc; import java.util.Set; public class CubeModel { - private ModelPart.Polygon[] polygons = new ModelPart.Polygon[6]; + private Polygon[] polygons; public float minX; public float minY; public float minZ; @@ -17,99 +17,165 @@ public class CubeModel { public float maxY; public float maxZ; - Vector3f[] vertices; - Vector3f[] transformed = new Vector3f[8]; - - public void setVertices(int i, int j, float f, float g, float h, float k, float l, float m, float n, float o, float p, boolean bl, float q, float r, Set set) { - this.minX = f; - this.minY = g; - this.minZ = h; - this.maxX = f + k; - this.maxY = g + l; - this.maxZ = h + m; - this.polygons = new ModelPart.Polygon[set.size()]; + Vertex[] vertices; + + public void setVertices(int u, int v, float minX, float minY, float minZ, float dimX, float dimY, float dimZ, float growX, float growY, float growZ, boolean mirror, float uTexScale, float vTexScale, Set set) { + this.minX = minX; + this.minY = minY; + this.minZ = minZ; + this.maxX = minX + dimX; + this.maxY = minY + dimY; + this.maxZ = minZ + dimZ; + this.polygons = new Polygon[set.size()]; float s = maxX; float t = maxY; - float u = maxZ; - f -= n; - g -= o; - h -= p; - s += n; - t += o; - u += p; - if (bl) { - float v = s; - s = f; - f = v; - } - - this.vertices = new Vector3f[]{ - new Vector3f(f, g, h), - new Vector3f(s, g, h), - new Vector3f(s, t, h), - new Vector3f(f, t, h), - new Vector3f(f, g, u), - new Vector3f(s, g, u), - new Vector3f(s, t, u), - new Vector3f(f, t, u) + float u1 = maxZ; + minX -= growX; + minY -= growY; + minZ -= growZ; + s += growX; + t += growY; + u1 += growZ; + if (mirror) { + float v1 = s; + s = minX; + minX = v1; + } + + this.vertices = new Vertex[]{ + new Vertex(minX, minY, minZ, 0.0F, 0.0F), + new Vertex(s, minY, minZ, 0.0F, 8.0F), + new Vertex(s, t, minZ, 8.0F, 8.0F), + new Vertex(minX, t, minZ, 8.0F, 0.0F), + new Vertex(minX, minY, u1, 0.0F, 0.0F), + new Vertex(s, minY, u1, 0.0F, 8.0F), + new Vertex(s, t, u1, 8.0F, 8.0F), + new Vertex(minX, t, u1, 8.0F, 0.0F) }; - for (int i1 = 0; i1 < 8; i1++) { - //pre-divide all vertices once - this.vertices[i1].div(16.0f); - this.transformed[i1] = new Vector3f(0.0f); - } - - ModelPart.Vertex vertex1 = new ModelPart.Vertex(transformed[0], 0.0F, 0.0F); - ModelPart.Vertex vertex2 = new ModelPart.Vertex(transformed[1], 0.0F, 8.0F); - ModelPart.Vertex vertex3 = new ModelPart.Vertex(transformed[2], 8.0F, 8.0F); - ModelPart.Vertex vertex4 = new ModelPart.Vertex(transformed[3], 8.0F, 0.0F); - ModelPart.Vertex vertex5 = new ModelPart.Vertex(transformed[4], 0.0F, 0.0F); - ModelPart.Vertex vertex6 = new ModelPart.Vertex(transformed[5], 0.0F, 8.0F); - ModelPart.Vertex vertex7 = new ModelPart.Vertex(transformed[6], 8.0F, 8.0F); - ModelPart.Vertex vertex8 = new ModelPart.Vertex(transformed[7], 8.0F, 0.0F); - - float w = (float)i; - float x = (float)i + m; - float y = (float)i + m + k; - float z = (float)i + m + k + k; - float aa = (float)i + m + k + m; - float ab = (float)i + m + k + m + k; - float ac = (float)j; - float ad = (float)j + m; - float ae = (float)j + m + l; + float w = (float)u; + float x = (float)u + dimZ; + float y = (float)u + dimZ + dimX; + float z = (float)u + dimZ + dimX + dimX; + float aa = (float)u + dimZ + dimX + dimZ; + float ab = (float)u + dimZ + dimX + dimZ + dimX; + float ac = (float)v; + float ad = (float)v + dimZ; + float ae = (float)v + dimZ + dimY; + + Vertex vertex1 = this.vertices[0]; + Vertex vertex2 = this.vertices[1]; + Vertex vertex3 = this.vertices[2]; + Vertex vertex4 = this.vertices[3]; + Vertex vertex5 = this.vertices[4]; + Vertex vertex6 = this.vertices[5]; + Vertex vertex7 = this.vertices[6]; + Vertex vertex8 = this.vertices[7]; + int idx = 0; if (set.contains(Direction.DOWN)) { - this.polygons[idx++] = new ModelPart.Polygon(new ModelPart.Vertex[]{vertex6, vertex5, vertex1, vertex2}, x, ac, y, ad, q, r, bl, Direction.DOWN); + this.polygons[idx++] = new Polygon(new Vertex[]{vertex6, vertex5, vertex1, vertex2}, x, ac, y, ad, uTexScale, vTexScale, mirror, Direction.DOWN); } if (set.contains(Direction.UP)) { - this.polygons[idx++] = new ModelPart.Polygon(new ModelPart.Vertex[]{vertex3, vertex4, vertex8, vertex7}, y, ad, z, ac, q, r, bl, Direction.UP); + this.polygons[idx++] = new Polygon(new Vertex[]{vertex3, vertex4, vertex8, vertex7}, y, ad, z, ac, uTexScale, vTexScale, mirror, Direction.UP); } if (set.contains(Direction.WEST)) { - this.polygons[idx++] = new ModelPart.Polygon(new ModelPart.Vertex[]{vertex1, vertex5, vertex8, vertex4}, w, ad, x, ae, q, r, bl, Direction.WEST); + this.polygons[idx++] = new Polygon(new Vertex[]{vertex1, vertex5, vertex8, vertex4}, w, ad, x, ae, uTexScale, vTexScale, mirror, Direction.WEST); } if (set.contains(Direction.NORTH)) { - this.polygons[idx++] = new ModelPart.Polygon(new ModelPart.Vertex[]{vertex2, vertex1, vertex4, vertex3}, x, ad, y, ae, q, r, bl, Direction.NORTH); + this.polygons[idx++] = new Polygon(new Vertex[]{vertex2, vertex1, vertex4, vertex3}, x, ad, y, ae, uTexScale, vTexScale, mirror, Direction.NORTH); } if (set.contains(Direction.EAST)) { - this.polygons[idx++] = new ModelPart.Polygon(new ModelPart.Vertex[]{vertex6, vertex2, vertex3, vertex7}, y, ad, aa, ae, q, r, bl, Direction.EAST); + this.polygons[idx++] = new Polygon(new Vertex[]{vertex6, vertex2, vertex3, vertex7}, y, ad, aa, ae, uTexScale, vTexScale, mirror, Direction.EAST); } if (set.contains(Direction.SOUTH)) { - this.polygons[idx] = new ModelPart.Polygon(new ModelPart.Vertex[]{vertex5, vertex6, vertex7, vertex8}, aa, ad, ab, ae, q, r, bl, Direction.SOUTH); + this.polygons[idx] = new Polygon(new Vertex[]{vertex5, vertex6, vertex7, vertex8}, aa, ad, ab, ae, uTexScale, vTexScale, mirror, Direction.SOUTH); } } public void transformVertices(Matrix4f matrix) { - //Transform original vertices and store them - for(int i = 0; i < 8; ++i) { - this.vertices[i].mulPosition(matrix, this.transformed[i]); + // Transform original vertices and store them + for (int i = 0; i < 8; ++i) { + Vertex vertex = this.vertices[i]; + vertex.pos.mulPosition(matrix, vertex.transformed); + } + } + + public Polygon[] getPolygons() { + return this.polygons; + } + + public record Polygon(Vertex[] vertices, Vector3fc normal) { + + public Polygon(Vertex[] vertices, float u0, float v0, float u1, float v1, float uSize, float vSize, boolean mirror, Direction direction) { + this(vertices, (mirror ? mirrorFacing(direction) : direction).getUnitVec3f()); + + // This will force NaN if uSize or vSize are 0 + float l = 0.0F / uSize; + float m = 0.0F / vSize; + + vertices[0] = vertices[0].remap(u1 / uSize - l, v0 / vSize + m); + vertices[1] = vertices[1].remap(u0 / uSize + l, v0 / vSize + m); + vertices[2] = vertices[2].remap(u0 / uSize + l, v1 / vSize - m); + vertices[3] = vertices[3].remap(u1 / uSize - l, v1 / vSize - m); + + if (mirror) { + int n = vertices.length; + + for (int o = 0; o < n / 2; o++) { + Vertex vertex = vertices[o]; + vertices[o] = vertices[n - 1 - o]; + vertices[n - 1 - o] = vertex; + } + } + } + + private static Direction mirrorFacing(Direction direction) { + return direction.getAxis() == Direction.Axis.X ? direction.getOpposite() : direction; + } + } + + public static class Vertex { + private static final float SCALE_FACTOR = 16.0F; + + final Vector3f pos; + final Vector3f transformed; + float u, v; + + public Vertex(float x, float y, float z, float u, float v) { + this.pos = new Vector3f(x / SCALE_FACTOR, y / SCALE_FACTOR, z / SCALE_FACTOR); + this.transformed = new Vector3f(); + this.u = u; + this.v = v; + } + + public Vertex(Vector3f pos, Vector3f transformed, float u, float v) { + this.pos = pos; + this.transformed = transformed; + this.u = u; + this.v = v; + } + + Vertex remap(float u, float v) { + return new Vertex(this.pos, this.transformed, u, v); + } + + public Vector3f pos() { + return transformed; + } + + public float u() { + return u; + } + + public float v() { + return v; } } - public ModelPart.Polygon[] getPolygons() { return this.polygons; } } diff --git a/src/main/java/net/vulkanmod/render/model/quad/ModelQuad.java b/src/main/java/net/vulkanmod/render/model/quad/ModelQuad.java index efeebc0bd..d87df233d 100644 --- a/src/main/java/net/vulkanmod/render/model/quad/ModelQuad.java +++ b/src/main/java/net/vulkanmod/render/model/quad/ModelQuad.java @@ -2,10 +2,18 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.core.Direction; +import net.vulkanmod.render.chunk.cull.QuadFacing; -public class ModelQuad implements QuadView { +/** + * Only used by FluidRenderer + */ +public class ModelQuad implements ModelQuadView { public static final int VERTEX_SIZE = 8; + public static int vertexOffset(int vertexIndex) { + return vertexIndex * VERTEX_SIZE; + } + private final int[] data = new int[4 * VERTEX_SIZE]; Direction direction; @@ -58,6 +66,21 @@ public Direction getFacingDirection() { return this.direction; } + @Override + public Direction lightFace() { + return this.direction; + } + + @Override + public QuadFacing getQuadFacing() { + return QuadFacing.UNDEFINED; + } + + @Override + public int getNormal() { + return 0; + } + public float setX(int idx, float f) { return this.data[vertexOffset(idx)] = Float.floatToRawIntBits(f); } @@ -88,8 +111,4 @@ public void setFlags(int f) { public void setSprite(TextureAtlasSprite sprite) { this.sprite = sprite; } - - private static int vertexOffset(int vertexIndex) { - return vertexIndex * VERTEX_SIZE; - } } diff --git a/src/main/java/net/vulkanmod/render/model/quad/ModelQuadFlags.java b/src/main/java/net/vulkanmod/render/model/quad/ModelQuadFlags.java index 9016cb4aa..bb1dc0cca 100644 --- a/src/main/java/net/vulkanmod/render/model/quad/ModelQuadFlags.java +++ b/src/main/java/net/vulkanmod/render/model/quad/ModelQuadFlags.java @@ -2,8 +2,6 @@ import net.minecraft.core.Direction; -import static net.vulkanmod.render.model.quad.ModelQuad.VERTEX_SIZE; - public class ModelQuadFlags { /** * Indicates that the quad does not fully cover the given face for the model. @@ -25,7 +23,7 @@ public static boolean contains(int flags, int mask) { return (flags & mask) != 0; } - public static int getQuadFlags(int[] vertices, Direction face) { + public static int getQuadFlags(ModelQuadView quad, Direction face) { float minX = 32.0F; float minY = 32.0F; float minZ = 32.0F; @@ -35,9 +33,9 @@ public static int getQuadFlags(int[] vertices, Direction face) { float maxZ = -32.0F; for (int i = 0; i < 4; ++i) { - float x = Float.intBitsToFloat(vertices[i * VERTEX_SIZE]); - float y = Float.intBitsToFloat(vertices[i * VERTEX_SIZE + 1]); - float z = Float.intBitsToFloat(vertices[i * VERTEX_SIZE + 2]); + float x = quad.getX(i); + float y = quad.getY(i); + float z = quad.getZ(i); minX = Math.min(minX, x); minY = Math.min(minY, y); diff --git a/src/main/java/net/vulkanmod/render/model/quad/QuadView.java b/src/main/java/net/vulkanmod/render/model/quad/ModelQuadView.java similarity index 71% rename from src/main/java/net/vulkanmod/render/model/quad/QuadView.java rename to src/main/java/net/vulkanmod/render/model/quad/ModelQuadView.java index 883c4b315..ac791d9a5 100644 --- a/src/main/java/net/vulkanmod/render/model/quad/QuadView.java +++ b/src/main/java/net/vulkanmod/render/model/quad/ModelQuadView.java @@ -1,8 +1,9 @@ package net.vulkanmod.render.model.quad; import net.minecraft.core.Direction; +import net.vulkanmod.render.chunk.cull.QuadFacing; -public interface QuadView { +public interface ModelQuadView { int getFlags(); @@ -22,6 +23,12 @@ public interface QuadView { Direction getFacingDirection(); + Direction lightFace(); + + QuadFacing getQuadFacing(); + + int getNormal(); + default boolean isTinted() { return this.getColorIndex() != -1; } diff --git a/src/main/java/net/vulkanmod/render/profiling/DebugEntryMemoryStats.java b/src/main/java/net/vulkanmod/render/profiling/DebugEntryMemoryStats.java new file mode 100644 index 000000000..7742cc0e1 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/profiling/DebugEntryMemoryStats.java @@ -0,0 +1,28 @@ +package net.vulkanmod.render.profiling; + +import net.minecraft.client.gui.components.debug.DebugScreenDisplayer; +import net.minecraft.client.gui.components.debug.DebugScreenEntry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.chunk.LevelChunk; +import net.vulkanmod.render.chunk.WorldRenderer; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class DebugEntryMemoryStats implements DebugScreenEntry { + private static final ResourceLocation GROUP = ResourceLocation.withDefaultNamespace("vk_memory"); + + @Override + public void display(DebugScreenDisplayer debugScreenDisplayer, @Nullable Level level, + @Nullable LevelChunk levelChunk, @Nullable LevelChunk levelChunk2) { + var chunkAreaManager = WorldRenderer.getInstance().getChunkAreaManager(); + + if (chunkAreaManager != null) { + debugScreenDisplayer.addToGroup( + GROUP, + List.of(chunkAreaManager.getStats()) + ); + } + } +} diff --git a/src/main/java/net/vulkanmod/render/profiling/Profiler.java b/src/main/java/net/vulkanmod/render/profiling/Profiler.java index a5a34318c..ccfe5cb59 100644 --- a/src/main/java/net/vulkanmod/render/profiling/Profiler.java +++ b/src/main/java/net/vulkanmod/render/profiling/Profiler.java @@ -37,6 +37,7 @@ public static void setActive(boolean b) { ObjectArrayList nodeStack = new ObjectArrayList<>(); ObjectArrayList nodes = new ObjectArrayList<>(); + ObjectArrayList currentFrameNodes = new ObjectArrayList<>(); Object2ReferenceOpenHashMap nodeMap = new Object2ReferenceOpenHashMap<>(); Node mainNode; @@ -67,7 +68,7 @@ public void push(String s) { node.children.clear(); if (node.parent == selectedNode) - nodes.add(node); + currentFrameNodes.add(node); currentNode = node; @@ -118,7 +119,10 @@ public void start() { pushNodeStack(mainNode); - nodes.clear(); + var t = nodes; + nodes = currentFrameNodes; + currentFrameNodes = t; + currentFrameNodes.clear(); } public void end() { diff --git a/src/main/java/net/vulkanmod/render/profiling/ProfilerOverlay.java b/src/main/java/net/vulkanmod/render/profiling/ProfilerOverlay.java index d75fcdbd4..ed85d1a97 100644 --- a/src/main/java/net/vulkanmod/render/profiling/ProfilerOverlay.java +++ b/src/main/java/net/vulkanmod/render/profiling/ProfilerOverlay.java @@ -1,17 +1,17 @@ package net.vulkanmod.render.profiling; import com.google.common.base.Strings; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.DefaultVertexFormat; -import com.mojang.blaze3d.vertex.VertexFormat; +import net.minecraft.SharedConstants; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; -import net.vulkanmod.config.gui.GuiRenderer; +import net.vulkanmod.Initializer; +import net.vulkanmod.config.gui.render.GuiRenderer; import net.vulkanmod.render.chunk.WorldRenderer; import net.vulkanmod.render.chunk.build.task.ChunkTask; import net.vulkanmod.render.chunk.build.thread.BuilderResources; +import net.vulkanmod.vulkan.VRenderSystem; import net.vulkanmod.vulkan.memory.MemoryManager; import net.vulkanmod.vulkan.util.ColorUtil; @@ -56,7 +56,6 @@ public static void onKeyPress(int key) { public void render(GuiGraphics guiGraphics) { GuiRenderer.guiGraphics = guiGraphics; - GuiRenderer.pose = guiGraphics.pose(); List infoList = this.buildInfo(); @@ -67,8 +66,7 @@ public void render(GuiGraphics guiGraphics) { Objects.requireNonNull(this.font); - RenderSystem.enableBlend(); - GuiRenderer.beginBatch(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); + VRenderSystem.enableBlend(); for (int i = 0; i < infoList.size(); ++i) { String line = infoList.get(i); @@ -82,8 +80,7 @@ public void render(GuiGraphics guiGraphics) { } } - GuiRenderer.endBatch(); - RenderSystem.disableBlend(); + VRenderSystem.disableBlend(); for (int i = 0; i < infoList.size(); ++i) { String line = infoList.get(i); @@ -101,16 +98,26 @@ private List buildInfo() { List list = new ArrayList<>(); list.add(""); list.add("Profiler"); + list.add("Version: %s %s ".formatted(Initializer.getVersion(), SharedConstants.getCurrentVersion().name())); this.updateResults(); - if (lastResults == null) + if (lastResults == null) { return list; + } + + var partialResults = lastResults.getPartialResults(); + if (partialResults.size() < 2) { + return list; + } int fps = Math.round(1000.0f / frametime); list.add(String.format("FPS: %d Frametime: %.3f", fps, frametime)); list.add(""); + list.add(String.format("CPU fence wait time: %.3f", partialResults.get(1).value)); + list.add(""); + for (Profiler.Result result : lastResults.getPartialResults()) { list.add(String.format("%s: %.3f", result.name, result.value)); } @@ -123,8 +130,9 @@ private List buildInfo() { list.add(""); list.add(String.format("Build time: %.0fms", BuildTimeProfiler.getDeltaTime())); - if (ChunkTask.BENCH) + if (ChunkTask.BENCH) { list.add(buildStats); + } return list; } diff --git a/src/main/java/net/vulkanmod/render/shader/CustomRenderPipelines.java b/src/main/java/net/vulkanmod/render/shader/CustomRenderPipelines.java new file mode 100644 index 000000000..07ca57f3c --- /dev/null +++ b/src/main/java/net/vulkanmod/render/shader/CustomRenderPipelines.java @@ -0,0 +1,31 @@ +package net.vulkanmod.render.shader; + +import com.mojang.blaze3d.pipeline.BlendFunction; +import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.blaze3d.platform.DepthTestFunction; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.VertexFormat; +import net.minecraft.client.renderer.RenderPipelines; + +import java.util.ArrayList; +import java.util.List; + +public class CustomRenderPipelines { + + public static final List pipelines = new ArrayList<>(); + + public static final RenderPipeline.Snippet GUI_TRIANGLES_SNIPPET = RenderPipeline.builder(RenderPipelines.MATRICES_PROJECTION_SNIPPET) + .withVertexShader("core/gui") + .withFragmentShader("core/gui") + .withBlend(BlendFunction.TRANSLUCENT) + .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.TRIANGLES) + .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST) + .buildSnippet(); + + public static final RenderPipeline GUI_TRIANGLES = register(RenderPipeline.builder(GUI_TRIANGLES_SNIPPET).withLocation("pipeline/gui").build()); + + static RenderPipeline register(RenderPipeline pipeline) { + pipelines.add(pipeline); + return pipeline; + } +} diff --git a/src/main/java/net/vulkanmod/render/shader/ShaderLoadUtil.java b/src/main/java/net/vulkanmod/render/shader/ShaderLoadUtil.java new file mode 100644 index 000000000..0a224062f --- /dev/null +++ b/src/main/java/net/vulkanmod/render/shader/ShaderLoadUtil.java @@ -0,0 +1,259 @@ +package net.vulkanmod.render.shader; + +import com.google.common.collect.Sets; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.mojang.blaze3d.shaders.ShaderType; +import net.minecraft.resources.ResourceLocation; +import net.vulkanmod.vulkan.shader.Pipeline; +import net.vulkanmod.vulkan.shader.SPIRVUtils; +import org.apache.commons.io.IOUtils; + +import java.io.*; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Set; + +public abstract class ShaderLoadUtil { + + public static final String RESOURCES_PATH = SPIRVUtils.class.getResource("/assets/vulkanmod").toExternalForm(); + public static final String SHADERS_PATH = "%s/shaders/".formatted(RESOURCES_PATH); + + public static final Set REMAPPED_SHADERS = Sets.newHashSet("core/screenquad.vsh","core/rendertype_item_entity_translucent_cull.vsh"); + + public static String resolveShaderPath(String path) { + return resolveShaderPath(SHADERS_PATH, path); + } + + public static String resolveShaderPath(String shaderPath, String path) { + return "%s%s".formatted(shaderPath, path); + } + + public static void loadShaders(Pipeline.Builder pipelineBuilder, JsonObject config, String configName, String path) { + String vertexShader = config.has("vertex") ? config.get("vertex").getAsString() : configName; + String fragmentShader = config.has("fragment") ? config.get("fragment").getAsString() : configName; + + if (vertexShader == null) { + vertexShader = configName; + } + if (fragmentShader == null) { + fragmentShader = configName; + } + + vertexShader = removeNameSpace(vertexShader); + fragmentShader = removeNameSpace(fragmentShader); + + vertexShader = getFileName(vertexShader); + fragmentShader = getFileName(fragmentShader); + + loadShader(pipelineBuilder, configName, path, vertexShader, SPIRVUtils.ShaderKind.VERTEX_SHADER); + loadShader(pipelineBuilder, configName, path, fragmentShader, SPIRVUtils.ShaderKind.FRAGMENT_SHADER); + } + + public static void loadShader(Pipeline.Builder pipelineBuilder, String configName, String path, SPIRVUtils.ShaderKind type) { + String[] splitPath = splitPath(path); + String shaderName = splitPath[1]; + String subPath = splitPath[0]; + + loadShader(pipelineBuilder, configName, subPath, shaderName, type); + } + + public static void loadShader(Pipeline.Builder pipelineBuilder, String configName, String path, String shaderName, SPIRVUtils.ShaderKind type) { + String source = getShaderSource(path, configName, shaderName, type); + + SPIRVUtils.SPIRV spirv = SPIRVUtils.compileShader(shaderName, source, type); + + switch (type) { + case VERTEX_SHADER -> pipelineBuilder.setVertShaderSPIRV(spirv); + case FRAGMENT_SHADER -> pipelineBuilder.setFragShaderSPIRV(spirv); + } + } + + public static String getConfigFilePath(String path, String rendertype) { + String basePath = "%s/shaders/%s".formatted(RESOURCES_PATH, path); + String configPath = "%s/%s/%s.json".formatted(basePath, rendertype, rendertype); + + Path filePath; + try { + filePath = FileSystems.getDefault().getPath(configPath); + + if (!Files.exists(filePath)) { + configPath = "%s/%s.json".formatted(basePath, rendertype); + filePath = FileSystems.getDefault().getPath(configPath); + } + + if (!Files.exists(filePath)) { + return null; + } + } catch (Throwable e) { + throw new RuntimeException(e); + } + + return filePath.toString(); + } + + public static JsonObject getJsonConfig(String path, String rendertype) { + // Check for external shader + if (rendertype.contains(String.valueOf(ResourceLocation.NAMESPACE_SEPARATOR))) { + return null; + } + + String basePath = path; + String configPath = "%s/%s/%s.json".formatted(basePath, rendertype, rendertype); + + InputStream stream; + try { + stream = getInputStream(configPath); + + if (stream == null) { + configPath = "%s/%s.json".formatted(basePath, rendertype); + stream = getInputStream(configPath); + } + + if (stream == null) { + return null; + } + + JsonElement jsonElement = JsonParser.parseReader(new BufferedReader(new InputStreamReader(stream))); + stream.close(); + + return (JsonObject) jsonElement; + } catch (Throwable e) { + throw new RuntimeException(e); + } + + } + + public static String getShaderSource(ResourceLocation resourceLocation, ShaderType type) { + String shaderExtension = switch (type) { + case VERTEX -> ".vsh"; + case FRAGMENT -> ".fsh"; + }; + + String path = resourceLocation.getPath(); + String[] splitPath = splitPath(path); + String shaderName = "%s%s".formatted(splitPath[1], shaderExtension); + String shaderFile = "%s/shaders/%s/%s".formatted(RESOURCES_PATH, path, shaderName); + + InputStream stream; + try { + stream = getInputStream(shaderFile); + + if (stream == null) { + return null; + } + + String source = IOUtils.toString(new BufferedReader(new InputStreamReader(stream))); + stream.close(); + + return source; + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + public static String getShaderSource(String path, ShaderType type) { + String shaderExtension = switch (type) { + case VERTEX -> ".vsh"; + case FRAGMENT -> ".fsh"; + }; + + String[] splitPath = splitPath(path); + String shaderName = "%s%s".formatted(splitPath[1], shaderExtension); + + String shaderFile = "%s/shaders/%s/%s".formatted(RESOURCES_PATH, path, shaderName); + + InputStream stream; + try { + stream = getInputStream(shaderFile); + String source = IOUtils.toString(new BufferedReader(new InputStreamReader(stream))); + stream.close(); + + return source; + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + public static String getShaderSource(String path, String configName, String shaderName, SPIRVUtils.ShaderKind type) { + String shaderExtension = switch (type) { + case VERTEX_SHADER -> ".vsh"; + case FRAGMENT_SHADER -> ".fsh"; + case COMPUTE_SHADER -> ".comp"; + default -> throw new UnsupportedOperationException("shader type %s unsupported"); + }; + + String basePath = path; + + String shaderPath = "/%s/%s".formatted(configName, configName); + String shaderFile = "%s%s%s".formatted(basePath, shaderPath, shaderExtension); + + InputStream stream; + try { + stream = getInputStream(shaderFile); + + if (stream == null) { + shaderPath = "/%s".formatted(shaderName); + shaderFile = "%s%s%s".formatted(basePath, shaderPath, shaderExtension); + stream = getInputStream(shaderFile); + } + + if (stream == null) { + shaderPath = "/%s/%s".formatted(configName, shaderName); + shaderFile = "%s%s%s".formatted(basePath, shaderPath, shaderExtension); + stream = getInputStream(shaderFile); + } + + if (stream == null) { + shaderPath = "/%s/%s".formatted(shaderName, shaderName); + shaderFile = "%s%s%s".formatted(basePath, shaderPath, shaderExtension); + stream = getInputStream(shaderFile); + } + + if (stream == null) { + return null; + } + + String source = IOUtils.toString(new BufferedReader(new InputStreamReader(stream))); + stream.close(); + + return source; + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + public static String getFileName(String path) { + int idx = path.lastIndexOf('/'); + return idx > -1 ? path.substring(idx + 1) : path; + } + + public static String removeNameSpace(String path) { + int idx = path.indexOf(':'); + return idx > -1 ? path.substring(idx + 1) : path; + } + + public static String[] splitPath(String path) { + int idx = path.lastIndexOf('/'); + + return new String[] {path.substring(0, idx), path.substring(idx + 1)}; + } + + public static InputStream getInputStream(String path) { + try { + var path1 = Paths.get(new URI(path)); + + if (!Files.exists(path1)) + return null; + + return Files.newInputStream(path1); + } catch (URISyntaxException | IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/net/vulkanmod/render/sky/CloudRenderer.java b/src/main/java/net/vulkanmod/render/sky/CloudRenderer.java new file mode 100644 index 000000000..60943f029 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/sky/CloudRenderer.java @@ -0,0 +1,407 @@ +package net.vulkanmod.render.sky; + +import com.mojang.blaze3d.opengl.GlStateManager; +import com.mojang.blaze3d.platform.NativeImage; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.*; +import net.minecraft.client.CloudStatus; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.Resource; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.Vec3; +import net.vulkanmod.render.PipelineManager; +import net.vulkanmod.render.VBO; +import net.vulkanmod.vulkan.Renderer; +import net.vulkanmod.vulkan.VRenderSystem; +import net.vulkanmod.vulkan.shader.GraphicsPipeline; +import net.vulkanmod.vulkan.util.ColorUtil; +import org.apache.commons.lang3.Validate; +import org.joml.Matrix4fStack; +import org.lwjgl.opengl.GL11; + +import java.io.IOException; +import java.util.Optional; + +public class CloudRenderer { + private static final ResourceLocation TEXTURE_LOCATION = ResourceLocation.withDefaultNamespace("textures/environment/clouds.png"); + + private static final int DIR_NEG_Y_BIT = 1 << 0; + private static final int DIR_POS_Y_BIT = 1 << 1; + private static final int DIR_NEG_X_BIT = 1 << 2; + private static final int DIR_POS_X_BIT = 1 << 3; + private static final int DIR_NEG_Z_BIT = 1 << 4; + private static final int DIR_POS_Z_BIT = 1 << 5; + + private static final byte Y_BELOW_CLOUDS = 0; + private static final byte Y_ABOVE_CLOUDS = 1; + private static final byte Y_INSIDE_CLOUDS = 2; + + private static final int CELL_WIDTH = 12; + private static final int CELL_HEIGHT = 4; + + private CloudGrid cloudGrid; + + private int prevCloudX; + private int prevCloudZ; + private byte prevCloudY; + + private CloudStatus prevCloudsType; + + private boolean generateClouds; + private VBO cloudBuffer; + + public CloudRenderer() { + loadTexture(); + } + + public void loadTexture() { + this.cloudGrid = createCloudGrid(TEXTURE_LOCATION); + } + + public void renderClouds(ClientLevel level, float ticks, float partialTicks, double camX, double camY, double camZ) { + Optional optional = level.dimensionType().cloudHeight(); + + if (optional.isEmpty()) { + return; + } + + Minecraft minecraft = Minecraft.getInstance(); + + int cloudHeight = optional.get(); + double timeOffset = (ticks + partialTicks) * 0.03F; + double centerX = (camX + timeOffset); + double centerZ = camZ + 0.33F * CELL_WIDTH; + double centerY = cloudHeight - (float) camY + 0.33F; + + int centerCellX = (int) Math.floor(centerX / CELL_WIDTH); + int centerCellZ = (int) Math.floor(centerZ / CELL_WIDTH); + + byte yState; + if (centerY < -4.0f) { + yState = Y_BELOW_CLOUDS; + } + else if (centerY > 0.0f) { + yState = Y_ABOVE_CLOUDS; + } + else { + yState = Y_INSIDE_CLOUDS; + } + + if (centerCellX != this.prevCloudX || centerCellZ != this.prevCloudZ + || (minecraft.options.getCloudsType() != this.prevCloudsType) + || (this.prevCloudY != yState) + || this.cloudBuffer == null) { + this.prevCloudX = centerCellX; + this.prevCloudZ = centerCellZ; + this.prevCloudsType = minecraft.options.getCloudsType(); + this.prevCloudY = yState; + this.generateClouds = true; + } + + if (this.generateClouds) { + this.generateClouds = false; + if (this.cloudBuffer != null) { + this.cloudBuffer.close(); + } + + this.resetBuffer(); + + MeshData cloudsMesh = this.buildClouds(Tesselator.getInstance(), centerCellX, centerCellZ, centerY); + + if (cloudsMesh == null) { + return; + } + + this.cloudBuffer = new VBO(true); + this.cloudBuffer.upload(cloudsMesh); + } + + if (this.cloudBuffer == null) { + return; + } + + float xTranslation = (float) (centerX - (centerCellX * CELL_WIDTH)); + float yTranslation = (float) (centerY); + float zTranslation = (float) (centerZ - (centerCellZ * CELL_WIDTH)); + + Renderer.getInstance().getMainPass().rebindMainTarget(); + + Matrix4fStack poseStack = RenderSystem.getModelViewStack(); + poseStack.pushMatrix(); + poseStack.translate(-xTranslation, yTranslation, -zTranslation); + VRenderSystem.applyModelViewMatrix(poseStack); + VRenderSystem.calculateMVP(); + + VRenderSystem.setModelOffset(-xTranslation, 0, -zTranslation); + + // TODO + Vec3 cloudColor = Vec3.fromRGB24(level.getCloudColor(partialTicks)); + VRenderSystem.setShaderColor((float) cloudColor.x, (float) cloudColor.y, (float) cloudColor.z, 0.8f); + + GraphicsPipeline pipeline = PipelineManager.getCloudsPipeline(); + VRenderSystem.enableBlend(); + VRenderSystem.blendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO); + VRenderSystem.enableDepthTest(); + VRenderSystem.depthFunc(GL11.GL_LEQUAL); + GlStateManager._enableDepthTest(); + GlStateManager._depthMask(true); + GlStateManager._colorMask(true, true, true, true); + GlStateManager._disablePolygonOffset(); + VRenderSystem.setPolygonModeGL(GL11.GL_FILL); + VRenderSystem.setPrimitiveTopologyGL(GL11.GL_TRIANGLES); + + boolean fastClouds = this.prevCloudsType == CloudStatus.FAST; + boolean insideClouds = yState == Y_INSIDE_CLOUDS; + boolean disableCull = insideClouds || (fastClouds && centerY <= 0.0f); + + if (disableCull) { + VRenderSystem.disableCull(); + } else { + VRenderSystem.enableCull(); + } + + if (!fastClouds) { + VRenderSystem.colorMask(false, false, false, false); + this.cloudBuffer.bind(pipeline); + this.cloudBuffer.draw(); + + VRenderSystem.colorMask(true, true, true, true); + } + + + this.cloudBuffer.bind(pipeline); + this.cloudBuffer.draw(); + + poseStack.popMatrix(); + VRenderSystem.enableCull(); + VRenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); + VRenderSystem.setModelOffset(0.0f, 0.0f, 0.0f); + } + + public void resetBuffer() { + if (this.cloudBuffer != null) { + this.cloudBuffer.close(); + this.cloudBuffer = null; + } + } + + private MeshData buildClouds(Tesselator tesselator, int centerCellX, int centerCellZ, double cloudY) { + final float upFaceBrightness = 1.0f; + final float xDirBrightness = 0.9f; + final float downFaceBrightness = 0.7f; + final float zDirBrightness = 0.8f; + + BufferBuilder bufferBuilder = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); + + int cloudRange = Math.min(Minecraft.getInstance().options.cloudRange().get(), 128) * 16; + int renderDistance = Mth.ceil(cloudRange / 12.0F); + boolean insideClouds = this.prevCloudY == Y_INSIDE_CLOUDS; + + if (this.prevCloudsType == CloudStatus.FANCY) { + + for (int cellX = -renderDistance; cellX < renderDistance; ++cellX) { + for (int cellZ = -renderDistance; cellZ < renderDistance; ++cellZ) { + int cellIdx = this.cloudGrid.getWrappedIdx(centerCellX + cellX, centerCellZ + cellZ); + byte renderFaces = this.cloudGrid.renderFaces[cellIdx]; + int baseColor = this.cloudGrid.pixels[cellIdx]; + + float x = cellX * CELL_WIDTH; + float z = cellZ * CELL_WIDTH; + + if ((renderFaces & DIR_POS_Y_BIT) != 0 && cloudY <= 0.0f) { + final int color = ColorUtil.ARGB.multiplyRGB(baseColor, upFaceBrightness); + putVertex(bufferBuilder, x + CELL_WIDTH, CELL_HEIGHT, z + CELL_WIDTH, color); + putVertex(bufferBuilder, x + CELL_WIDTH, CELL_HEIGHT, z + 0.0f, color); + putVertex(bufferBuilder, x + 0.0f, CELL_HEIGHT, z + 0.0f, color); + putVertex(bufferBuilder, x + 0.0f, CELL_HEIGHT, z + CELL_WIDTH, color); + } + + if ((renderFaces & DIR_NEG_Y_BIT) != 0 && cloudY >= -CELL_HEIGHT) { + final int color = ColorUtil.ARGB.multiplyRGB(baseColor, downFaceBrightness); + putVertex(bufferBuilder, x + 0.0f, 0.0f, z + CELL_WIDTH, color); + putVertex(bufferBuilder, x + 0.0f, 0.0f, z + 0.0f, color); + putVertex(bufferBuilder, x + CELL_WIDTH, 0.0f, z + 0.0f, color); + putVertex(bufferBuilder, x + CELL_WIDTH, 0.0f, z + CELL_WIDTH, color); + } + + if ((renderFaces & DIR_POS_X_BIT) != 0 && (x < 1.0f || insideClouds)) { + final int color = ColorUtil.ARGB.multiplyRGB(baseColor, xDirBrightness); + putVertex(bufferBuilder, x + CELL_WIDTH, CELL_HEIGHT, z + CELL_WIDTH, color); + putVertex(bufferBuilder, x + CELL_WIDTH, 0.0f, z + CELL_WIDTH, color); + putVertex(bufferBuilder, x + CELL_WIDTH, 0.0f, z + 0.0f, color); + putVertex(bufferBuilder, x + CELL_WIDTH, CELL_HEIGHT, z + 0.0f, color); + } + + if ((renderFaces & DIR_NEG_X_BIT) != 0 && (x > -1.0f || insideClouds)) { + final int color = ColorUtil.ARGB.multiplyRGB(baseColor, xDirBrightness); + putVertex(bufferBuilder, x + 0.0f, CELL_HEIGHT, z + 0.0f, color); + putVertex(bufferBuilder, x + 0.0f, 0.0f, z + 0.0f, color); + putVertex(bufferBuilder, x + 0.0f, 0.0f, z + CELL_WIDTH, color); + putVertex(bufferBuilder, x + 0.0f, CELL_HEIGHT, z + CELL_WIDTH, color); + } + + if ((renderFaces & DIR_POS_Z_BIT) != 0 && (z < 1.0f || insideClouds)) { + final int color = ColorUtil.ARGB.multiplyRGB(baseColor, zDirBrightness); + putVertex(bufferBuilder, x + 0.0f, CELL_HEIGHT, z + CELL_WIDTH, color); + putVertex(bufferBuilder, x + 0.0f, 0.0f, z + CELL_WIDTH, color); + putVertex(bufferBuilder, x + CELL_WIDTH, 0.0f, z + CELL_WIDTH, color); + putVertex(bufferBuilder, x + CELL_WIDTH, CELL_HEIGHT, z + CELL_WIDTH, color); + } + + if ((renderFaces & DIR_NEG_Z_BIT) != 0 && (z > -1.0f || insideClouds)) { + final int color = ColorUtil.ARGB.multiplyRGB(baseColor, zDirBrightness); + putVertex(bufferBuilder, x + CELL_WIDTH, CELL_HEIGHT, z + 0.0f, color); + putVertex(bufferBuilder, x + CELL_WIDTH, 0.0f, z + 0.0f, color); + putVertex(bufferBuilder, x + 0.0f, 0.0f, z + 0.0f, color); + putVertex(bufferBuilder, x + 0.0f, CELL_HEIGHT, z + 0.0f, color); + } + + } + } + } + else { + + for (int cellX = -renderDistance; cellX < renderDistance; ++cellX) { + for (int cellZ = -renderDistance; cellZ < renderDistance; ++cellZ) { + int cellIdx = this.cloudGrid.getWrappedIdx(centerCellX + cellX, centerCellZ + cellZ); + byte renderFaces = this.cloudGrid.renderFaces[cellIdx]; + int baseColor = this.cloudGrid.pixels[cellIdx]; + + float x = cellX * CELL_WIDTH; + float z = cellZ * CELL_WIDTH; + + if ((renderFaces & DIR_NEG_Y_BIT) != 0) { + final int color = ColorUtil.ARGB.multiplyRGB(baseColor, upFaceBrightness); + putVertex(bufferBuilder, x + 0.0f, 0.0f, z + CELL_WIDTH, color); + putVertex(bufferBuilder, x + 0.0f, 0.0f, z + 0.0f, color); + putVertex(bufferBuilder, x + CELL_WIDTH, 0.0f, z + 0.0f, color); + putVertex(bufferBuilder, x + CELL_WIDTH, 0.0f, z + CELL_WIDTH, color); + } + + } + } + } + + return bufferBuilder.build(); + } + + private static void putVertex(BufferBuilder bufferBuilder, float x, float y, float z, int color) { + bufferBuilder.addVertex(x, y, z).setColor(color); + } + + private static CloudGrid createCloudGrid(ResourceLocation textureLocation) { + ResourceManager resourceManager = Minecraft.getInstance().getResourceManager(); + + try { + Resource resource = resourceManager.getResourceOrThrow(textureLocation); + + try (var inputStream = resource.open()) { + NativeImage image = NativeImage.read(inputStream); + + int width = image.getWidth(); + int height = image.getHeight(); + Validate.isTrue(width == height, "Image width and height must be the same"); + + int[] pixels = image.getPixelsABGR(); + + return new CloudGrid(pixels, width); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + static class CloudGrid { + final int width; + final int[] pixels; + final byte[] renderFaces; + + CloudGrid(int[] pixels, int width) { + this.pixels = pixels; + this.width = width; + + this.renderFaces = computeRenderFaces(); + } + + byte[] computeRenderFaces() { + byte[] renderFaces = new byte[pixels.length]; + + for (int z = 0; z < this.width; z++) { + for (int x = 0; x < this.width; x++) { + int idx = this.getIdx(x, z); + int pixel = this.pixels[idx]; + + if (!hasColor(pixel)) { + continue; + } + + byte faces = DIR_NEG_Y_BIT | DIR_POS_Y_BIT; + + int adjPixel; + + adjPixel = getTexelWrapped(x - 1, z); + if (pixel != adjPixel) { + faces |= DIR_NEG_X_BIT; + } + + adjPixel = getTexelWrapped(x + 1, z); + if (pixel != adjPixel) { + faces |= DIR_POS_X_BIT; + } + + adjPixel = getTexelWrapped(x, z - 1); + if (pixel != adjPixel) { + faces |= DIR_NEG_Z_BIT; + } + + adjPixel = getTexelWrapped(x, z + 1); + if (pixel != adjPixel) { + faces |= DIR_POS_Z_BIT; + } + + renderFaces[idx] = faces; + } + } + + return renderFaces; + } + + int getTexelWrapped(int x, int z) { + if (x < 0) { + x = this.width - 1; + } + + if (x > this.width - 1) { + x = 0; + } + + if (z < 0) { + z = this.width - 1; + } + + if (z > this.width - 1) { + z = 0; + } + + return this.pixels[getIdx(x, z)]; + } + + int getWrappedIdx(int x, int z) { + x = Math.floorMod(x, this.width); + z = Math.floorMod(z, this.width); + + return this.getIdx(x, z); + } + + int getIdx(int x, int z) { + return z * this.width + x; + } + + private static boolean hasColor(int pixel) { + return ((pixel >> 24) & 0xFF) > 1; + } + } +} diff --git a/src/main/java/net/vulkanmod/render/texture/ImageUploadHelper.java b/src/main/java/net/vulkanmod/render/texture/ImageUploadHelper.java new file mode 100644 index 000000000..8554c36c6 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/texture/ImageUploadHelper.java @@ -0,0 +1,43 @@ +package net.vulkanmod.render.texture; + +import net.vulkanmod.vulkan.Synchronization; +import net.vulkanmod.vulkan.device.DeviceManager; +import net.vulkanmod.vulkan.queue.CommandPool; +import net.vulkanmod.vulkan.queue.Queue; + +public class ImageUploadHelper { + + public static final ImageUploadHelper INSTANCE = new ImageUploadHelper(); + + final Queue queue; + private CommandPool.CommandBuffer currentCmdBuffer; + + public ImageUploadHelper() { + queue = DeviceManager.getGraphicsQueue(); + } + + public void submitCommands() { + if (this.currentCmdBuffer == null) { + return; + } + + SpriteUpdateUtil.transitionLayouts(); + + queue.submitCommands(this.currentCmdBuffer, true); + Synchronization.INSTANCE.addCommandBuffer(this.currentCmdBuffer, true); + + this.currentCmdBuffer = null; + } + + public CommandPool.CommandBuffer getOrStartCommandBuffer() { + if (this.currentCmdBuffer == null) { + this.currentCmdBuffer = this.queue.beginCommands(); + } + + return this.currentCmdBuffer; + } + + public CommandPool.CommandBuffer getCommandBuffer() { + return this.currentCmdBuffer; + } +} diff --git a/src/main/java/net/vulkanmod/render/texture/SpriteUpdateUtil.java b/src/main/java/net/vulkanmod/render/texture/SpriteUpdateUtil.java new file mode 100644 index 000000000..23cb63bca --- /dev/null +++ b/src/main/java/net/vulkanmod/render/texture/SpriteUpdateUtil.java @@ -0,0 +1,44 @@ +package net.vulkanmod.render.texture; + +import net.vulkanmod.vulkan.texture.VulkanImage; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.vulkan.VkCommandBuffer; + +import java.util.HashSet; +import java.util.Set; + +public abstract class SpriteUpdateUtil { + + private static boolean doUpload = true; + private static final Set transitionedLayouts = new HashSet<>(); + + public static void setDoUpload(boolean b) { + doUpload = b; + } + + public static boolean doUploadFrame() { + return doUpload; + } + + public static void addTransitionedLayout(VulkanImage image) { + transitionedLayouts.add(image); + } + + public static void transitionLayouts() { + if (transitionedLayouts.isEmpty()) { + return; + } + + VkCommandBuffer commandBuffer = ImageUploadHelper.INSTANCE.getOrStartCommandBuffer().handle; + + transitionedLayouts.forEach( + image -> + { + try (MemoryStack stack = MemoryStack.stackPush()) { + image.readOnlyLayout(stack, commandBuffer); + } + + }); + transitionedLayouts.clear(); + } +} diff --git a/src/main/java/net/vulkanmod/render/texture/SpriteUtil.java b/src/main/java/net/vulkanmod/render/texture/SpriteUtil.java deleted file mode 100644 index 6b5df13ff..000000000 --- a/src/main/java/net/vulkanmod/render/texture/SpriteUtil.java +++ /dev/null @@ -1,35 +0,0 @@ -package net.vulkanmod.render.texture; - -import net.vulkanmod.vulkan.texture.VulkanImage; -import org.lwjgl.system.MemoryStack; -import org.lwjgl.vulkan.VkCommandBuffer; - -import java.util.HashSet; -import java.util.Set; - -public abstract class SpriteUtil { - - private static boolean doUpload = false; - - private static Set transitionedLayouts = new HashSet<>(); - - public static void setDoUpload(boolean b) { - doUpload = b; - } - - public static boolean shouldUpload() { - return doUpload; - } - - public static void addTransitionedLayout(VulkanImage image) { - transitionedLayouts.add(image); - } - - public static void transitionLayouts(VkCommandBuffer commandBuffer) { - try(MemoryStack stack = MemoryStack.stackPush()) { - transitionedLayouts.forEach(image -> image.readOnlyLayout(stack, commandBuffer)); - - transitionedLayouts.clear(); - } - } -} diff --git a/src/main/java/net/vulkanmod/render/util/DrawUtil.java b/src/main/java/net/vulkanmod/render/util/DrawUtil.java index 430194d69..b4e527eb8 100644 --- a/src/main/java/net/vulkanmod/render/util/DrawUtil.java +++ b/src/main/java/net/vulkanmod/render/util/DrawUtil.java @@ -1,8 +1,10 @@ package net.vulkanmod.render.util; +import com.mojang.blaze3d.ProjectionType; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.*; import net.vulkanmod.vulkan.Renderer; +import net.vulkanmod.vulkan.VRenderSystem; import net.vulkanmod.vulkan.shader.GraphicsPipeline; import net.vulkanmod.vulkan.shader.Pipeline; import net.vulkanmod.vulkan.texture.VTextureSelector; @@ -18,7 +20,7 @@ public static void blitQuad() { public static void drawTexQuad(BufferBuilder builder, float x0, float y0, float x1, float y1, float z, float u0, float v0, float u1, float v1) { - Tesselator tesselator = RenderSystem.renderThreadTesselator(); + Tesselator tesselator = Tesselator.getInstance(); BufferBuilder bufferBuilder = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX); bufferBuilder.addVertex(x0, y0, z).setUv(0.0F, 1.0F); bufferBuilder.addVertex(x1, y0, z).setUv(1.0F, 1.0F); @@ -32,7 +34,7 @@ public static void drawTexQuad(BufferBuilder builder, float x0, float y0, float } public static void blitQuad(float x0, float y0, float x1, float y1) { - Tesselator tesselator = RenderSystem.renderThreadTesselator(); + Tesselator tesselator = Tesselator.getInstance(); BufferBuilder bufferBuilder = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX); bufferBuilder.addVertex(x0, y0, 0.0f).setUv(0.0F, 1.0F); bufferBuilder.addVertex(x1, y0, 0.0f).setUv(1.0F, 1.0F); @@ -46,18 +48,15 @@ public static void blitQuad(float x0, float y0, float x1, float y1) { } public static void drawFramebuffer(GraphicsPipeline pipeline, VulkanImage attachment) { - Renderer.getInstance().bindGraphicsPipeline(pipeline); - VTextureSelector.bindTexture(attachment); - Matrix4f matrix4f = new Matrix4f().setOrtho(0.0F, 1.0F, 0.0F, 1.0F, 0.0F, 1.0F, true); - RenderSystem.setProjectionMatrix(matrix4f, VertexSorting.DISTANCE_TO_ORIGIN); - Matrix4fStack posestack = RenderSystem.getModelViewStack(); - posestack.pushMatrix(); - posestack.identity(); - RenderSystem.applyModelViewMatrix(); - posestack.popMatrix(); + Matrix4f projection = new Matrix4f().setOrtho(0.0F, 1.0F, 0.0F, 1.0F, 0.0F, 1.0F, true); + Matrix4fStack poseStack = RenderSystem.getModelViewStack(); + poseStack.pushMatrix(); + poseStack.identity(); + VRenderSystem.applyMVP(poseStack, projection); + poseStack.popMatrix(); Renderer.getInstance().uploadAndBindUBOs(pipeline); diff --git a/src/main/java/net/vulkanmod/render/util/MathUtil.java b/src/main/java/net/vulkanmod/render/util/MathUtil.java index 99f26cbcb..0d8e42fe8 100644 --- a/src/main/java/net/vulkanmod/render/util/MathUtil.java +++ b/src/main/java/net/vulkanmod/render/util/MathUtil.java @@ -1,5 +1,10 @@ package net.vulkanmod.render.util; +import net.vulkanmod.render.vertex.format.I32_SNorm; +import org.joml.Math; +import org.joml.Matrix3f; +import org.joml.Matrix4f; + public class MathUtil { public static float clamp(float min, float max, float x) { @@ -17,4 +22,46 @@ public static float saturate(float x) { public static float lerp(float v0, float v1, float t) { return v0 + t * (v1 - v0); } + + // JOML Math util + + public static float transformX(Matrix4f mat, float x, float y, float z) { + return Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30()))); + } + + public static float transformY(Matrix4f mat, float x, float y, float z) { + return Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31()))); + } + + public static float transformZ(Matrix4f mat, float x, float y, float z) { + return Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32()))); + } + + public static int packTransformedNorm(Matrix3f mat, boolean trustedNormals, float x, float y, float z) { + float nx = transformNormX(mat, x, y, z); + float ny = transformNormY(mat, x, y, z); + float nz = transformNormZ(mat, x, y, z); + + if (!trustedNormals) { + float scalar = Math.invsqrt(Math.fma(nx, nx, Math.fma(ny, ny, nz * nz))); + nx = nx * scalar; + ny = ny * scalar; + nz = nz * scalar; + } + + int packedNormal = I32_SNorm.packNormal(nx, ny, nz); + return packedNormal; + } + + public static float transformNormX(Matrix3f mat, float x, float y, float z) { + return Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, mat.m20() * z)); + } + + public static float transformNormY(Matrix3f mat, float x, float y, float z) { + return Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, mat.m21() * z)); + } + + public static float transformNormZ(Matrix3f mat, float x, float y, float z) { + return Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, mat.m22() * z)); + } } diff --git a/src/main/java/net/vulkanmod/render/vertex/CustomVertexFormat.java b/src/main/java/net/vulkanmod/render/vertex/CustomVertexFormat.java index 78e798735..7ec452ce5 100644 --- a/src/main/java/net/vulkanmod/render/vertex/CustomVertexFormat.java +++ b/src/main/java/net/vulkanmod/render/vertex/CustomVertexFormat.java @@ -3,19 +3,27 @@ import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormatElement; -public class CustomVertexFormat { - +public abstract class CustomVertexFormat { public static final VertexFormatElement ELEMENT_POSITION = new VertexFormatElement(0, 0,VertexFormatElement.Type.SHORT, VertexFormatElement.Usage.POSITION, 4); - public static final VertexFormatElement ELEMENT_COLOR = new VertexFormatElement(1, 0, VertexFormatElement.Type.UBYTE, VertexFormatElement.Usage.COLOR, 4); + public static final VertexFormatElement ELEMENT_COLOR = new VertexFormatElement(1, 0, VertexFormatElement.Type.UINT, VertexFormatElement.Usage.COLOR, 1); public static final VertexFormatElement ELEMENT_UV0 = new VertexFormatElement(2, 0, VertexFormatElement.Type.USHORT, VertexFormatElement.Usage.UV, 2); - public static final VertexFormatElement ELEMENT_UV2 = new VertexFormatElement(3, 2, VertexFormatElement.Type.SHORT, VertexFormatElement.Usage.UV, 2); - public static final VertexFormat COMPRESSED_TERRAIN = VertexFormat.builder() - .add("Position", ELEMENT_POSITION) - .add("Color", ELEMENT_COLOR) - .add("UV0", ELEMENT_UV0) - .add("UV2", ELEMENT_UV2) - .build(); + private static float POSITION_OFFSET = 4.0f; + + public static final VertexFormat COMPRESSED_TERRAIN = + VertexFormat.builder() + .add("Position", ELEMENT_POSITION) + .add("UV0", ELEMENT_UV0) + .add("Color", ELEMENT_COLOR) + .build(); public static final VertexFormat NONE = VertexFormat.builder().build(); + + public static void setPositionOffset(float positionOffset) { + POSITION_OFFSET = positionOffset; + } + + public static float getPositionOffset() { + return POSITION_OFFSET; + } } diff --git a/src/main/java/net/vulkanmod/render/vertex/QuadSorter.java b/src/main/java/net/vulkanmod/render/vertex/QuadSorter.java index fa6dd03da..91c26a129 100644 --- a/src/main/java/net/vulkanmod/render/vertex/QuadSorter.java +++ b/src/main/java/net/vulkanmod/render/vertex/QuadSorter.java @@ -15,6 +15,10 @@ public class QuadSorter { private VertexFormat format; private int vertexCount; + private int indexCount; + + private float[] distances; + private int[] sortingPointsIndices; public void setQuadSortOrigin(float x, float y, float z) { this.sortX = x; @@ -23,12 +27,14 @@ public void setQuadSortOrigin(float x, float y, float z) { } public SortState getSortState() { - return new SortState(this.vertexCount, this.sortingPoints); + return new SortState(this.vertexCount, this.sortingPoints, this.distances, this.sortingPointsIndices); } public void restoreSortState(QuadSorter.SortState sortState) { this.vertexCount = sortState.vertexCount; this.sortingPoints = sortState.sortingPoints; + this.distances = sortState.distances; + this.sortingPointsIndices = sortState.sortingPointsIndices; this.indexOnly = true; } @@ -80,9 +86,43 @@ public void setupQuadSortingPoints(long bufferPtr, int vertexCount, VertexFormat } this.sortingPoints = sortingPoints; + this.distances = new float[pointCount]; + this.sortingPointsIndices = new int[pointCount]; } public void putSortedQuadIndices(TerrainBufferBuilder bufferBuilder, VertexFormat.IndexType indexType) { + float[] distances = this.distances; + int[] sortingPointsIndices = this.sortingPointsIndices; + + for (int i = 0; i < this.sortingPoints.length; sortingPointsIndices[i] = i++) { + float dx = this.sortingPoints[i].x() - this.sortX; + float dy = this.sortingPoints[i].y() - this.sortY; + float dz = this.sortingPoints[i].z() - this.sortZ; + distances[i] = dx * dx + dy * dy + dz * dz; + } + + SortUtil.mergeSort(sortingPointsIndices, distances); + + long ptr = bufferBuilder.getPtr(); + + final int size = indexType.bytes; + final int stride = 4; // 4 vertices in a quad + for (int i = 0; i < sortingPointsIndices.length; ++i) { + final int quadIndex = sortingPointsIndices[i]; + final int baseVertex = quadIndex * stride; + + MemoryUtil.memPutInt(ptr + (size * 0L), baseVertex + 0); + MemoryUtil.memPutInt(ptr + (size * 1L), baseVertex + 1); + MemoryUtil.memPutInt(ptr + (size * 2L), baseVertex + 2); + MemoryUtil.memPutInt(ptr + (size * 3L), baseVertex + 2); + MemoryUtil.memPutInt(ptr + (size * 4L), baseVertex + 3); + MemoryUtil.memPutInt(ptr + (size * 5L), baseVertex + 0); + + ptr += size * 6L; + } + } + + public void putSortedQuadIndices(TerrainBuilder bufferBuilder, VertexFormat.IndexType indexType) { float[] distances = new float[this.sortingPoints.length]; int[] sortingPoints = new int[this.sortingPoints.length]; @@ -95,7 +135,7 @@ public void putSortedQuadIndices(TerrainBufferBuilder bufferBuilder, VertexForma SortUtil.mergeSort(sortingPoints, distances); - long ptr = bufferBuilder.getPtr(); + long ptr = bufferBuilder.indexBufferPtr; final int size = indexType.bytes; final int stride = 4; // 4 vertices in a quad @@ -114,14 +154,29 @@ public void putSortedQuadIndices(TerrainBufferBuilder bufferBuilder, VertexForma } } + public void reset() { + this.vertexCount = 0; + } + + public int getVertexCount() { + return vertexCount; + } + + public int getIndexCount() { + return indexCount; + } + public static class SortState { final int vertexCount; final Vector3f[] sortingPoints; + final float[] distances; + final int[] sortingPointsIndices; - SortState(int vertexCount, Vector3f[] sortingPoints) { + SortState(int vertexCount, Vector3f[] sortingPoints, float[] distances, int[] sortingPointsIndices) { this.vertexCount = vertexCount; this.sortingPoints = sortingPoints; - + this.distances = distances; + this.sortingPointsIndices = sortingPointsIndices; } } } diff --git a/src/main/java/net/vulkanmod/render/vertex/TerrainBufferBuilder.java b/src/main/java/net/vulkanmod/render/vertex/TerrainBufferBuilder.java index ca116035e..248aa5dfe 100644 --- a/src/main/java/net/vulkanmod/render/vertex/TerrainBufferBuilder.java +++ b/src/main/java/net/vulkanmod/render/vertex/TerrainBufferBuilder.java @@ -1,51 +1,38 @@ package net.vulkanmod.render.vertex; -import com.mojang.blaze3d.vertex.VertexFormat; -import net.minecraft.world.level.block.state.BlockState; +import com.mojang.blaze3d.vertex.VertexConsumer; import net.vulkanmod.Initializer; -import net.vulkanmod.render.PipelineManager; -import net.vulkanmod.render.util.SortUtil; +import net.vulkanmod.render.vertex.format.I32_SNorm; import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.Nullable; -import org.joml.Vector3f; import org.lwjgl.system.MemoryUtil; import java.nio.ByteBuffer; -public class TerrainBufferBuilder { +public class TerrainBufferBuilder implements VertexConsumer { private static final Logger LOGGER = Initializer.LOGGER; private static final MemoryUtil.MemoryAllocator ALLOCATOR = MemoryUtil.getAllocator(false); private int capacity; - protected long bufferPtr; - protected int nextElementByte; - private int vertexCount; - - private int renderedBufferCount; - private int renderedBufferPointer; + private int vertexSize; - private final VertexFormat format; - - private boolean building; + protected long bufferPtr; - private final QuadSorter quadSorter = new QuadSorter(); + protected int nextElementByte; + int vertices; - private boolean needsSorting; - private boolean indexOnly; + private long elementPtr; - protected VertexBuilder vertexBuilder; + private VertexBuilder vertexBuilder; - public TerrainBufferBuilder(int size) { + public TerrainBufferBuilder(int size, int vertexSize, VertexBuilder vertexBuilder) { this.bufferPtr = ALLOCATOR.malloc(size); this.capacity = size; - - this.format = PipelineManager.TERRAIN_VERTEX_FORMAT; - this.vertexBuilder = PipelineManager.TERRAIN_VERTEX_FORMAT == CustomVertexFormat.COMPRESSED_TERRAIN - ? new VertexBuilder.CompressedVertexBuilder() : new VertexBuilder.DefaultVertexBuilder(); + this.vertexSize = vertexSize; + this.vertexBuilder = vertexBuilder; } public void ensureCapacity() { - this.ensureCapacity(this.format.getVertexSize() * 4); + this.ensureCapacity(this.vertexSize * 4); } private void ensureCapacity(int size) { @@ -66,237 +53,93 @@ private void resize(int i) { } } - public void setupQuadSorting(float x, float y, float z) { - this.quadSorter.setQuadSortOrigin(x, y, z); - this.needsSorting = true; - } - - public QuadSorter.SortState getSortState() { - return this.quadSorter.getSortState(); - } - - public void restoreSortState(QuadSorter.SortState sortState) { - this.vertexCount = sortState.vertexCount; - this.nextElementByte = this.renderedBufferPointer; - - this.quadSorter.restoreSortState(sortState); - - this.indexOnly = true; - } - - public void setIndexOnly() { - this.indexOnly = true; - } - - public void begin() { - if (this.building) { - throw new IllegalStateException("Already building!"); - } else { - this.building = true; - } - } - - public void setupQuadSortingPoints() { - this.quadSorter.setupQuadSortingPoints(this.bufferPtr + this.renderedBufferPointer, this.vertexCount, this.format); - } - - public boolean isCurrentBatchEmpty() { - return this.vertexCount == 0; - } - - @Nullable - public RenderedBuffer end() { - this.ensureDrawing(); - if (this.isCurrentBatchEmpty()) { - this.reset(); - return null; - } else { - RenderedBuffer renderedBuffer = this.storeRenderedBuffer(); - this.reset(); - return renderedBuffer; - } - } - - private void ensureDrawing() { - if (!this.building) { - throw new IllegalStateException("Not building!"); - } - } - - private RenderedBuffer storeRenderedBuffer() { - int indexCount = this.vertexCount / 4 * 6; - int vertexBufferSize = !this.indexOnly ? this.vertexCount * this.format.getVertexSize() : 0; - VertexFormat.IndexType indexType = VertexFormat.IndexType.least(indexCount); - - boolean sequentialIndexing; - int size; - - if (this.needsSorting) { - int indexBufferSize = indexCount * indexType.bytes; - this.ensureCapacity(indexBufferSize); - - this.quadSorter.putSortedQuadIndices(this, indexType); - - sequentialIndexing = false; - this.nextElementByte += indexBufferSize; - size = vertexBufferSize + indexBufferSize; - } else { - sequentialIndexing = true; - size = vertexBufferSize; - } - - int ptr = this.renderedBufferPointer; - this.renderedBufferPointer += size; - ++this.renderedBufferCount; - - DrawState drawState = new DrawState(this.format.getVertexSize(), this.vertexCount, indexCount, indexType, this.indexOnly, sequentialIndexing); - return new RenderedBuffer(ptr, drawState); + public void endVertex() { + this.nextElementByte += this.vertexSize; + ++this.vertices; } - public void reset() { - this.building = false; - this.vertexCount = 0; - - this.indexOnly = false; - this.needsSorting = false; + public void vertex(float x, float y, float z, int color, float u, float v, int light, int packedNormal) { + final long ptr = this.bufferPtr + this.nextElementByte; + this.vertexBuilder.vertex(ptr, x, y, z, color, u, v, light, packedNormal); + this.endVertex(); } - void releaseRenderedBuffer() { - if (this.renderedBufferCount > 0 && --this.renderedBufferCount == 0) { - this.clear(); - } - + public void end() { } public void clear() { - if (this.renderedBufferCount > 0) { - LOGGER.warn("Clearing BufferBuilder with unused batches"); - } - - this.discard(); - } - - public void discard() { - this.renderedBufferCount = 0; - this.renderedBufferPointer = 0; this.nextElementByte = 0; + this.vertices = 0; } - public boolean building() { - return this.building; - } - - public void endVertex() { - this.nextElementByte += this.vertexBuilder.getStride(); - ++this.vertexCount; + public void free() { + ALLOCATOR.free(this.bufferPtr); } - public void vertex(float x, float y, float z, int color, float u, float v, int light, int packedNormal) { - final long ptr = this.bufferPtr + this.nextElementByte; - this.vertexBuilder.vertex(ptr, x, y, z, color, u, v, light, packedNormal); - this.endVertex(); - } - - public void setBlockAttributes(BlockState blockState) { + public ByteBuffer getBuffer() { + return MemoryUtil.memByteBuffer(this.bufferPtr, this.vertices * this.vertexSize); } public long getPtr() { - return this.bufferPtr + this.nextElementByte; + return bufferPtr; } - public int getVertexCount() { - return vertexCount; + public int getVertices() { + return vertices; } - public class RenderedBuffer { - private final int pointer; - private final DrawState drawState; - private boolean released; - - RenderedBuffer(int pointer, DrawState drawState) { - this.pointer = pointer; - this.drawState = drawState; - } - - public ByteBuffer vertexBuffer() { - int start = this.pointer + this.drawState.vertexBufferStart(); - int end = this.pointer + this.drawState.vertexBufferEnd(); - return MemoryUtil.memByteBuffer(TerrainBufferBuilder.this.bufferPtr + start, end - start); - } + public int getNextElementByte() { + return nextElementByte; + } - public ByteBuffer indexBuffer() { - int start = this.pointer + this.drawState.indexBufferStart(); - int end = this.pointer + this.drawState.indexBufferEnd(); - return MemoryUtil.memByteBuffer(TerrainBufferBuilder.this.bufferPtr + start, end - start); - } + @Override + public VertexConsumer addVertex(float x, float y, float z) { + this.elementPtr = this.bufferPtr + this.nextElementByte; + this.endVertex(); - public DrawState drawState() { - return this.drawState; - } + this.vertexBuilder.position(this.elementPtr, x, y, z); - public boolean isEmpty() { - return this.drawState.vertexCount == 0; - } + return this; + } - public void release() { - if (this.released) { - throw new IllegalStateException("Buffer has already been released!"); - } else { - TerrainBufferBuilder.this.releaseRenderedBuffer(); - this.released = true; - } - } - } + @Override + public VertexConsumer setColor(int r, int g, int b, int a) { + int color = (a & 0xFF) << 24 | (b & 0xFF) << 16 | (g & 0xFF) << 8 | (r & 0xFF); - public record DrawState(int vertexSize, int vertexCount, int indexCount, VertexFormat.IndexType indexType, - boolean indexOnly, boolean sequentialIndex) { + this.vertexBuilder.color(this.elementPtr, color); - public int vertexBufferSize() { - return this.vertexCount * this.vertexSize; - } + return this; + } - public int vertexBufferStart() { - return 0; - } + @Override + public VertexConsumer setUv(float u, float v) { + this.vertexBuilder.uv(this.elementPtr, u, v); - public int vertexBufferEnd() { - return this.vertexBufferSize(); - } + return this; + } - public int indexBufferStart() { - return this.indexOnly ? 0 : this.vertexBufferEnd(); - } + public VertexConsumer setLight(int i) { + this.vertexBuilder.light(this.elementPtr, i); - public int indexBufferEnd() { - return this.indexBufferStart() + this.indexBufferSize(); - } + return this; + } - private int indexBufferSize() { - return this.sequentialIndex ? 0 : this.indexCount * this.indexType.bytes; - } - - public int bufferSize() { - return this.indexBufferEnd(); - } - - public int vertexCount() { - return this.vertexCount; - } + @Override + public VertexConsumer setNormal(float f, float g, float h) { + int packedNormal = I32_SNorm.packNormal(f, g, h); - public int indexCount() { - return this.indexCount; - } + this.vertexBuilder.normal(this.elementPtr, packedNormal); - public VertexFormat.IndexType indexType() { - return this.indexType; - } + return this; + } - public boolean indexOnly() { - return this.indexOnly; - } + @Override + public VertexConsumer setUv1(int i, int j) { + return this; + } - public boolean sequentialIndex() { - return this.sequentialIndex; - } - } + @Override + public VertexConsumer setUv2(int i, int j) { + return this; + } } diff --git a/src/main/java/net/vulkanmod/render/vertex/TerrainBuilder.java b/src/main/java/net/vulkanmod/render/vertex/TerrainBuilder.java new file mode 100644 index 000000000..43b547bcc --- /dev/null +++ b/src/main/java/net/vulkanmod/render/vertex/TerrainBuilder.java @@ -0,0 +1,197 @@ +package net.vulkanmod.render.vertex; + +import com.mojang.blaze3d.vertex.VertexFormat; +import net.minecraft.world.level.block.state.BlockState; +import net.vulkanmod.Initializer; +import net.vulkanmod.render.PipelineManager; +import net.vulkanmod.render.chunk.cull.QuadFacing; +import net.vulkanmod.vulkan.memory.buffer.IndexBuffer; +import org.apache.logging.log4j.Logger; +import org.lwjgl.system.MemoryUtil; + +import java.nio.ByteBuffer; + +public class TerrainBuilder { + private static final Logger LOGGER = Initializer.LOGGER; + private static final MemoryUtil.MemoryAllocator ALLOCATOR = MemoryUtil.getAllocator(false); + + protected long indexBufferPtr; + + private int indexBufferCapacity; + + private final VertexFormat format; + + private boolean building; + + private final QuadSorter quadSorter = new QuadSorter(); + + private boolean needsSorting; + private boolean indexOnly; + + protected VertexBuilder vertexBuilder; + + private final TerrainBufferBuilder[] bufferBuilders; + + public TerrainBuilder(int size, VertexBuilder vertexBuilder) { + // FIXME: same size is used for both index and vertex buffers + this.indexBufferCapacity = size; + this.indexBufferPtr = ALLOCATOR.malloc(this.indexBufferCapacity); + + this.format = PipelineManager.terrainVertexFormat; + this.vertexBuilder = vertexBuilder; + + var bufferBuilders = new TerrainBufferBuilder[QuadFacing.COUNT]; + for (int i = 0; i < QuadFacing.COUNT; i++) { + bufferBuilders[i] = new TerrainBufferBuilder(size, this.format.getVertexSize(), this.vertexBuilder); + } + + this.bufferBuilders = bufferBuilders; + } + + public TerrainBufferBuilder getBufferBuilder(int i) { + return this.bufferBuilders[i]; + } + + private void ensureIndexCapacity(int size) { + if (size > this.indexBufferCapacity) { + int capacity = this.indexBufferCapacity; + int newSize = (capacity + size) * 2; + this.resizeIndexBuffer(newSize); + } + } + + private void resizeIndexBuffer(int i) { + this.indexBufferPtr = ALLOCATOR.realloc(this.indexBufferPtr, i); + LOGGER.debug("Needed to grow index buffer: Old size {} bytes, new size {} bytes.", this.indexBufferCapacity, i); + if (this.indexBufferPtr == 0L) { + throw new OutOfMemoryError("Failed to resize buffer from " + this.indexBufferCapacity + " bytes to " + i + " bytes"); + } else { + this.indexBufferCapacity = i; + } + } + + public void setupQuadSorting(float x, float y, float z) { + this.quadSorter.setQuadSortOrigin(x, y, z); + this.needsSorting = true; + } + + public QuadSorter.SortState getSortState() { + return this.quadSorter.getSortState(); + } + + public void restoreSortState(QuadSorter.SortState sortState) { + this.quadSorter.restoreSortState(sortState); + + this.indexOnly = true; + } + + public void setIndexOnly() { + this.indexOnly = true; + } + + public void begin() { + if (this.building) { + throw new IllegalStateException("Already building!"); + } else { + this.building = true; + } + } + + public void setupQuadSortingPoints() { + TerrainBufferBuilder bufferBuilder = bufferBuilders[QuadFacing.UNDEFINED.ordinal()]; + long bufferPtr = bufferBuilder.getPtr(); + int vertexCount = bufferBuilder.getVertices(); + + this.quadSorter.setupQuadSortingPoints(bufferPtr, vertexCount, this.format); + } + + public DrawState endDrawing() { + for (TerrainBufferBuilder bufferBuilder : this.bufferBuilders) { + bufferBuilder.end(); + } + + int vertexCount = this.quadSorter.getVertexCount(); + + int indexCount = vertexCount / 4 * 6; + + VertexFormat.IndexType indexType = VertexFormat.IndexType.least(indexCount); + boolean sequentialIndexing; + + // TODO sorting + if (this.needsSorting) { + int indexBufferSize = indexCount * indexType.bytes; + this.ensureIndexCapacity(indexBufferSize); + + this.quadSorter.putSortedQuadIndices(this, indexType); + + sequentialIndexing = false; + } else { + sequentialIndexing = true; + } + + return new DrawState(this.format.getVertexSize(), indexCount, indexType, this.indexOnly, sequentialIndexing); + } + + // TODO hardcoded index type size + public ByteBuffer getIndexBuffer() { + int indexCount = this.quadSorter.getVertexCount() * 6 / 4; + + return MemoryUtil.memByteBuffer(this.indexBufferPtr, indexCount * 2); + } + + private void ensureDrawing() { + if (!this.building) { + throw new IllegalStateException("Not building!"); + } + } + + public void reset() { + this.building = false; + + this.indexOnly = false; + this.needsSorting = false; + } + + public void clear() { + this.reset(); + + for (TerrainBufferBuilder bufferBuilder : this.bufferBuilders) { + bufferBuilder.clear(); + } + } + + public void free() { + ALLOCATOR.free(this.indexBufferPtr); + + for (TerrainBufferBuilder bufferBuilder : this.bufferBuilders) { + bufferBuilder.free(); + } + } + + public void setBlockAttributes(BlockState blockState) { + } + + public record DrawState(int vertexSize, int indexCount, VertexFormat.IndexType indexType, + boolean indexOnly, boolean sequentialIndex) { + + private int indexBufferSize() { + return this.sequentialIndex ? 0 : this.indexCount * this.indexType.bytes; + } + + public int indexCount() { + return this.indexCount; + } + + public VertexFormat.IndexType indexType() { + return this.indexType; + } + + public boolean indexOnly() { + return this.indexOnly; + } + + public boolean sequentialIndex() { + return this.sequentialIndex; + } + } +} diff --git a/src/main/java/net/vulkanmod/render/vertex/TerrainRenderType.java b/src/main/java/net/vulkanmod/render/vertex/TerrainRenderType.java index bd42c0752..2c1281920 100644 --- a/src/main/java/net/vulkanmod/render/vertex/TerrainRenderType.java +++ b/src/main/java/net/vulkanmod/render/vertex/TerrainRenderType.java @@ -1,10 +1,13 @@ package net.vulkanmod.render.vertex; import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.chunk.ChunkSectionLayer; +import net.vulkanmod.Initializer; import net.vulkanmod.interfaces.ExtendedRenderType; import net.vulkanmod.vulkan.VRenderSystem; import java.util.EnumSet; +import java.util.function.Function; public enum TerrainRenderType { SOLID(0.0f), @@ -18,6 +21,8 @@ public enum TerrainRenderType { public static final EnumSet COMPACT_RENDER_TYPES = EnumSet.of(CUTOUT_MIPPED, TRANSLUCENT); public static final EnumSet SEMI_COMPACT_RENDER_TYPES = EnumSet.of(CUTOUT_MIPPED, CUTOUT, TRANSLUCENT); + private static Function remapper; + static { SEMI_COMPACT_RENDER_TYPES.add(CUTOUT); SEMI_COMPACT_RENDER_TYPES.add(CUTOUT_MIPPED); @@ -41,6 +46,16 @@ public static TerrainRenderType get(RenderType renderType) { return ((ExtendedRenderType)renderType).getTerrainRenderType(); } + public static TerrainRenderType get(ChunkSectionLayer layer) { + return switch (layer) { + case SOLID -> SOLID; + case CUTOUT_MIPPED -> CUTOUT_MIPPED; + case CUTOUT -> CUTOUT; + case TRANSLUCENT -> TRANSLUCENT; + case TRIPWIRE -> TRIPWIRE; + }; + } + public static TerrainRenderType get(String name) { return switch (name) { case "solid" -> TerrainRenderType.SOLID; @@ -52,13 +67,32 @@ public static TerrainRenderType get(String name) { }; } - public static RenderType getRenderType(TerrainRenderType renderType) { + public static ChunkSectionLayer getLayer(TerrainRenderType renderType) { return switch (renderType) { - case SOLID -> RenderType.solid(); - case CUTOUT -> RenderType.cutout(); - case CUTOUT_MIPPED -> RenderType.cutoutMipped(); - case TRANSLUCENT -> RenderType.translucent(); - case TRIPWIRE -> RenderType.tripwire(); + case SOLID -> ChunkSectionLayer.SOLID; + case CUTOUT -> ChunkSectionLayer.CUTOUT; + case CUTOUT_MIPPED -> ChunkSectionLayer.CUTOUT_MIPPED; + case TRANSLUCENT -> ChunkSectionLayer.TRANSLUCENT; + case TRIPWIRE -> ChunkSectionLayer.TRIPWIRE; }; } + + public static void updateMapping() { + if (Initializer.CONFIG.uniqueOpaqueLayer) { + remapper = (renderType) -> switch (renderType) { + case SOLID, CUTOUT, CUTOUT_MIPPED -> TerrainRenderType.CUTOUT_MIPPED; + case TRANSLUCENT, TRIPWIRE -> TerrainRenderType.TRANSLUCENT; + }; + } else { + remapper = (renderType) -> switch (renderType) { + case SOLID, CUTOUT_MIPPED -> TerrainRenderType.CUTOUT_MIPPED; + case CUTOUT -> TerrainRenderType.CUTOUT; + case TRANSLUCENT, TRIPWIRE -> TerrainRenderType.TRANSLUCENT; + }; + } + } + + public static TerrainRenderType getRemapped(TerrainRenderType renderType) { + return remapper.apply(renderType); + } } diff --git a/src/main/java/net/vulkanmod/render/vertex/VertexBuilder.java b/src/main/java/net/vulkanmod/render/vertex/VertexBuilder.java index 511845515..5f6555459 100644 --- a/src/main/java/net/vulkanmod/render/vertex/VertexBuilder.java +++ b/src/main/java/net/vulkanmod/render/vertex/VertexBuilder.java @@ -5,6 +5,16 @@ public interface VertexBuilder { void vertex(long ptr, float x, float y, float z, int color, float u, float v, int light, int packedNormal); + void position(long ptr, float x, float y, float z); + + void color(long ptr, int color); + + void uv(long ptr, float u, float v); + + void light(long ptr, int light); + + void normal(long ptr, int normal); + int getStride(); class DefaultVertexBuilder implements VertexBuilder { @@ -26,6 +36,32 @@ public void vertex(long ptr, float x, float y, float z, int color, float u, floa MemoryUtil.memPutInt(ptr + 28, packedNormal); } + // TODO + @Override + public void position(long ptr, float x, float y, float z) { + + } + + @Override + public void color(long ptr, int color) { + + } + + @Override + public void uv(long ptr, float u, float v) { + + } + + @Override + public void light(long ptr, int light) { + + } + + @Override + public void normal(long ptr, int normal) { + + } + @Override public int getStride() { return VERTEX_SIZE; @@ -33,7 +69,7 @@ public int getStride() { } class CompressedVertexBuilder implements VertexBuilder { - private static final int VERTEX_SIZE = 20; + private static final int VERTEX_SIZE = 16; public static final float POS_CONV_MUL = 2048.0f; public static final float POS_OFFSET = -4.0f; @@ -53,10 +89,43 @@ public void vertex(long ptr, float x, float y, float z, int color, float u, floa final short l = (short) (((light >>> 8) & 0xFF00) | (light & 0xFF)); MemoryUtil.memPutShort(ptr + 6, l); - MemoryUtil.memPutInt(ptr + 8, color); + MemoryUtil.memPutShort(ptr + 8, (short) (u * UV_CONV_MUL)); + MemoryUtil.memPutShort(ptr + 10, (short) (v * UV_CONV_MUL)); + + MemoryUtil.memPutInt(ptr + 12, color); + } + + @Override + public void position(long ptr, float x, float y, float z) { + final short sX = (short) (x * POS_CONV_MUL + POS_OFFSET_CONV); + final short sY = (short) (y * POS_CONV_MUL + POS_OFFSET_CONV); + final short sZ = (short) (z * POS_CONV_MUL + POS_OFFSET_CONV); + + MemoryUtil.memPutShort(ptr + 0, sX); + MemoryUtil.memPutShort(ptr + 2, sY); + MemoryUtil.memPutShort(ptr + 4, sZ); + } + + @Override + public void color(long ptr, int color) { + MemoryUtil.memPutInt(ptr + 12, color); + } + + @Override + public void uv(long ptr, float u, float v) { + MemoryUtil.memPutShort(ptr + 8, (short) (u * UV_CONV_MUL)); + MemoryUtil.memPutShort(ptr + 10, (short) (v * UV_CONV_MUL)); + } + + @Override + public void light(long ptr, int light) { + final short l = (short) (((light >>> 8) & 0xFF00) | (light & 0xFF)); + MemoryUtil.memPutShort(ptr + 6, l); + } + + @Override + public void normal(long ptr, int normal) { - MemoryUtil.memPutShort(ptr + 12, (short) (u * UV_CONV_MUL)); - MemoryUtil.memPutShort(ptr + 14, (short) (v * UV_CONV_MUL)); } @Override diff --git a/src/main/java/net/vulkanmod/render/vertex/VertexUtil.java b/src/main/java/net/vulkanmod/render/vertex/format/I32_SNorm.java similarity index 73% rename from src/main/java/net/vulkanmod/render/vertex/VertexUtil.java rename to src/main/java/net/vulkanmod/render/vertex/format/I32_SNorm.java index 00777f51c..fb8366991 100644 --- a/src/main/java/net/vulkanmod/render/vertex/VertexUtil.java +++ b/src/main/java/net/vulkanmod/render/vertex/format/I32_SNorm.java @@ -1,7 +1,6 @@ -package net.vulkanmod.render.vertex; - -public class VertexUtil { +package net.vulkanmod.render.vertex.format; +public abstract class I32_SNorm { private static final float NORM_INV = 1.0f / 127.0f; public static int packNormal(float x, float y, float z) { @@ -16,16 +15,15 @@ public static int packNormal(int x, int y, int z) { return (x & 0xFF) | (y & 0xFF) << 8| (z & 0xFF) << 16; } - public static float unpackN1(int i) { + public static float unpackX(int i) { return (byte)(i & 0xFF) * NORM_INV; } - public static float unpackN2(int i) { + public static float unpackY(int i) { return (byte)((i >> 8) & 0xFF) * NORM_INV; } - public static float unpackN3(int i) { + public static float unpackZ(int i) { return (byte)((i >> 16) & 0xFF) * NORM_INV; } - } diff --git a/src/main/java/net/vulkanmod/vulkan/Drawer.java b/src/main/java/net/vulkanmod/vulkan/Drawer.java index 40b88274b..f71363c0c 100644 --- a/src/main/java/net/vulkanmod/vulkan/Drawer.java +++ b/src/main/java/net/vulkanmod/vulkan/Drawer.java @@ -2,6 +2,11 @@ import com.mojang.blaze3d.vertex.VertexFormat; import net.vulkanmod.vulkan.memory.*; +import net.vulkanmod.vulkan.memory.buffer.Buffer; +import net.vulkanmod.vulkan.memory.buffer.IndexBuffer; +import net.vulkanmod.vulkan.memory.buffer.UniformBuffer; +import net.vulkanmod.vulkan.memory.buffer.VertexBuffer; +import net.vulkanmod.vulkan.memory.buffer.index.AutoIndexBuffer; import net.vulkanmod.vulkan.util.VUtil; import org.lwjgl.system.MemoryUtil; import org.lwjgl.vulkan.VkCommandBuffer; @@ -13,7 +18,8 @@ import static org.lwjgl.vulkan.VK10.*; public class Drawer { - private static final int INITIAL_VB_SIZE = 2000000; + private static final int INITIAL_VB_SIZE = 4000000; + private static final int INITIAL_IB_SIZE = 1000000; private static final int INITIAL_UB_SIZE = 200000; private static final LongBuffer buffers = MemoryUtil.memAllocLong(1); @@ -23,19 +29,22 @@ public class Drawer { private int framesNum; private VertexBuffer[] vertexBuffers; + private IndexBuffer[] indexBuffers; + private final AutoIndexBuffer quadsIndexBuffer; private final AutoIndexBuffer quadsIntIndexBuffer; private final AutoIndexBuffer linesIndexBuffer; private final AutoIndexBuffer debugLineStripIndexBuffer; private final AutoIndexBuffer triangleFanIndexBuffer; private final AutoIndexBuffer triangleStripIndexBuffer; + private UniformBuffer[] uniformBuffers; private int currentFrame; public Drawer() { // Index buffers - this.quadsIndexBuffer = new AutoIndexBuffer(AutoIndexBuffer.QUAD_U16_MAX_VERTEX_COUNT, AutoIndexBuffer.DrawType.QUADS); + this.quadsIndexBuffer = new AutoIndexBuffer(AutoIndexBuffer.U16_MAX_VERTEX_COUNT, AutoIndexBuffer.DrawType.QUADS); this.quadsIntIndexBuffer = new AutoIndexBuffer(100000, AutoIndexBuffer.DrawType.QUADS); this.linesIndexBuffer = new AutoIndexBuffer(10000, AutoIndexBuffer.DrawType.LINES); this.debugLineStripIndexBuffer = new AutoIndexBuffer(10000, AutoIndexBuffer.DrawType.DEBUG_LINE_STRIP); @@ -52,15 +61,23 @@ public void createResources(int framesNum) { if (this.vertexBuffers != null) { Arrays.stream(this.vertexBuffers).iterator().forEachRemaining( - Buffer::freeBuffer + Buffer::scheduleFree ); } this.vertexBuffers = new VertexBuffer[framesNum]; Arrays.setAll(this.vertexBuffers, i -> new VertexBuffer(INITIAL_VB_SIZE, MemoryTypes.HOST_MEM)); + if (this.indexBuffers != null) { + Arrays.stream(this.indexBuffers).iterator().forEachRemaining( + Buffer::scheduleFree + ); + } + this.indexBuffers = new IndexBuffer[framesNum]; + Arrays.setAll(this.indexBuffers, i -> new IndexBuffer(INITIAL_IB_SIZE, MemoryTypes.HOST_MEM)); + if (this.uniformBuffers != null) { Arrays.stream(this.uniformBuffers).iterator().forEachRemaining( - Buffer::freeBuffer + Buffer::scheduleFree ); } this.uniformBuffers = new UniformBuffer[framesNum]; @@ -69,64 +86,54 @@ public void createResources(int framesNum) { public void resetBuffers(int currentFrame) { this.vertexBuffers[currentFrame].reset(); + this.indexBuffers[currentFrame].reset(); this.uniformBuffers[currentFrame].reset(); } - public void draw(ByteBuffer buffer, VertexFormat.Mode mode, VertexFormat vertexFormat, int vertexCount) { - AutoIndexBuffer autoIndexBuffer; - int indexCount; + public void draw(ByteBuffer vertexData, VertexFormat.Mode mode, VertexFormat vertexFormat, int vertexCount) { + draw(vertexData, null, mode, vertexFormat, vertexCount); + } + public void draw(ByteBuffer vertexData, ByteBuffer indexData, VertexFormat.Mode mode, VertexFormat vertexFormat, int vertexCount) { VertexBuffer vertexBuffer = this.vertexBuffers[this.currentFrame]; - vertexBuffer.copyToVertexBuffer(vertexFormat.getVertexSize(), vertexCount, buffer); + int size = vertexFormat.getVertexSize() * vertexCount; + vertexBuffer.copyBuffer(vertexData, size); - switch (mode) { - case QUADS -> { - indexCount = vertexCount * 3 / 2; + if (indexData != null) { + IndexBuffer indexBuffer = this.indexBuffers[this.currentFrame]; + indexBuffer.copyBuffer(indexData, indexData.remaining()); - autoIndexBuffer = indexCount > AutoIndexBuffer.U16_MAX_INDEX_COUNT - ? this.quadsIntIndexBuffer : this.quadsIndexBuffer; - } - case LINES -> { - autoIndexBuffer = this.linesIndexBuffer; - indexCount = vertexCount * 3 / 2; - } - case TRIANGLE_FAN -> { - autoIndexBuffer = this.triangleFanIndexBuffer; - indexCount = (vertexCount - 2) * 3; - } - case TRIANGLE_STRIP, LINE_STRIP -> { - autoIndexBuffer = this.triangleStripIndexBuffer; - indexCount = (vertexCount - 2) * 3; - } - case DEBUG_LINE_STRIP -> { - autoIndexBuffer = this.debugLineStripIndexBuffer; - indexCount = (vertexCount - 1) * 2; - } - case TRIANGLES, DEBUG_LINES -> { - indexCount = 0; - autoIndexBuffer = null; - } - default -> throw new RuntimeException(String.format("unknown drawMode: %s", mode)); + int indexCount = vertexCount * 3 / 2; + + drawIndexed(vertexBuffer, indexBuffer, indexCount); } + else { + AutoIndexBuffer autoIndexBuffer = getAutoIndexBuffer(mode, vertexCount); - if (indexCount > 0) { - autoIndexBuffer.checkCapacity(vertexCount); + if (autoIndexBuffer != null) { + int indexCount = autoIndexBuffer.getIndexCount(vertexCount); + autoIndexBuffer.checkCapacity(vertexCount); - drawIndexed(vertexBuffer, autoIndexBuffer.getIndexBuffer(), indexCount); - } else { - draw(vertexBuffer, vertexCount); + drawIndexed(vertexBuffer, autoIndexBuffer.getIndexBuffer(), indexCount); + } + else { + draw(vertexBuffer, vertexCount); + } } + } + public void drawIndexed(Buffer vertexBuffer, IndexBuffer indexBuffer, int indexCount) { + drawIndexed(vertexBuffer, indexBuffer, indexCount, indexBuffer.indexType.value); } - public void drawIndexed(VertexBuffer vertexBuffer, IndexBuffer indexBuffer, int indexCount) { + public void drawIndexed(Buffer vertexBuffer, Buffer indexBuffer, int indexCount, int indexType) { VkCommandBuffer commandBuffer = Renderer.getCommandBuffer(); VUtil.UNSAFE.putLong(pBuffers, vertexBuffer.getId()); VUtil.UNSAFE.putLong(pOffsets, vertexBuffer.getOffset()); nvkCmdBindVertexBuffers(commandBuffer, 0, 1, pBuffers, pOffsets); - bindIndexBuffer(commandBuffer, indexBuffer); + bindIndexBuffer(commandBuffer, indexBuffer, indexType); vkCmdDrawIndexed(commandBuffer, indexCount, 1, 0, 0, 0); } @@ -140,8 +147,8 @@ public void draw(VertexBuffer vertexBuffer, int vertexCount) { vkCmdDraw(commandBuffer, vertexCount, 1, 0, 0); } - public void bindIndexBuffer(VkCommandBuffer commandBuffer, IndexBuffer indexBuffer) { - vkCmdBindIndexBuffer(commandBuffer, indexBuffer.getId(), indexBuffer.getOffset(), indexBuffer.indexType.type); + public void bindIndexBuffer(VkCommandBuffer commandBuffer, Buffer indexBuffer, int indexType) { + vkCmdBindIndexBuffer(commandBuffer, indexBuffer.getId(), indexBuffer.getOffset(), indexType); } public void cleanUpResources() { @@ -150,14 +157,18 @@ public void cleanUpResources() { buffer = this.vertexBuffers[i]; MemoryManager.freeBuffer(buffer.getId(), buffer.getAllocation()); - buffer = this.uniformBuffers[i]; + buffer = this.indexBuffers[i]; MemoryManager.freeBuffer(buffer.getId(), buffer.getAllocation()); + buffer = this.uniformBuffers[i]; + MemoryManager.freeBuffer(buffer.getId(), buffer.getAllocation()); } this.quadsIndexBuffer.freeBuffer(); + this.quadsIntIndexBuffer.freeBuffer(); this.linesIndexBuffer.freeBuffer(); this.triangleFanIndexBuffer.freeBuffer(); + this.triangleStripIndexBuffer.freeBuffer(); this.debugLineStripIndexBuffer.freeBuffer(); } @@ -185,4 +196,19 @@ public UniformBuffer getUniformBuffer() { return this.uniformBuffers[this.currentFrame]; } + public AutoIndexBuffer getAutoIndexBuffer(VertexFormat.Mode mode, int vertexCount) { + return switch (mode) { + case QUADS -> { + int indexCount = vertexCount * 3 / 2; + + yield indexCount > AutoIndexBuffer.U16_MAX_VERTEX_COUNT + ? this.quadsIntIndexBuffer : this.quadsIndexBuffer; + } + case LINES -> this.linesIndexBuffer; + case TRIANGLE_FAN -> this.triangleFanIndexBuffer; + case TRIANGLE_STRIP, LINE_STRIP -> this.triangleStripIndexBuffer; + case DEBUG_LINE_STRIP -> this.debugLineStripIndexBuffer; + case TRIANGLES, DEBUG_LINES -> null; + }; + } } diff --git a/src/main/java/net/vulkanmod/vulkan/Renderer.java b/src/main/java/net/vulkanmod/vulkan/Renderer.java index d06831374..665f4911e 100644 --- a/src/main/java/net/vulkanmod/vulkan/Renderer.java +++ b/src/main/java/net/vulkanmod/vulkan/Renderer.java @@ -1,21 +1,25 @@ package net.vulkanmod.vulkan; +import com.mojang.blaze3d.opengl.GlStateManager; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.minecraft.client.Minecraft; import net.vulkanmod.Initializer; -import net.vulkanmod.gl.GlFramebuffer; +import net.vulkanmod.gl.VkGlFramebuffer; import net.vulkanmod.mixin.window.WindowAccessor; import net.vulkanmod.render.PipelineManager; import net.vulkanmod.render.chunk.WorldRenderer; import net.vulkanmod.render.chunk.buffer.UploadManager; import net.vulkanmod.render.profiling.Profiler; +import net.vulkanmod.render.texture.ImageUploadHelper; import net.vulkanmod.vulkan.device.DeviceManager; import net.vulkanmod.vulkan.framebuffer.Framebuffer; import net.vulkanmod.vulkan.framebuffer.RenderPass; +import net.vulkanmod.vulkan.framebuffer.SwapChain; import net.vulkanmod.vulkan.memory.MemoryManager; import net.vulkanmod.vulkan.pass.DefaultMainPass; import net.vulkanmod.vulkan.pass.MainPass; +import net.vulkanmod.vulkan.queue.CommandPool; import net.vulkanmod.vulkan.shader.GraphicsPipeline; import net.vulkanmod.vulkan.shader.Pipeline; import net.vulkanmod.vulkan.shader.PipelineState; @@ -36,9 +40,9 @@ import java.util.List; import java.util.Set; -import static com.mojang.blaze3d.platform.GlConst.GL_COLOR_BUFFER_BIT; -import static com.mojang.blaze3d.platform.GlConst.GL_DEPTH_BUFFER_BIT; import static net.vulkanmod.vulkan.Vulkan.*; +import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT; +import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT; import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.EXTDebugUtils.*; import static org.lwjgl.vulkan.KHRSwapchain.*; @@ -79,12 +83,14 @@ public static int getCurrentImage() { private Drawer drawer; + private SwapChain swapChain; + private int framesNum; - private int imagesNum; - private List commandBuffers; + private List mainCommandBuffers; private ArrayList imageAvailableSemaphores; private ArrayList renderFinishedSemaphores; private ArrayList inFlightFences; + private List transferCbs; private Framebuffer boundFramebuffer; private RenderPass boundRenderPass; @@ -94,15 +100,15 @@ public static int getCurrentImage() { private static int lastReset = -1; private VkCommandBuffer currentCmdBuffer; private boolean recordingCmds = false; + int recursion = 0; - MainPass mainPass = DefaultMainPass.create(); + MainPass mainPass; private final List onResizeCallbacks = new ObjectArrayList<>(); public Renderer() { device = Vulkan.getVkDevice(); framesNum = Initializer.CONFIG.frameQueueSize; - imagesNum = getSwapChain().getImagesNum(); } public static void setLineWidth(float width) { @@ -116,6 +122,9 @@ private void init() { MemoryManager.createInstance(Renderer.getFramesNum()); Vulkan.createStagingBuffers(); + swapChain = new SwapChain(); + mainPass = DefaultMainPass.create(); + drawer = new Drawer(); drawer.createResources(framesNum); @@ -128,14 +137,13 @@ private void init() { } private void allocateCommandBuffers() { - if (commandBuffers != null) { - commandBuffers.forEach(commandBuffer -> vkFreeCommandBuffers(device, Vulkan.getCommandPool(), commandBuffer)); + if (mainCommandBuffers != null) { + mainCommandBuffers.forEach(commandBuffer -> vkFreeCommandBuffers(device, Vulkan.getCommandPool(), commandBuffer)); } - commandBuffers = new ArrayList<>(framesNum); + mainCommandBuffers = new ArrayList<>(framesNum); try (MemoryStack stack = stackPush()) { - VkCommandBufferAllocateInfo allocInfo = VkCommandBufferAllocateInfo.calloc(stack); allocInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO); allocInfo.commandPool(getCommandPool()); @@ -150,9 +158,22 @@ private void allocateCommandBuffers() { } for (int i = 0; i < framesNum; i++) { - commandBuffers.add(new VkCommandBuffer(pCommandBuffers.get(i), device)); + mainCommandBuffers.add(new VkCommandBuffer(pCommandBuffers.get(i), device)); } } + + if (transferCbs != null) { + transferCbs.forEach(commandBuffer -> { + vkResetCommandBuffer(commandBuffer.handle, 0); + commandBuffer.reset(); + }); + } + + transferCbs = new ArrayList<>(framesNum); + + for (int i = 0; i < framesNum; i++) { + transferCbs.add(DeviceManager.getTransferQueue().getCommandPool().getCommandBuffer()); + } } private void createSyncObjects() { @@ -176,8 +197,8 @@ private void createSyncObjects() { for (int i = 0; i < framesNum; i++) { if (vkCreateSemaphore(device, semaphoreInfo, null, pImageAvailableSemaphore) != VK_SUCCESS - || vkCreateSemaphore(device, semaphoreInfo, null, pRenderFinishedSemaphore) != VK_SUCCESS - || vkCreateFence(device, fenceInfo, null, pFence) != VK_SUCCESS) { + || vkCreateSemaphore(device, semaphoreInfo, null, pRenderFinishedSemaphore) != VK_SUCCESS + || vkCreateFence(device, fenceInfo, null, pFence) != VK_SUCCESS) { throw new RuntimeException("Failed to create synchronization objects for the frame: " + i); } @@ -191,11 +212,27 @@ private void createSyncObjects() { } } - public void beginFrame() { + public void preInitFrame() { Profiler p = Profiler.getMainProfiler(); p.pop(); - p.push("Frame_fence"); + p.round(); + p.push("Frame_ops"); + + // runTick might be called recursively, + // this check forces sync to avoid upload corruption + if (lastReset == currentFrame) { + submitUploads(); + waitFences(); + } + lastReset = currentFrame; + drawer.resetBuffers(currentFrame); + + WorldRenderer.getInstance().uploadSections(); + UploadManager.INSTANCE.submitUploads(); + } + + public void beginFrame() { if (swapChainUpdate) { recreateSwapChain(); swapChainUpdate = false; @@ -209,9 +246,22 @@ public void beginFrame() { } } - - if (skipRendering || recordingCmds) + if (skipRendering) { return; + } + + this.recursion++; + + // In case this is a recursive call end prev frame + if (this.recursion > 1) { + this.endFrame(); + } + + this.preInitFrame(); + + Profiler p = Profiler.getMainProfiler(); + p.pop(); + p.push("Frame_fence"); vkWaitForFences(device, inFlightFences.get(currentFrame), true, VUtil.UINT64_MAX); @@ -223,20 +273,19 @@ public void beginFrame() { resetDescriptors(); - currentCmdBuffer = commandBuffers.get(currentFrame); + currentCmdBuffer = mainCommandBuffers.get(currentFrame); vkResetCommandBuffer(currentCmdBuffer, 0); try (MemoryStack stack = stackPush()) { - IntBuffer pImageIndex = stack.mallocInt(1); - int vkResult = vkAcquireNextImageKHR(device, Vulkan.getSwapChain().getId(), VUtil.UINT64_MAX, - imageAvailableSemaphores.get(currentFrame), VK_NULL_HANDLE, pImageIndex); + int vkResult = vkAcquireNextImageKHR(device, swapChain.getId(), VUtil.UINT64_MAX, + imageAvailableSemaphores.get(currentFrame), VK_NULL_HANDLE, pImageIndex); if (vkResult == VK_SUBOPTIMAL_KHR || vkResult == VK_ERROR_OUT_OF_DATE_KHR || swapChainUpdate) { swapChainUpdate = true; skipRendering = true; - beginFrame(); + this.beginFrame(); return; } else if (vkResult != VK_SUCCESS) { @@ -245,13 +294,13 @@ public void beginFrame() { imageIndex = pImageIndex.get(0); - this.beginRenderPass(stack); + this.beginMainRenderPass(stack); } p.pop(); } - private void beginRenderPass(MemoryStack stack) { + private void beginMainRenderPass(MemoryStack stack) { VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.calloc(stack); beginInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO); beginInfo.flags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); @@ -273,11 +322,19 @@ public void endFrame() { if (skipRendering || !recordingCmds) return; + if (this.recursion == 0) { + return; + } + this.recursion--; + Profiler p = Profiler.getMainProfiler(); p.push("End_rendering"); mainPass.end(currentCmdBuffer); + submitUploads(); + waitFences(); + submitFrame(); recordingCmds = false; @@ -295,19 +352,26 @@ private void submitFrame() { VkSubmitInfo submitInfo = VkSubmitInfo.calloc(stack); submitInfo.sType(VK_STRUCTURE_TYPE_SUBMIT_INFO); - submitInfo.waitSemaphoreCount(1); - submitInfo.pWaitSemaphores(stack.longs(imageAvailableSemaphores.get(currentFrame))); - submitInfo.pWaitDstStageMask(stack.ints(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)); + Synchronization.INSTANCE.addWaitSemaphore(imageAvailableSemaphores.get(currentFrame)); + var waitSemaphores = Synchronization.INSTANCE.getWaitSemaphores(stack); + int waitSemaphoreCount = waitSemaphores.limit(); + IntBuffer waitDstStageMask = stack.mallocInt(waitSemaphoreCount); - submitInfo.pSignalSemaphores(stack.longs(renderFinishedSemaphores.get(currentFrame))); + for (int i = 0; i < waitSemaphoreCount - 1; i++) { + waitDstStageMask.put(i, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + } + // Image available semaphore mask + waitDstStageMask.put(waitSemaphoreCount - 1, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + submitInfo.pWaitSemaphores(waitSemaphores); + submitInfo.waitSemaphoreCount(waitSemaphores.limit()); + submitInfo.pWaitDstStageMask(waitDstStageMask); + submitInfo.pSignalSemaphores(stack.longs(renderFinishedSemaphores.get(currentFrame))); submitInfo.pCommandBuffers(stack.pointers(currentCmdBuffer)); vkResetFences(device, inFlightFences.get(currentFrame)); - Synchronization.INSTANCE.waitFences(); - - if ((vkResult = vkQueueSubmit(DeviceManager.getGraphicsQueue().queue(), submitInfo, inFlightFences.get(currentFrame))) != VK_SUCCESS) { + if ((vkResult = vkQueueSubmit(DeviceManager.getGraphicsQueue().vkQueue(), submitInfo, inFlightFences.get(currentFrame))) != VK_SUCCESS) { vkResetFences(device, inFlightFences.get(currentFrame)); throw new RuntimeException("Failed to submit draw command buffer: %s".formatted(VkResult.decode(vkResult))); } @@ -318,11 +382,11 @@ private void submitFrame() { presentInfo.pWaitSemaphores(stack.longs(renderFinishedSemaphores.get(currentFrame))); presentInfo.swapchainCount(1); - presentInfo.pSwapchains(stack.longs(Vulkan.getSwapChain().getId())); + presentInfo.pSwapchains(stack.longs(swapChain.getId())); presentInfo.pImageIndices(stack.ints(imageIndex)); - vkResult = vkQueuePresentKHR(DeviceManager.getPresentQueue().queue(), presentInfo); + vkResult = vkQueuePresentKHR(DeviceManager.getPresentQueue().vkQueue(), presentInfo); if (vkResult == VK_ERROR_OUT_OF_DATE_KHR || vkResult == VK_SUBOPTIMAL_KHR || swapChainUpdate) { swapChainUpdate = true; @@ -331,12 +395,15 @@ private void submitFrame() { throw new RuntimeException("Failed to present rendered frame: %s".formatted(VkResult.decode(vkResult))); } + // Semaphore waited command buffers will be reset right after waiting this command buffer's fence + Synchronization.INSTANCE.scheduleCbReset(); + currentFrame = (currentFrame + 1) % framesNum; } } /** - * Called in case draw results are needed before the of the frame + * Called in case draw results are needed before the end of the frame */ public void flushCmds() { if (!this.recordingCmds) @@ -355,42 +422,64 @@ public void flushCmds() { vkResetFences(device, inFlightFences.get(currentFrame)); - Synchronization.INSTANCE.waitFences(); + submitUploads(); + waitFences(); - if ((vkResult = vkQueueSubmit(DeviceManager.getGraphicsQueue().queue(), submitInfo, inFlightFences.get(currentFrame))) != VK_SUCCESS) { + if ((vkResult = vkQueueSubmit(DeviceManager.getGraphicsQueue().vkQueue(), submitInfo, inFlightFences.get(currentFrame))) != VK_SUCCESS) { vkResetFences(device, inFlightFences.get(currentFrame)); throw new RuntimeException("Failed to submit draw command buffer: %s".formatted(VkResult.decode(vkResult))); } vkWaitForFences(device, inFlightFences.get(currentFrame), true, VUtil.UINT64_MAX); - this.beginRenderPass(stack); + this.beginMainRenderPass(stack); } } + public void submitUploads() { + var transferCb = transferCbs.get(currentFrame); + + if (transferCb.isRecording()) { + final var transferQueue = DeviceManager.getTransferQueue(); + try (MemoryStack stack = MemoryStack.stackPush()) { + transferCb.submitCommands(stack, transferQueue.vkQueue(), true); + } + + Synchronization.INSTANCE.addCommandBuffer(transferCb, true); + + transferCbs.set(currentFrame, transferQueue.getCommandPool().getCommandBuffer()); + } + + ImageUploadHelper.INSTANCE.submitCommands(); + } + public void endRenderPass() { endRenderPass(currentCmdBuffer); } public void endRenderPass(VkCommandBuffer commandBuffer) { - if (skipRendering || this.boundFramebuffer == null) + if (skipRendering || !recordingCmds || this.boundFramebuffer == null) return; - if (!DYNAMIC_RENDERING) - this.boundRenderPass.endRenderPass(currentCmdBuffer); - else - KHRDynamicRendering.vkCmdEndRenderingKHR(commandBuffer); + this.boundRenderPass.endRenderPass(commandBuffer); this.boundRenderPass = null; this.boundFramebuffer = null; - GlFramebuffer.resetBoundFramebuffer(); + VkGlFramebuffer.resetBoundFramebuffer(); } - public boolean beginRendering(RenderPass renderPass, Framebuffer framebuffer) { - if (skipRendering || !recordingCmds) + public boolean beginRenderPass(RenderPass renderPass, Framebuffer framebuffer) { + // TODO: minimizing could trigger this preventing rendering (e.g. texture atlas uploads) + if (skipRendering) return false; + if (!recordingCmds) { + this.beginFrame(); + + recordingCmds = true; + } + if (this.boundFramebuffer != framebuffer) { this.endRenderPass(currentCmdBuffer); @@ -399,29 +488,13 @@ public boolean beginRendering(RenderPass renderPass, Framebuffer framebuffer) { } this.boundFramebuffer = framebuffer; - } - return true; - } + this.boundRenderPass = renderPass; - public void preInitFrame() { - Profiler p = Profiler.getMainProfiler(); - p.pop(); - p.round(); - p.push("Frame_ops"); - - // runTick might be called recursively, - // this check forces sync to avoid upload corruption - if (lastReset == currentFrame) { - Synchronization.INSTANCE.waitFences(); + Renderer.setViewportState(0, 0, framebuffer.getWidth(), framebuffer.getHeight()); + Renderer.setScissor(0, 0, framebuffer.getWidth(), framebuffer.getHeight()); } - lastReset = currentFrame; - - drawer.resetBuffers(currentFrame); - - Vulkan.getStagingBuffer().reset(); - WorldRenderer.getInstance().uploadSections(); - UploadManager.INSTANCE.submitUploads(); + return true; } public void addUsedPipeline(Pipeline pipeline) { @@ -432,6 +505,12 @@ public void removeUsedPipeline(Pipeline pipeline) { usedPipelines.remove(pipeline); } + private void waitFences() { + // Make sure there are no uploads/transitions scheduled + Synchronization.INSTANCE.waitFences(); + Vulkan.getStagingBuffer().reset(); + } + private void resetDescriptors() { for (Pipeline pipeline : usedPipelines) { pipeline.resetDescriptorPool(currentFrame); @@ -449,34 +528,36 @@ void waitForSwapChain() { try (MemoryStack stack = MemoryStack.stackPush()) { //Empty Submit VkSubmitInfo info = VkSubmitInfo.calloc(stack) - .sType$Default() - .pWaitSemaphores(stack.longs(imageAvailableSemaphores.get(currentFrame))) - .pWaitDstStageMask(stack.ints(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)); + .sType$Default() + .pWaitSemaphores(stack.longs(imageAvailableSemaphores.get(currentFrame))) + .pWaitDstStageMask(stack.ints(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)); - vkQueueSubmit(DeviceManager.getGraphicsQueue().queue(), info, inFlightFences.get(currentFrame)); + vkQueueSubmit(DeviceManager.getGraphicsQueue().vkQueue(), info, inFlightFences.get(currentFrame)); vkWaitForFences(device, inFlightFences.get(currentFrame), true, -1); } } @SuppressWarnings("UnreachableCode") private void recreateSwapChain() { - Synchronization.INSTANCE.waitFences(); + submitUploads(); + waitFences(); Vulkan.waitIdle(); - commandBuffers.forEach(commandBuffer -> vkResetCommandBuffer(commandBuffer, 0)); + mainCommandBuffers.forEach(commandBuffer -> vkResetCommandBuffer(commandBuffer, 0)); + recordingCmds = false; - Vulkan.getSwapChain().recreate(); + swapChain.recreate(); //Semaphores need to be recreated in order to make them unsignaled destroySyncObjects(); int newFramesNum = Initializer.CONFIG.frameQueueSize; - imagesNum = getSwapChain().getImagesNum(); if (framesNum != newFramesNum) { UploadManager.INSTANCE.submitUploads(); framesNum = newFramesNum; + MemoryManager.getInstance().freeAllBuffers(); MemoryManager.createInstance(newFramesNum); createStagingBuffers(); allocateCommandBuffers(); @@ -487,6 +568,7 @@ private void recreateSwapChain() { } createSyncObjects(); + this.mainPass.onResize(); this.onResizeCallbacks.forEach(Runnable::run); ((WindowAccessor) (Object) Minecraft.getInstance().getWindow()).getEventHandler().resizeDisplay(); @@ -495,9 +577,12 @@ private void recreateSwapChain() { } public void cleanUpResources() { + WorldRenderer.getInstance().cleanUp(); destroySyncObjects(); drawer.cleanUpResources(); + mainPass.cleanUp(); + swapChain.cleanUp(); PipelineManager.destroyPipelines(); VTextureSelector.getWhiteTexture().free(); @@ -511,26 +596,6 @@ private void destroySyncObjects() { } } - public void setBoundFramebuffer(Framebuffer framebuffer) { - this.boundFramebuffer = framebuffer; - } - - public void setBoundRenderPass(RenderPass boundRenderPass) { - this.boundRenderPass = boundRenderPass; - } - - public RenderPass getBoundRenderPass() { - return boundRenderPass; - } - - public void setMainPass(MainPass mainPass) { - this.mainPass = mainPass; - } - - public MainPass getMainPass() { - return this.mainPass; - } - public void addOnResizeCallback(Runnable runnable) { this.onResizeCallbacks.add(runnable); } @@ -575,27 +640,75 @@ public Pipeline getBoundPipeline() { return boundPipeline; } + public void setBoundFramebuffer(Framebuffer framebuffer) { + this.boundFramebuffer = framebuffer; + } + + public Framebuffer getBoundFramebuffer() { + return boundFramebuffer; + } + + public void setBoundRenderPass(RenderPass boundRenderPass) { + this.boundRenderPass = boundRenderPass; + } + + public RenderPass getBoundRenderPass() { + return boundRenderPass; + } + + public void setMainPass(MainPass mainPass) { + this.mainPass = mainPass; + } + + public MainPass getMainPass() { + return this.mainPass; + } + + public SwapChain getSwapChain() { + return swapChain; + } + + public CommandPool.CommandBuffer getTransferCb() { + return transferCbs.get(currentFrame); + } + private static void resetDynamicState(VkCommandBuffer commandBuffer) { vkCmdSetDepthBias(commandBuffer, 0.0F, 0.0F, 0.0F); vkCmdSetLineWidth(commandBuffer, 1.0F); } - public static void setDepthBias(float units, float factor) { + public static void setDepthBias(float constant, float slope) { VkCommandBuffer commandBuffer = INSTANCE.currentCmdBuffer; - vkCmdSetDepthBias(commandBuffer, units, 0.0f, factor); + vkCmdSetDepthBias(commandBuffer, constant, 0.0f, slope); + } + + public static void clearAttachments(int attachments) { + clearAttachments(INSTANCE.currentCmdBuffer, attachments); } - public static void clearAttachments(int v) { + public static void clearAttachments(VkCommandBuffer commandBuffer, int attachments) { Framebuffer framebuffer = Renderer.getInstance().boundFramebuffer; if (framebuffer == null) return; - clearAttachments(v, framebuffer.getWidth(), framebuffer.getHeight()); + clearAttachments(commandBuffer, attachments, framebuffer.getWidth(), framebuffer.getHeight()); } - public static void clearAttachments(int v, int width, int height) { + public static void clearAttachments(int attachments, int width, int height) { + clearAttachments(INSTANCE.currentCmdBuffer, attachments, width , height); + } + + public static void clearAttachments(int attachments, int x, int y, int width, int height) { + clearAttachments(INSTANCE.currentCmdBuffer, attachments, x, y, width , height); + } + + public static void clearAttachments(VkCommandBuffer commandBuffer, int attachments, int width, int height) { + clearAttachments(commandBuffer, attachments, 0, 0, width, height); + } + + public static void clearAttachments(VkCommandBuffer commandBuffer, int attachments, int x, int y, int width, int height) { if (skipRendering) return; @@ -608,9 +721,9 @@ public static void clearAttachments(int v, int width, int height) { VkClearValue depthValue = VkClearValue.calloc(stack); depthValue.depthStencil().set(VRenderSystem.clearDepthValue, 0); //Use fast depth clears if possible - int attachmentsCount = v == (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT) ? 2 : 1; + int attachmentsCount = attachments == (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT) ? 2 : 1; final VkClearAttachment.Buffer pAttachments = VkClearAttachment.malloc(attachmentsCount, stack); - switch (v) { + switch (attachments) { case GL_DEPTH_BUFFER_BIT -> { VkClearAttachment clearDepth = pAttachments.get(0); @@ -642,7 +755,7 @@ public static void clearAttachments(int v, int width, int height) { //Rect to clear VkRect2D renderArea = VkRect2D.malloc(stack); - renderArea.offset().set(0, 0); + renderArea.offset().set(x, y); renderArea.extent().set(width, height); VkClearRect.Buffer pRect = VkClearRect.malloc(1, stack); @@ -650,12 +763,23 @@ public static void clearAttachments(int v, int width, int height) { pRect.baseArrayLayer(0); pRect.layerCount(1); - vkCmdClearAttachments(INSTANCE.currentCmdBuffer, pAttachments, pRect); + vkCmdClearAttachments(commandBuffer, pAttachments, pRect); } } public static void setInvertedViewport(int x, int y, int width, int height) { - setViewport(x, y + height, width, -height); + setViewportState(x, y + height, width, -height); + } + + public static void resetViewport() { + int width = INSTANCE.getSwapChain().getWidth(); + int height = INSTANCE.getSwapChain().getHeight(); + + setViewportState(0, 0, width, height); + } + + public static void setViewportState(int x, int y, int width, int height) { + GlStateManager._viewport(x, y, width, height); } public static void setViewport(int x, int y, int width, int height) { @@ -679,25 +803,8 @@ public static void setViewport(int x, int y, int width, int height, MemoryStack vkCmdSetViewport(INSTANCE.currentCmdBuffer, 0, viewport); } - public static void resetViewport() { - try (MemoryStack stack = stackPush()) { - int width = getSwapChain().getWidth(); - int height = getSwapChain().getHeight(); - - VkViewport.Buffer viewport = VkViewport.malloc(1, stack); - viewport.x(0.0f); - viewport.y(height); - viewport.width(width); - viewport.height(-height); - viewport.minDepth(0.0f); - viewport.maxDepth(1.0f); - - vkCmdSetViewport(INSTANCE.currentCmdBuffer, 0, viewport); - } - } - public static void setScissor(int x, int y, int width, int height) { - if (INSTANCE.boundFramebuffer == null) + if (!INSTANCE.recordingCmds || INSTANCE.boundFramebuffer == null) return; try (MemoryStack stack = stackPush()) { diff --git a/src/main/java/net/vulkanmod/vulkan/Synchronization.java b/src/main/java/net/vulkanmod/vulkan/Synchronization.java index 609052db3..8a1b971d8 100644 --- a/src/main/java/net/vulkanmod/vulkan/Synchronization.java +++ b/src/main/java/net/vulkanmod/vulkan/Synchronization.java @@ -1,8 +1,11 @@ package net.vulkanmod.vulkan; +import it.unimi.dsi.fastutil.longs.LongArrayList; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.vulkanmod.vulkan.memory.MemoryManager; import net.vulkanmod.vulkan.queue.CommandPool; import net.vulkanmod.vulkan.util.VUtil; +import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryUtil; import org.lwjgl.vulkan.VkDevice; @@ -10,6 +13,9 @@ import static org.lwjgl.vulkan.VK10.*; +/*** + * Synchronization utility to sync in frame ops that need to be completed before executing main cmd buffer. + */ public class Synchronization { private static final int ALLOCATION_SIZE = 50; @@ -18,15 +24,28 @@ public class Synchronization { private final LongBuffer fences; private int idx = 0; - private ObjectArrayList commandBuffers = new ObjectArrayList<>(); + private final ObjectArrayList fenceCbs = new ObjectArrayList<>(); + + private final LongArrayList semaphores = new LongArrayList(); + private final ObjectArrayList semaphoreCbs = new ObjectArrayList<>(); Synchronization(int allocSize) { this.fences = MemoryUtil.memAllocLong(allocSize); } - public synchronized void addCommandBuffer(CommandPool.CommandBuffer commandBuffer) { - this.addFence(commandBuffer.getFence()); - this.commandBuffers.add(commandBuffer); + public void addCommandBuffer(CommandPool.CommandBuffer commandBuffer) { + addCommandBuffer(commandBuffer, false); + } + + public synchronized void addCommandBuffer(CommandPool.CommandBuffer commandBuffer, boolean useSemaphore) { + if (!useSemaphore) { + this.addFence(commandBuffer.getFence()); + this.fenceCbs.add(commandBuffer); + } + else { + this.semaphores.add(commandBuffer.getSemaphore()); + this.semaphoreCbs.add(commandBuffer); + } } public synchronized void addFence(long fence) { @@ -47,13 +66,37 @@ public synchronized void waitFences() { vkWaitForFences(device, fences, true, VUtil.UINT64_MAX); - this.commandBuffers.forEach(CommandPool.CommandBuffer::reset); - this.commandBuffers.clear(); + this.fenceCbs.forEach(CommandPool.CommandBuffer::reset); + this.fenceCbs.clear(); fences.limit(ALLOCATION_SIZE); idx = 0; } + public synchronized void addWaitSemaphore(long semaphore) { + this.semaphores.add(semaphore); + } + + public LongBuffer getWaitSemaphores(MemoryStack stack) { + var buffer = stack.mallocLong(this.semaphores.size()) + .put(this.semaphores.elements(), 0, this.semaphores.size()); + buffer.flip(); + + this.semaphores.clear(); + return buffer; + } + + public void scheduleCbReset() { + final var frameSemaphoreCbs = this.semaphoreCbs.clone(); + MemoryManager.getInstance().addFrameOp( + () -> { + frameSemaphoreCbs.forEach(CommandPool.CommandBuffer::reset); + } + ); + + this.semaphoreCbs.clear(); + } + public static void waitFence(long fence) { VkDevice device = Vulkan.getVkDevice(); diff --git a/src/main/java/net/vulkanmod/vulkan/VRenderSystem.java b/src/main/java/net/vulkanmod/vulkan/VRenderSystem.java index 08bd5bdc6..fb1fe4468 100644 --- a/src/main/java/net/vulkanmod/vulkan/VRenderSystem.java +++ b/src/main/java/net/vulkanmod/vulkan/VRenderSystem.java @@ -1,10 +1,11 @@ package net.vulkanmod.vulkan; -import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.buffers.GpuBufferSlice; import com.mojang.blaze3d.platform.Window; -import com.mojang.blaze3d.systems.RenderSystem; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.fog.FogData; +import net.vulkanmod.render.engine.VkGpuBuffer; import net.vulkanmod.vulkan.device.DeviceManager; import net.vulkanmod.vulkan.shader.PipelineState; import net.vulkanmod.vulkan.util.ColorUtil; @@ -46,21 +47,26 @@ public abstract class VRenderSystem { public static MappedBuffer TextureMatrix = new MappedBuffer(16 * 4); public static MappedBuffer MVP = new MappedBuffer(16 * 4); - public static MappedBuffer ChunkOffset = new MappedBuffer(3 * 4); + public static MappedBuffer modelOffset = new MappedBuffer(3 * 4); public static MappedBuffer lightDirection0 = new MappedBuffer(3 * 4); public static MappedBuffer lightDirection1 = new MappedBuffer(3 * 4); public static MappedBuffer shaderColor = new MappedBuffer(4 * 4); public static MappedBuffer shaderFogColor = new MappedBuffer(4 * 4); + public static FogData fogData; public static MappedBuffer screenSize = new MappedBuffer(2 * 4); public static float alphaCutout = 0.0f; - private static final float[] depthBias = new float[2]; + private static boolean depthBiasEnabled = false; + private static float depthBiasConstant = 0.0f; + private static float depthBiasSlope = 0.0f; public static void initRenderer() { Vulkan.initVulkan(window); + + setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); } public static MappedBuffer getScreenSize() { @@ -79,8 +85,8 @@ public static void setWindow(long window) { VRenderSystem.window = window; } - public static ByteBuffer getChunkOffset() { - return ChunkOffset.buffer; + public static ByteBuffer getModelOffset() { + return modelOffset.buffer; } public static int maxSupportedTextureSize() { @@ -95,13 +101,20 @@ public static void applyMVP(Matrix4f MV, Matrix4f P) { public static void applyModelViewMatrix(Matrix4f mat) { mat.get(modelViewMatrix.buffer.asFloatBuffer()); - //MemoryUtil.memPutFloat(MemoryUtil.memAddress(modelViewMatrix), 1); } public static void applyProjectionMatrix(Matrix4f mat) { mat.get(projectionMatrix.buffer.asFloatBuffer()); } + public static void applyProjectionMatrix(GpuBufferSlice bufferSlice) { + long ptr = ((VkGpuBuffer) bufferSlice.buffer()).getBuffer().getDataPtr(); + ByteBuffer byteBuffer = MemoryUtil.memByteBuffer(ptr + bufferSlice.offset(), bufferSlice.length()); + Matrix4f matrix4f = new Matrix4f().set(byteBuffer); + + matrix4f.get(projectionMatrix.buffer.asFloatBuffer()); + } + public static void calculateMVP() { org.joml.Matrix4f MV = new org.joml.Matrix4f(modelViewMatrix.buffer.asFloatBuffer()); org.joml.Matrix4f P = new org.joml.Matrix4f(projectionMatrix.buffer.asFloatBuffer()); @@ -129,11 +142,11 @@ public static MappedBuffer getMVP() { return MVP; } - public static void setChunkOffset(float f1, float f2, float f3) { - long ptr = ChunkOffset.ptr; - VUtil.UNSAFE.putFloat(ptr, f1); - VUtil.UNSAFE.putFloat(ptr + 4, f2); - VUtil.UNSAFE.putFloat(ptr + 8, f3); + public static void setModelOffset(float x, float y, float z) { + long ptr = modelOffset.ptr; + VUtil.UNSAFE.putFloat(ptr, x); + VUtil.UNSAFE.putFloat(ptr + 4, y); + VUtil.UNSAFE.putFloat(ptr + 8, z); } public static void setShaderColor(float f1, float f2, float f3, float f4) { @@ -152,6 +165,10 @@ public static MappedBuffer getShaderFogColor() { return shaderFogColor; } + public static FogData getFogData() { + return fogData; + } + public static void setClearColor(float f1, float f2, float f3, float f4) { ColorUtil.setRGBA_Buffer(clearColor, f1, f2, f3, f4); } @@ -229,22 +246,18 @@ public static void disableBlend() { PipelineState.blendInfo.enabled = false; } - public static void blendFunc(GlStateManager.SourceFactor sourceFactor, GlStateManager.DestFactor destFactor) { - PipelineState.blendInfo.setBlendFunction(sourceFactor, destFactor); - } - public static void blendFunc(int srcFactor, int dstFactor) { PipelineState.blendInfo.setBlendFunction(srcFactor, dstFactor); } - public static void blendFuncSeparate(GlStateManager.SourceFactor p_69417_, GlStateManager.DestFactor p_69418_, GlStateManager.SourceFactor p_69419_, GlStateManager.DestFactor p_69420_) { - PipelineState.blendInfo.setBlendFuncSeparate(p_69417_, p_69418_, p_69419_, p_69420_); - } - public static void blendFuncSeparate(int srcFactorRGB, int dstFactorRGB, int srcFactorAlpha, int dstFactorAlpha) { PipelineState.blendInfo.setBlendFuncSeparate(srcFactorRGB, dstFactorRGB, srcFactorAlpha, dstFactorAlpha); } + public static void blendOp(int op) { + PipelineState.blendInfo.setBlendOp(op); + } + public static void enableColorLogicOp() { logicOp = true; } @@ -253,21 +266,31 @@ public static void disableColorLogicOp() { logicOp = false; } - public static void logicOp(GlStateManager.LogicOp logicOp) { - logicOpFun = logicOp.value; + public static void logicOp(int glLogicOp) { + logicOpFun = glLogicOp; } - public static void polygonOffset(float v, float v1) { - depthBias[0] = v; - depthBias[1] = v1; + public static void polygonOffset(float slope, float biasConstant) { + if (depthBiasConstant != biasConstant || depthBiasSlope != slope) { + depthBiasConstant = biasConstant; + depthBiasSlope = slope; + + Renderer.setDepthBias(depthBiasConstant, depthBiasSlope); + } } public static void enablePolygonOffset() { - Renderer.setDepthBias(depthBias[0], depthBias[1]); + if (!depthBiasEnabled) { + Renderer.setDepthBias(depthBiasConstant, depthBiasSlope); + depthBiasEnabled = true; + } } public static void disablePolygonOffset() { - Renderer.setDepthBias(0.0F, 0.0F); + if (depthBiasEnabled) { + Renderer.setDepthBias(0.0F, 0.0F); + depthBiasEnabled = false; + } } } diff --git a/src/main/java/net/vulkanmod/vulkan/Vulkan.java b/src/main/java/net/vulkanmod/vulkan/Vulkan.java index 33c75fcea..31152a2a8 100644 --- a/src/main/java/net/vulkanmod/vulkan/Vulkan.java +++ b/src/main/java/net/vulkanmod/vulkan/Vulkan.java @@ -3,13 +3,13 @@ import net.vulkanmod.vulkan.device.Device; import net.vulkanmod.vulkan.device.DeviceManager; import net.vulkanmod.vulkan.framebuffer.SwapChain; -import net.vulkanmod.vulkan.memory.Buffer; +import net.vulkanmod.vulkan.memory.buffer.Buffer; import net.vulkanmod.vulkan.memory.MemoryManager; import net.vulkanmod.vulkan.memory.MemoryTypes; -import net.vulkanmod.vulkan.memory.StagingBuffer; +import net.vulkanmod.vulkan.memory.buffer.StagingBuffer; import net.vulkanmod.vulkan.queue.Queue; import net.vulkanmod.vulkan.shader.Pipeline; -import net.vulkanmod.vulkan.util.VUtil; +import net.vulkanmod.vulkan.texture.SamplerManager; import net.vulkanmod.vulkan.util.VkResult; import org.lwjgl.PointerBuffer; import org.lwjgl.system.MemoryStack; @@ -26,8 +26,7 @@ import static net.vulkanmod.vulkan.util.VUtil.asPointerBuffer; import static org.lwjgl.glfw.GLFWVulkan.glfwCreateWindowSurface; import static org.lwjgl.glfw.GLFWVulkan.glfwGetRequiredInstanceExtensions; -import static org.lwjgl.system.MemoryStack.stackGet; -import static org.lwjgl.system.MemoryStack.stackPush; +import static org.lwjgl.system.MemoryStack.*; import static org.lwjgl.system.MemoryUtil.NULL; import static org.lwjgl.util.vma.Vma.vmaCreateAllocator; import static org.lwjgl.util.vma.Vma.vmaDestroyAllocator; @@ -35,14 +34,13 @@ import static org.lwjgl.vulkan.KHRDynamicRendering.VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME; import static org.lwjgl.vulkan.KHRSwapchain.VK_KHR_SWAPCHAIN_EXTENSION_NAME; import static org.lwjgl.vulkan.VK10.*; -import static org.lwjgl.vulkan.VK12.VK_API_VERSION_1_2; +import static org.lwjgl.vulkan.VK11.VK_API_VERSION_1_1; public class Vulkan { public static final boolean ENABLE_VALIDATION_LAYERS = false; // public static final boolean ENABLE_VALIDATION_LAYERS = true; - // public static final boolean DYNAMIC_RENDERING = true; public static final boolean DYNAMIC_RENDERING = false; public static final Set VALIDATION_LAYERS; @@ -125,8 +123,6 @@ public static long getAllocator() { private static long debugMessenger; private static long surface; - private static SwapChain swapChain; - private static long commandPool; private static VkCommandBuffer immediateCmdBuffer; private static long immediateFence; @@ -149,12 +145,8 @@ public static void initVulkan(long window) { MemoryTypes.createMemoryTypes(); createCommandPool(); - allocateImmediateCmdBuffer(); setupDepthFormat(); - createSwapChain(); - Renderer.initRenderer(); - } static void createStagingBuffers() { @@ -165,7 +157,7 @@ static void createStagingBuffers() { stagingBuffers = new StagingBuffer[Renderer.getFramesNum()]; for (int i = 0; i < stagingBuffers.length; ++i) { - stagingBuffers[i] = new StagingBuffer(30 * 1024 * 1024); + stagingBuffers[i] = new StagingBuffer(); } } @@ -173,10 +165,6 @@ static void setupDepthFormat() { DEFAULT_DEPTH_FORMAT = DeviceManager.findDepthFormat(use24BitsDepthFormat); } - private static void createSwapChain() { - swapChain = new SwapChain(); - } - public static void waitIdle() { vkDeviceWaitIdle(DeviceManager.vkDevice); } @@ -189,7 +177,6 @@ public static void cleanUp() { Pipeline.destroyPipelineCache(); Renderer.getInstance().cleanUpResources(); - swapChain.cleanUp(); freeStagingBuffers(); @@ -201,6 +188,7 @@ public static void cleanUp() { vmaDestroyAllocator(allocator); + SamplerManager.cleanUp(); DeviceManager.destroy(); destroyDebugUtilsMessengerEXT(instance, debugMessenger, null); KHRSurface.vkDestroySurfaceKHR(instance, surface, null); @@ -208,7 +196,7 @@ public static void cleanUp() { } private static void freeStagingBuffers() { - Arrays.stream(stagingBuffers).forEach(Buffer::freeBuffer); + Arrays.stream(stagingBuffers).forEach(Buffer::scheduleFree); } private static void createInstance() { @@ -228,7 +216,7 @@ private static void createInstance() { appInfo.applicationVersion(VK_MAKE_VERSION(1, 0, 0)); appInfo.pEngineName(stack.UTF8Safe("VulkanMod Engine")); appInfo.engineVersion(VK_MAKE_VERSION(1, 0, 0)); - appInfo.apiVersion(VK_API_VERSION_1_2); + appInfo.apiVersion(VK_API_VERSION_1_1); VkInstanceCreateInfo createInfo = VkInstanceCreateInfo.calloc(stack); @@ -305,6 +293,17 @@ private static void setupDebugMessenger() { } } + public static void setDebugLabel(MemoryStack stack, int objectType, long handle, String label) { + if (ENABLE_VALIDATION_LAYERS) { + VkDebugUtilsObjectNameInfoEXT nameInfo = VkDebugUtilsObjectNameInfoEXT.calloc(stack); + nameInfo.sType$Default(); + nameInfo.objectType(objectType); + nameInfo.objectHandle(handle); + nameInfo.pObjectName(stackUTF8(label)); + EXTDebugUtils.vkSetDebugUtilsObjectNameEXT(Vulkan.getVkDevice(), nameInfo); + } + } + private static void createSurface(long handle) { window = handle; @@ -330,7 +329,7 @@ private static void createVma() { allocatorCreateInfo.device(DeviceManager.vkDevice); allocatorCreateInfo.pVulkanFunctions(vulkanFunctions); allocatorCreateInfo.instance(instance); - allocatorCreateInfo.vulkanApiVersion(VK_API_VERSION_1_2); + allocatorCreateInfo.vulkanApiVersion(VK_API_VERSION_1_1); PointerBuffer pAllocator = stack.pointers(VK_NULL_HANDLE); @@ -361,58 +360,6 @@ private static void createCommandPool() { } } - private static void allocateImmediateCmdBuffer() { - try (MemoryStack stack = stackPush()) { - - VkCommandBufferAllocateInfo allocInfo = VkCommandBufferAllocateInfo.calloc(stack); - allocInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO); - allocInfo.level(VK_COMMAND_BUFFER_LEVEL_PRIMARY); - allocInfo.commandPool(commandPool); - allocInfo.commandBufferCount(1); - - PointerBuffer pCommandBuffer = stack.mallocPointer(1); - vkAllocateCommandBuffers(DeviceManager.vkDevice, allocInfo, pCommandBuffer); - immediateCmdBuffer = new VkCommandBuffer(pCommandBuffer.get(0), DeviceManager.vkDevice); - - VkFenceCreateInfo fenceInfo = VkFenceCreateInfo.calloc(stack); - fenceInfo.sType(VK_STRUCTURE_TYPE_FENCE_CREATE_INFO); - fenceInfo.flags(VK_FENCE_CREATE_SIGNALED_BIT); - - LongBuffer pFence = stack.mallocLong(1); - vkCreateFence(DeviceManager.vkDevice, fenceInfo, null, pFence); - vkResetFences(DeviceManager.vkDevice, pFence.get(0)); - - immediateFence = pFence.get(0); - } - } - - public static VkCommandBuffer beginImmediateCmd() { - try (MemoryStack stack = stackPush()) { - VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.calloc(stack); - beginInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO); - - vkBeginCommandBuffer(immediateCmdBuffer, beginInfo); - } - return immediateCmdBuffer; - } - - public static void endImmediateCmd() { - try (MemoryStack stack = stackPush()) { - vkEndCommandBuffer(immediateCmdBuffer); - - VkSubmitInfo submitInfo = VkSubmitInfo.calloc(stack); - submitInfo.sType(VK_STRUCTURE_TYPE_SUBMIT_INFO); - submitInfo.pCommandBuffers(stack.pointers(immediateCmdBuffer)); - - vkQueueSubmit(DeviceManager.getGraphicsQueue().queue(), submitInfo, immediateFence); - - vkWaitForFences(DeviceManager.vkDevice, immediateFence, true, VUtil.UINT64_MAX); - vkResetFences(DeviceManager.vkDevice, immediateFence); - vkResetCommandBuffer(immediateCmdBuffer, 0); - } - - } - private static PointerBuffer getRequiredInstanceExtensions() { PointerBuffer glfwExtensions = glfwGetRequiredInstanceExtensions(); @@ -440,6 +387,7 @@ public static void checkResult(int result, String errorMessage) { } public static void setVsync(boolean b) { + SwapChain swapChain = Renderer.getInstance().getSwapChain(); if (swapChain.isVsync() != b) { Renderer.scheduleSwapChainUpdate(); swapChain.setVsync(b); @@ -454,10 +402,6 @@ public static long getSurface() { return surface; } - public static SwapChain getSwapChain() { - return swapChain; - } - public static long getCommandPool() { return commandPool; } diff --git a/src/main/java/net/vulkanmod/vulkan/device/Device.java b/src/main/java/net/vulkanmod/vulkan/device/Device.java index da850d3b9..a8ab2b70c 100644 --- a/src/main/java/net/vulkanmod/vulkan/device/Device.java +++ b/src/main/java/net/vulkanmod/vulkan/device/Device.java @@ -72,8 +72,15 @@ public Device(VkPhysicalDevice device) { private static String decodeVendor(int i) { return switch (i) { case (0x10DE) -> "Nvidia"; - case (0x1022) -> "AMD"; + case (0x1022), (0x1002) -> "AMD"; // AMD has two deviceIds, apparently case (0x8086) -> "Intel"; + case (0x1010) -> "Imagination Technologies"; + case (0x13B5) -> "ARM"; + case (0x5143) -> "Qualcomm"; + case (0x106B) -> "Apple"; + case (0x14E4) -> "Broadcom"; + case (0x1AE0) -> "Google"; // Not sure about this, SwiftShader devices have this id + case (0x10005) -> "Mesa"; // Honeykrisp on Apple devices has this vendorId for some reason default -> "undef"; //Either AMD or Unknown Driver version/vendor and.or Encoding Scheme }; } @@ -90,7 +97,7 @@ static String decDefVersion(int v) { private static String decodeDvrVersion(int v, int i) { return switch (i) { case (0x10DE) -> decodeNvidia(v); //Nvidia - case (0x1022) -> decDefVersion(v); //AMD + case (0x1022), (0x1002) -> decDefVersion(v); //AMD case (0x8086) -> decIntelVersion(v); //Intel default -> decDefVersion(v); //Either AMD or Unknown Driver Encoding Scheme }; @@ -113,9 +120,9 @@ static int getVkVer() { var a = stack.mallocInt(1); vkEnumerateInstanceVersion(a); int vkVer1 = a.get(0); - if (VK_VERSION_MINOR(vkVer1) < 2) { + /* if (VK_VERSION_MINOR(vkVer1) < 2) { throw new RuntimeException("Vulkan 1.2 not supported: Only Has: %s".formatted(decDefVersion(vkVer1))); - } + }*/ return vkVer1; } } @@ -149,7 +156,7 @@ public boolean isDrawIndirectSupported() { // Added these to allow detecting GPU vendor, to allow handling vendor specific circumstances: // (e.g. such as in case we encounter a vendor specific driver bug) public boolean isAMD() { - return vendorId == 0x1022; + return vendorId == 0x1022 || vendorId == 0x1002; } public boolean isNvidia() { diff --git a/src/main/java/net/vulkanmod/vulkan/framebuffer/Framebuffer.java b/src/main/java/net/vulkanmod/vulkan/framebuffer/Framebuffer.java index b5eb00b10..d34fb50ac 100644 --- a/src/main/java/net/vulkanmod/vulkan/framebuffer/Framebuffer.java +++ b/src/main/java/net/vulkanmod/vulkan/framebuffer/Framebuffer.java @@ -1,6 +1,5 @@ package net.vulkanmod.vulkan.framebuffer; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.Reference2LongArrayMap; import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.Vulkan; @@ -19,8 +18,7 @@ public class Framebuffer { public static final int DEFAULT_FORMAT = VK_FORMAT_R8G8B8A8_UNORM; -// private long id; - + public final String name; protected int format; protected int depthFormat; protected int width, height; @@ -34,14 +32,17 @@ public class Framebuffer { private VulkanImage colorAttachment; protected VulkanImage depthAttachment; - private final ObjectArrayList renderPasses = new ObjectArrayList<>(); + private int level; - private final Reference2LongArrayMap framebufferIds = new Reference2LongArrayMap<>(); + private final Reference2LongArrayMap renderpassToFramebufferMap = new Reference2LongArrayMap<>(); - //SwapChain - protected Framebuffer() {} + // SwapChain + protected Framebuffer() { + this.name = null; + } public Framebuffer(Builder builder) { + this.name = builder.name; this.format = builder.format; this.depthFormat = builder.depthFormat; this.width = builder.width; @@ -57,26 +58,30 @@ public Framebuffer(Builder builder) { this.colorAttachment = builder.colorAttachment; this.depthAttachment = builder.depthAttachment; } - } - public void addRenderPass(RenderPass renderPass) { - this.renderPasses.add(renderPass); + this.level = builder.level; } public void createImages() { if (this.hasColorAttachment) { - this.colorAttachment = VulkanImage.builder(this.width, this.height) - .setFormat(format) - .setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT) - .setLinearFiltering(linearFiltering) - .setClamp(true) - .createVulkanImage(); + this.colorAttachment = + VulkanImage.builder(this.width, this.height) + .setName(this.name != null ? String.format("%s Color", this.name) : null) + .setFormat(format) + .setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT) + .setLinearFiltering(linearFiltering) + .setClamp(true) + .createVulkanImage(); } if (this.hasDepthAttachment) { - this.depthAttachment = VulkanImage.createDepthImage(depthFormat, this.width, this.height, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, - depthLinearFiltering, true); + this.depthAttachment = VulkanImage.builder(width, height) + .setName(this.name != null ? String.format("%s Depth", this.name) : null) + .setFormat(depthFormat) + .setUsage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT) + .setLinearFiltering(depthLinearFiltering) + .setClamp(true) + .createVulkanImage(); this.attachmentCount++; } @@ -92,7 +97,6 @@ public void resize(int newWidth, int newHeight) { } private long createFramebuffer(RenderPass renderPass) { - try (MemoryStack stack = MemoryStack.stackPush()) { LongBuffer attachments; @@ -123,22 +127,19 @@ private long createFramebuffer(RenderPass renderPass) { } public void beginRenderPass(VkCommandBuffer commandBuffer, RenderPass renderPass, MemoryStack stack) { + renderPass.setFramebuffer(this); + if (!DYNAMIC_RENDERING) { long framebufferId = this.getFramebufferId(renderPass); renderPass.beginRenderPass(commandBuffer, framebufferId, stack); - } else { + } + else { renderPass.beginDynamicRendering(commandBuffer, stack); } - - Renderer.getInstance().setBoundRenderPass(renderPass); - Renderer.getInstance().setBoundFramebuffer(this); - - Renderer.setViewport(0, 0, this.width, this.height); - Renderer.setScissor(0, 0, this.width, this.height); } protected long getFramebufferId(RenderPass renderPass) { - return this.framebufferIds.computeIfAbsent(renderPass, renderPass1 -> createFramebuffer(renderPass)); + return this.renderpassToFramebufferMap.computeIfAbsent(renderPass, renderPass1 -> createFramebuffer(renderPass)); } public VkViewport.Buffer viewport(MemoryStack stack) { @@ -175,7 +176,7 @@ public void cleanUp(boolean cleanImages) { } final VkDevice device = Vulkan.getVkDevice(); - final var ids = framebufferIds.values().toLongArray(); + final var ids = renderpassToFramebufferMap.values().toLongArray(); MemoryManager.getInstance().addFrameOp( () -> Arrays.stream(ids).forEach(id -> @@ -183,7 +184,18 @@ public void cleanUp(boolean cleanImages) { ); - framebufferIds.clear(); + renderpassToFramebufferMap.clear(); + } + + public void setLevel(int level) { + int maxLevel = this.colorAttachment.mipLevels - 1; + if (level > maxLevel) { + throw new IllegalStateException( + "Requested mip level (%d) greater than color attachments max mip level (%d)" + .formatted(level, maxLevel)); + } + + this.level = level; } public long getDepthImageView() { @@ -198,6 +210,10 @@ public VulkanImage getColorAttachment() { return colorAttachment; } + public long getColorAttachmentView() { + return colorAttachment.getLevelImageView(level); + } + public int getWidth() { return this.width; } @@ -223,6 +239,7 @@ public static Builder builder(VulkanImage colorAttachment, VulkanImage depthAtta } public static class Builder { + final String name; final boolean createImages; final int width, height; int format, depthFormat; @@ -230,19 +247,25 @@ public static class Builder { VulkanImage colorAttachment; VulkanImage depthAttachment; -// int colorAttachments; boolean hasColorAttachment; boolean hasDepthAttachment; boolean linearFiltering; boolean depthLinearFiltering; + int level = 0; + public Builder(int width, int height, int colorAttachments, boolean hasDepthAttachment) { + this(null, width, height, colorAttachments, hasDepthAttachment); + } + + public Builder(String name, int width, int height, int colorAttachments, boolean hasDepthAttachment) { Validate.isTrue(colorAttachments > 0 || hasDepthAttachment, "At least 1 attachment needed"); //TODO multi color attachments Validate.isTrue(colorAttachments <= 1, "Not supported"); + this.name = name; this.createImages = true; this.format = DEFAULT_FORMAT; this.depthFormat = Vulkan.getDefaultDepthFormat(); @@ -256,6 +279,7 @@ public Builder(int width, int height, int colorAttachments, boolean hasDepthAtta } public Builder(VulkanImage colorAttachment, VulkanImage depthAttachment) { + this.name = null; this.createImages = false; this.colorAttachment = colorAttachment; this.depthAttachment = depthAttachment; @@ -276,6 +300,12 @@ public Framebuffer build() { return new Framebuffer(this); } + public Builder setLevel(int level) { + this.level = level; + + return this; + } + public Builder setFormat(int format) { this.format = format; diff --git a/src/main/java/net/vulkanmod/vulkan/framebuffer/RenderPass.java b/src/main/java/net/vulkanmod/vulkan/framebuffer/RenderPass.java index 24cc8c031..62e237c56 100644 --- a/src/main/java/net/vulkanmod/vulkan/framebuffer/RenderPass.java +++ b/src/main/java/net/vulkanmod/vulkan/framebuffer/RenderPass.java @@ -34,8 +34,6 @@ public RenderPass(Framebuffer framebuffer, AttachmentInfo colorAttachmentInfo, A this.attachmentCount = count; if (!Vulkan.DYNAMIC_RENDERING) { - framebuffer.addRenderPass(this); - createRenderPass(); } @@ -56,17 +54,17 @@ private void createRenderPass() { if (colorAttachmentInfo != null) { VkAttachmentDescription colorAttachment = attachments.get(i); colorAttachment.format(colorAttachmentInfo.format) - .samples(VK_SAMPLE_COUNT_1_BIT) - .loadOp(colorAttachmentInfo.loadOp) - .storeOp(colorAttachmentInfo.storeOp) - .stencilLoadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE) - .stencilStoreOp(VK_ATTACHMENT_STORE_OP_DONT_CARE) - .initialLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) - .finalLayout(colorAttachmentInfo.finalLayout); + .samples(VK_SAMPLE_COUNT_1_BIT) + .loadOp(colorAttachmentInfo.loadOp) + .storeOp(colorAttachmentInfo.storeOp) + .stencilLoadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE) + .stencilStoreOp(VK_ATTACHMENT_STORE_OP_DONT_CARE) + .initialLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + .finalLayout(colorAttachmentInfo.finalLayout); VkAttachmentReference colorAttachmentRef = attachmentRefs.get(0) - .attachment(0) - .layout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + .attachment(0) + .layout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); subpass.colorAttachmentCount(1); subpass.pColorAttachments(VkAttachmentReference.calloc(1, stack).put(0, colorAttachmentRef)); @@ -78,49 +76,49 @@ private void createRenderPass() { if (depthAttachmentInfo != null) { VkAttachmentDescription depthAttachment = attachments.get(i); depthAttachment.format(depthAttachmentInfo.format) - .samples(VK_SAMPLE_COUNT_1_BIT) - .loadOp(depthAttachmentInfo.loadOp) - .storeOp(depthAttachmentInfo.storeOp) - .stencilLoadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE) - .stencilStoreOp(VK_ATTACHMENT_STORE_OP_DONT_CARE) - .initialLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) - .finalLayout(depthAttachmentInfo.finalLayout); + .samples(VK_SAMPLE_COUNT_1_BIT) + .loadOp(depthAttachmentInfo.loadOp) + .storeOp(depthAttachmentInfo.storeOp) + .stencilLoadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE) + .stencilStoreOp(VK_ATTACHMENT_STORE_OP_DONT_CARE) + .initialLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) + .finalLayout(depthAttachmentInfo.finalLayout); VkAttachmentReference depthAttachmentRef = attachmentRefs.get(1) - .attachment(1) - .layout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + .attachment(1) + .layout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); subpass.pDepthStencilAttachment(depthAttachmentRef); } VkRenderPassCreateInfo renderPassInfo = VkRenderPassCreateInfo.calloc(stack); renderPassInfo.sType$Default() - .pAttachments(attachments) - .pSubpasses(subpass); + .pAttachments(attachments) + .pSubpasses(subpass); //Layout transition subpass depency switch (colorAttachmentInfo.finalLayout) { case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR -> { VkSubpassDependency.Buffer subpassDependencies = VkSubpassDependency.calloc(1, stack); subpassDependencies.get(0) - .srcSubpass(VK_SUBPASS_EXTERNAL) - .dstSubpass(0) - .srcStageMask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT) - .dstStageMask(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT) - .srcAccessMask(0) - .dstAccessMask(0); + .srcSubpass(VK_SUBPASS_EXTERNAL) + .dstSubpass(0) + .srcStageMask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT) + .dstStageMask(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT) + .srcAccessMask(0) + .dstAccessMask(0); renderPassInfo.pDependencies(subpassDependencies); } case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL -> { VkSubpassDependency.Buffer subpassDependencies = VkSubpassDependency.calloc(1, stack); subpassDependencies.get(0) - .srcSubpass(0) - .dstSubpass(VK_SUBPASS_EXTERNAL) - .srcStageMask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT) - .dstStageMask(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT) - .srcAccessMask(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT) - .dstAccessMask(VK_ACCESS_SHADER_READ_BIT); + .srcSubpass(0) + .dstSubpass(VK_SUBPASS_EXTERNAL) + .srcStageMask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT) + .dstStageMask(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT) + .srcAccessMask(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT) + .dstAccessMask(VK_ACCESS_SHADER_READ_BIT); renderPassInfo.pDependencies(subpassDependencies); } @@ -139,11 +137,17 @@ private void createRenderPass() { public void beginRenderPass(VkCommandBuffer commandBuffer, long framebufferId, MemoryStack stack) { if (colorAttachmentInfo != null - && framebuffer.getColorAttachment().getCurrentLayout() != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) - framebuffer.getColorAttachment().transitionImageLayout(stack, commandBuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + && framebuffer.getColorAttachment().getCurrentLayout() != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + { + framebuffer.getColorAttachment() + .transitionImageLayout(stack, commandBuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + } if (depthAttachmentInfo != null - && framebuffer.getDepthAttachment().getCurrentLayout() != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) - framebuffer.getDepthAttachment().transitionImageLayout(stack, commandBuffer, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + && framebuffer.getDepthAttachment().getCurrentLayout() != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) + { + framebuffer.getDepthAttachment() + .transitionImageLayout(stack, commandBuffer, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + } VkRenderPassBeginInfo renderPassInfo = VkRenderPassBeginInfo.calloc(stack); renderPassInfo.sType$Default(); @@ -167,24 +171,58 @@ public void beginRenderPass(VkCommandBuffer commandBuffer, long framebufferId, M } public void endRenderPass(VkCommandBuffer commandBuffer) { - vkCmdEndRenderPass(commandBuffer); + if (Vulkan.DYNAMIC_RENDERING) { + KHRDynamicRendering.vkCmdEndRenderingKHR(commandBuffer); + + try (MemoryStack stack = MemoryStack.stackPush()) { + if (colorAttachmentInfo != null + && framebuffer.getColorAttachment().getCurrentLayout() != this.colorAttachmentInfo.finalLayout) + { + framebuffer.getColorAttachment() + .transitionImageLayout(stack, commandBuffer, this.colorAttachmentInfo.finalLayout); + } + if (depthAttachmentInfo != null + && framebuffer.getDepthAttachment().getCurrentLayout() != this.depthAttachmentInfo.finalLayout) + { + framebuffer.getDepthAttachment() + .transitionImageLayout(stack, commandBuffer, this.depthAttachmentInfo.finalLayout); + } + } - if (colorAttachmentInfo != null) - framebuffer.getColorAttachment().setCurrentLayout(colorAttachmentInfo.finalLayout); + } + else { + vkCmdEndRenderPass(commandBuffer); - if (depthAttachmentInfo != null) - framebuffer.getDepthAttachment().setCurrentLayout(depthAttachmentInfo.finalLayout); + if (colorAttachmentInfo != null) + framebuffer.getColorAttachment().setCurrentLayout(colorAttachmentInfo.finalLayout); + + if (depthAttachmentInfo != null) + framebuffer.getDepthAttachment().setCurrentLayout(depthAttachmentInfo.finalLayout); + } Renderer.getInstance().setBoundRenderPass(null); } public void beginDynamicRendering(VkCommandBuffer commandBuffer, MemoryStack stack) { + if (colorAttachmentInfo != null + && framebuffer.getColorAttachment().getCurrentLayout() != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + { + framebuffer.getColorAttachment() + .transitionImageLayout(stack, commandBuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + } + if (depthAttachmentInfo != null + && framebuffer.getDepthAttachment().getCurrentLayout() != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) + { + framebuffer.getDepthAttachment() + .transitionImageLayout(stack, commandBuffer, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + } + VkRect2D renderArea = VkRect2D.malloc(stack); renderArea.offset().set(0, 0); renderArea.extent().set(framebuffer.getWidth(), framebuffer.getHeight()); VkClearValue.Buffer clearValues = VkClearValue.malloc(2, stack); - clearValues.get(0).color().float32(stack.floats(0.0f, 0.0f, 0.0f, 1.0f)); + clearValues.get(0).color().float32(VRenderSystem.clearColor); clearValues.get(1).depthStencil().set(1.0f, 0); VkRenderingInfo renderingInfo = VkRenderingInfo.calloc(stack); @@ -205,7 +243,7 @@ public void beginDynamicRendering(VkCommandBuffer commandBuffer, MemoryStack sta renderingInfo.pColorAttachments(colorAttachment); } - //Depth attachment + // Depth attachment if (depthAttachmentInfo != null) { VkRenderingAttachmentInfo depthAttachment = VkRenderingAttachmentInfo.calloc(stack); depthAttachment.sType(KHRDynamicRendering.VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR); @@ -221,21 +259,20 @@ public void beginDynamicRendering(VkCommandBuffer commandBuffer, MemoryStack sta KHRDynamicRendering.vkCmdBeginRenderingKHR(commandBuffer, renderingInfo); } - public void endDynamicRendering(VkCommandBuffer commandBuffer) { - KHRDynamicRendering.vkCmdEndRenderingKHR(commandBuffer); - } - public Framebuffer getFramebuffer() { return framebuffer; } - public void cleanUp() { - //TODO - - if (!Vulkan.DYNAMIC_RENDERING) - MemoryManager.getInstance().addFrameOp( - () -> vkDestroyRenderPass(Vulkan.getVkDevice(), this.id, null)); + public void setFramebuffer(Framebuffer framebuffer) { + this.framebuffer = framebuffer; + } + public void cleanUp() { + if (!Vulkan.DYNAMIC_RENDERING) { + MemoryManager.getInstance() + .addFrameOp( + () -> vkDestroyRenderPass(Vulkan.getVkDevice(), this.id, null)); + } } public long getId() { diff --git a/src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java b/src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java index 44b8bf7e5..9fe29eec7 100644 --- a/src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java +++ b/src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java @@ -2,12 +2,12 @@ import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; import net.vulkanmod.Initializer; -import net.vulkanmod.gl.GlTexture; import net.vulkanmod.render.util.MathUtil; import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.Vulkan; import net.vulkanmod.vulkan.device.DeviceManager; import net.vulkanmod.vulkan.queue.Queue; +import net.vulkanmod.vulkan.texture.SamplerManager; import net.vulkanmod.vulkan.texture.VulkanImage; import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.*; @@ -29,8 +29,6 @@ import static org.lwjgl.vulkan.VK10.*; public class SwapChain extends Framebuffer { - private static final int DEFAULT_IMAGE_COUNT = 3; - // Necessary until tearing-control-unstable-v1 is fully implemented on all GPU Drivers for Wayland // (As Immediate Mode (and by extension Screen tearing) doesn't exist on some Wayland installations currently) private static final int defUncappedMode = checkPresentMode(VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_MAILBOX_KHR); @@ -43,8 +41,6 @@ public class SwapChain extends Framebuffer { public boolean isBGRAformat; private boolean vsync = false; - private int[] glIds; - public SwapChain() { this.attachmentCount = 2; this.depthFormat = Vulkan.getDefaultDepthFormat(); @@ -90,9 +86,10 @@ private void createSwapChain() { return; } - // minImageCount depends on driver: Mesa/RADV needs a min of 4, but most other drivers are at least 2 or 3 - // TODO using FIFO present mode with image num > 2 introduces (unnecessary) input lag - int requestedImages = Math.max(DEFAULT_IMAGE_COUNT, surfaceProperties.capabilities.minImageCount()); + int requestedImages = surfaceProperties.capabilities.minImageCount() + 1; + if (surfaceProperties.capabilities.maxImageCount() > 0 && requestedImages > surfaceProperties.capabilities.maxImageCount()) { + requestedImages = surfaceProperties.capabilities.maxImageCount(); + } IntBuffer imageCount = stack.ints(requestedImages); @@ -126,18 +123,16 @@ private void createSwapChain() { createInfo.presentMode(presentMode); createInfo.clipped(true); - createInfo.oldSwapchain(this.swapChainId); + if (this.swapChainId != VK_NULL_HANDLE) { + this.swapChainImages.forEach(image -> vkDestroyImageView(device, image.getImageView(), null)); + vkDestroySwapchainKHR(device, this.swapChainId, null); + } LongBuffer pSwapChain = stack.longs(VK_NULL_HANDLE); int result = vkCreateSwapchainKHR(device, createInfo, null, pSwapChain); Vulkan.checkResult(result, "Failed to create swap chain"); - if (this.swapChainId != VK_NULL_HANDLE) { - this.swapChainImages.forEach(image -> vkDestroyImageView(device, image.getImageView(), null)); - vkDestroySwapchainKHR(device, this.swapChainId, null); - } - this.swapChainId = pSwapChain.get(0); vkGetSwapchainImagesKHR(device, this.swapChainId, imageCount, null); @@ -153,32 +148,18 @@ private void createSwapChain() { for (int i = 0; i < pSwapchainImages.capacity(); i++) { long imageId = pSwapchainImages.get(i); - long imageView = VulkanImage.createImageView(imageId, this.format, VK_IMAGE_ASPECT_COLOR_BIT, 1); + long imageView = VulkanImage.createImageView(imageId, this.format, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1); - VulkanImage image = new VulkanImage(imageId, this.format, 1, this.width, this.height, 4, 0, imageView); - image.updateTextureSampler(true, true, false); + VulkanImage image = new VulkanImage("Swapchain", imageId, this.format, 1, this.width, this.height, 4, 0, imageView); + long samplerId = SamplerManager.getSampler(true, true, 0); + image.setSampler(samplerId); this.swapChainImages.add(image); } } - createGlIds(); createDepthResources(); } - private void createGlIds() { - this.glIds = new int[this.swapChainImages.size()]; - - for (int i = 0; i < this.swapChainImages.size(); i++) { - int id = GlTexture.genTextureId(); - this.glIds[i] = id; - GlTexture.bindIdToImage(id, this.swapChainImages.get(i)); - } - } - - public int getColorAttachmentGlId() { - return this.glIds[Renderer.getCurrentImage()]; - } - private long[] createFramebuffers(RenderPass renderPass) { try (MemoryStack stack = MemoryStack.stackPush()) { @@ -291,7 +272,7 @@ private int getPresentMode(IntBuffer availablePresentModes) { } } - Initializer.LOGGER.warn("Requested mode not supported: " + getDisplayModeString(requestedMode) + ": using VSync"); + Initializer.LOGGER.warn("Requested mode not supported: " + getDisplayModeString(requestedMode) + ": using FIFO present mode"); return VK_PRESENT_MODE_FIFO_KHR; } @@ -310,7 +291,7 @@ private static VkExtent2D getExtent(VkSurfaceCapabilitiesKHR capabilities) { return capabilities.currentExtent(); } - //Fallback + // Fallback IntBuffer width = stackGet().ints(0); IntBuffer height = stackGet().ints(0); @@ -337,7 +318,7 @@ private static int checkPresentMode(int... requestedModes) { } } } - return VK_PRESENT_MODE_FIFO_KHR; //If None of the request modes exist/are supported by Driver + return VK_PRESENT_MODE_FIFO_KHR; // If None of the request modes exist/are supported by Driver } } diff --git a/src/main/java/net/vulkanmod/vulkan/memory/Buffer.java b/src/main/java/net/vulkanmod/vulkan/memory/Buffer.java deleted file mode 100644 index b0a558f41..000000000 --- a/src/main/java/net/vulkanmod/vulkan/memory/Buffer.java +++ /dev/null @@ -1,59 +0,0 @@ -package net.vulkanmod.vulkan.memory; - -import org.lwjgl.PointerBuffer; - -public abstract class Buffer { - protected long id; - protected long allocation; - - protected int bufferSize; - protected int usedBytes; - protected int offset; - - protected MemoryType type; - protected int usage; - protected PointerBuffer data; - - protected Buffer(int usage, MemoryType type) { - //TODO: check usage - this.usage = usage; - this.type = type; - - } - - protected void createBuffer(int bufferSize) { - this.type.createBuffer(this, bufferSize); - - if(this.type.mappable()) { - this.data = MemoryManager.getInstance().Map(this.allocation); - } - } - - public void freeBuffer() { - MemoryManager.getInstance().addToFreeable(this); - } - - public void reset() { usedBytes = 0; } - - public long getAllocation() { return allocation; } - - public long getUsedBytes() { return usedBytes; } - - public long getOffset() { return offset; } - - public long getId() { return id; } - - public int getBufferSize() { return bufferSize; } - - protected void setBufferSize(int size) { this.bufferSize = size; } - - protected void setId(long id) { this.id = id; } - - protected void setAllocation(long allocation) {this.allocation = allocation; } - - public BufferInfo getBufferInfo() { return new BufferInfo(this.id, this.allocation, this.bufferSize, this.type.getType()); } - - public record BufferInfo(long id, long allocation, long bufferSize, MemoryType.Type type) { - - } -} diff --git a/src/main/java/net/vulkanmod/vulkan/memory/IndexBuffer.java b/src/main/java/net/vulkanmod/vulkan/memory/IndexBuffer.java deleted file mode 100644 index 311f71720..000000000 --- a/src/main/java/net/vulkanmod/vulkan/memory/IndexBuffer.java +++ /dev/null @@ -1,49 +0,0 @@ -package net.vulkanmod.vulkan.memory; - -import java.nio.ByteBuffer; - -import static org.lwjgl.vulkan.VK10.*; - -public class IndexBuffer extends Buffer { - - public IndexType indexType; - - public IndexBuffer(int size, MemoryType type) { - this(size, type, IndexType.SHORT); - } - - public IndexBuffer(int size, MemoryType type, IndexType indexType) { - super(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, type); - this.indexType = indexType; - - this.createBuffer(size); - } - - public void copyBuffer(ByteBuffer buffer) { - int size = buffer.remaining(); - - if(size > this.bufferSize - this.usedBytes) { - throw new RuntimeException("Trying to write buffer beyond max size."); - } - else { - this.type.copyToBuffer(this, size, buffer); - offset = usedBytes; - usedBytes += size; - } - } - - public enum IndexType { - SHORT(2, VK_INDEX_TYPE_UINT16), - INT(4, VK_INDEX_TYPE_UINT32); - - public final int size; - public final int type; - - IndexType(int size, int type) { - this.size = size; - this.type = type; - } - } - - -} diff --git a/src/main/java/net/vulkanmod/vulkan/memory/MemoryManager.java b/src/main/java/net/vulkanmod/vulkan/memory/MemoryManager.java index a007bb189..b52be1121 100644 --- a/src/main/java/net/vulkanmod/vulkan/memory/MemoryManager.java +++ b/src/main/java/net/vulkanmod/vulkan/memory/MemoryManager.java @@ -6,6 +6,8 @@ import net.vulkanmod.render.chunk.buffer.AreaBuffer; import net.vulkanmod.vulkan.Vulkan; import net.vulkanmod.vulkan.device.DeviceManager; +import net.vulkanmod.vulkan.memory.buffer.Buffer; +import net.vulkanmod.vulkan.queue.Queue; import net.vulkanmod.vulkan.texture.VulkanImage; import net.vulkanmod.vulkan.util.Pair; import net.vulkanmod.vulkan.util.VkResult; @@ -43,11 +45,11 @@ public class MemoryManager { private int currentFrame = 0; - private ObjectArrayList[] freeableBuffers = new ObjectArrayList[Frames]; - private ObjectArrayList[] freeableImages = new ObjectArrayList[Frames]; + private final ObjectArrayList[] freeableBuffers = new ObjectArrayList[Frames]; + private final ObjectArrayList[] freeableImages = new ObjectArrayList[Frames]; - private ObjectArrayList[] frameOps = new ObjectArrayList[Frames]; - private ObjectArrayList>[] segmentsToFree = new ObjectArrayList[Frames]; + private final ObjectArrayList[] frameOps = new ObjectArrayList[Frames]; + private final ObjectArrayList>[] segmentsToFree = new ObjectArrayList[Frames]; //debug private ObjectArrayList[] stackTraces; @@ -82,6 +84,7 @@ public static void createInstance(int frames) { public synchronized void initFrame(int frame) { this.setCurrentFrame(frame); this.freeBuffers(frame); + this.freeImages(frame); this.doFrameOps(frame); this.freeSegments(frame); } @@ -94,6 +97,7 @@ public void setCurrentFrame(int frame) { public void freeAllBuffers() { for (int frame = 0; frame < Frames; ++frame) { this.freeBuffers(frame); + this.freeImages(frame); this.doFrameOps(frame); } @@ -124,11 +128,8 @@ public void createBuffer(long size, int usage, int properties, LongBuffer pBuffe } } - public synchronized void createBuffer(Buffer buffer, int size, int usage, int properties) { - + public synchronized void createBuffer(Buffer buffer, long size, int usage, int properties) { try (MemoryStack stack = stackPush()) { - buffer.setBufferSize(size); - LongBuffer pBuffer = stack.mallocLong(1); PointerBuffer pAllocation = stack.pointers(VK_NULL_HANDLE); @@ -136,10 +137,12 @@ public synchronized void createBuffer(Buffer buffer, int size, int usage, int pr buffer.setId(pBuffer.get(0)); buffer.setAllocation(pAllocation.get(0)); + buffer.setBufferSize(size); - if ((properties & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) > 0) { + if ((properties & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0) { deviceMemory += size; - } else { + } + else { nativeMemory += size; } @@ -147,11 +150,11 @@ public synchronized void createBuffer(Buffer buffer, int size, int usage, int pr } } - public static synchronized void createImage(int width, int height, int mipLevels, int format, int tiling, int usage, int memProperties, - LongBuffer pTextureImage, PointerBuffer pTextureImageMemory) { - + public void createImage(int width, int height, int arrayLayers, int mipLevels, + int format, int tiling, int usage, int flags, + int memProperties, + LongBuffer pTextureImage, PointerBuffer pTextureImageMemory) { try (MemoryStack stack = stackPush()) { - VkImageCreateInfo imageInfo = VkImageCreateInfo.calloc(stack); imageInfo.sType(VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO); imageInfo.imageType(VK_IMAGE_TYPE_2D); @@ -159,26 +162,34 @@ public static synchronized void createImage(int width, int height, int mipLevels imageInfo.extent().height(height); imageInfo.extent().depth(1); imageInfo.mipLevels(mipLevels); - imageInfo.arrayLayers(1); + imageInfo.arrayLayers(arrayLayers); imageInfo.format(format); imageInfo.tiling(tiling); imageInfo.initialLayout(VK_IMAGE_LAYOUT_UNDEFINED); imageInfo.usage(usage); imageInfo.samples(VK_SAMPLE_COUNT_1_BIT); + imageInfo.flags(flags); // imageInfo.sharingMode(VK_SHARING_MODE_CONCURRENT); - // TODO hardcoded queue family indices - imageInfo.pQueueFamilyIndices(stack.ints(0, 1)); + imageInfo.pQueueFamilyIndices( + stack.ints(Queue.getQueueFamilies().graphicsFamily, Queue.getQueueFamilies().computeFamily)); VmaAllocationCreateInfo allocationInfo = VmaAllocationCreateInfo.calloc(stack); allocationInfo.requiredFlags(memProperties); - vmaCreateImage(ALLOCATOR, imageInfo, allocationInfo, pTextureImage, pTextureImageMemory, null); + int result = vmaCreateImage(ALLOCATOR, imageInfo, allocationInfo, pTextureImage, pTextureImageMemory, null); + if (result != VK_SUCCESS) { + Initializer.LOGGER.info(String.format("Failed to create image with size: %dx%d", width, height)); + + throw new RuntimeException("Failed to create image: %s".formatted(VkResult.decode(result))); + } } } public static void addImage(VulkanImage image) { images.putIfAbsent(image.getId(), image); + + deviceMemory += image.size; } public static void MapAndCopy(long allocation, Consumer consumer) { @@ -210,17 +221,19 @@ private static void freeBuffer(Buffer.BufferInfo bufferInfo) { if (bufferInfo.type() == MemoryType.Type.DEVICE_LOCAL) { deviceMemory -= bufferInfo.bufferSize(); - } else { + } + else { nativeMemory -= bufferInfo.bufferSize(); } buffers.remove(bufferInfo.id()); } - public static void freeImage(long image, long allocation) { - vmaDestroyImage(ALLOCATOR, image, allocation); + public static void freeImage(long imageId, long allocation) { + vmaDestroyImage(ALLOCATOR, imageId, allocation); - images.remove(image); + VulkanImage image = images.remove(imageId); + deviceMemory -= image.size; } public synchronized void addToFreeable(Buffer buffer) { @@ -261,12 +274,10 @@ private void freeBuffers(int frame) { if (DEBUG) stackTraces[frame].clear(); - - this.freeImages(); } - private void freeImages() { - List bufferList = freeableImages[currentFrame]; + private void freeImages(int frame) { + List bufferList = freeableImages[frame]; for (VulkanImage image : bufferList) { image.doFree(); diff --git a/src/main/java/net/vulkanmod/vulkan/memory/MemoryType.java b/src/main/java/net/vulkanmod/vulkan/memory/MemoryType.java index 91380c0d6..15bf8d6df 100644 --- a/src/main/java/net/vulkanmod/vulkan/memory/MemoryType.java +++ b/src/main/java/net/vulkanmod/vulkan/memory/MemoryType.java @@ -1,5 +1,6 @@ package net.vulkanmod.vulkan.memory; +import net.vulkanmod.vulkan.memory.buffer.Buffer; import org.lwjgl.vulkan.VkMemoryHeap; import org.lwjgl.vulkan.VkMemoryType; @@ -16,13 +17,13 @@ public abstract class MemoryType { this.vkMemoryHeap = vkMemoryHeap; } - abstract void createBuffer(Buffer buffer, int size); + public abstract void createBuffer(Buffer buffer, long size); - abstract void copyToBuffer(Buffer buffer, long bufferSize, ByteBuffer byteBuffer); + public abstract void copyToBuffer(Buffer buffer, ByteBuffer src, long size, long srcOffset, long dstOffset); - abstract void copyFromBuffer(Buffer buffer, long bufferSize, ByteBuffer byteBuffer); + public abstract void copyFromBuffer(Buffer buffer, long bufferSize, ByteBuffer byteBuffer); - abstract boolean mappable(); + public abstract boolean mappable(); public Type getType() { return this.type; diff --git a/src/main/java/net/vulkanmod/vulkan/memory/MemoryTypes.java b/src/main/java/net/vulkanmod/vulkan/memory/MemoryTypes.java index 300a813b5..9becd6202 100644 --- a/src/main/java/net/vulkanmod/vulkan/memory/MemoryTypes.java +++ b/src/main/java/net/vulkanmod/vulkan/memory/MemoryTypes.java @@ -2,7 +2,10 @@ import net.vulkanmod.vulkan.Vulkan; import net.vulkanmod.vulkan.device.DeviceManager; +import net.vulkanmod.vulkan.memory.buffer.Buffer; +import net.vulkanmod.vulkan.memory.buffer.StagingBuffer; import net.vulkanmod.vulkan.util.VUtil; +import org.lwjgl.system.MemoryUtil; import org.lwjgl.vulkan.VkMemoryHeap; import org.lwjgl.vulkan.VkMemoryType; @@ -19,15 +22,14 @@ public static void createMemoryTypes() { for (int i = 0; i < DeviceManager.memoryProperties.memoryTypeCount(); ++i) { VkMemoryType memoryType = DeviceManager.memoryProperties.memoryTypes(i); VkMemoryHeap heap = DeviceManager.memoryProperties.memoryHeaps(memoryType.heapIndex()); + int propertyFlags = memoryType.propertyFlags(); - //GPU only Memory - if (memoryType.propertyFlags() == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) { + if (propertyFlags == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) { GPU_MEM = new DeviceLocalMemory(memoryType, heap); - } - if (memoryType.propertyFlags() == (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT)) { - HOST_MEM = new HostLocalCachedMemory(memoryType, heap); + if (propertyFlags == (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) { + HOST_MEM = new HostCoherentMemory(memoryType, heap); } } @@ -63,35 +65,35 @@ public static class DeviceLocalMemory extends MemoryType { } @Override - void createBuffer(Buffer buffer, int size) { + public void createBuffer(Buffer buffer, long size) { MemoryManager.getInstance().createBuffer(buffer, size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | buffer.usage, VK_MEMORY_HEAP_DEVICE_LOCAL_BIT); } @Override - void copyToBuffer(Buffer buffer, long bufferSize, ByteBuffer byteBuffer) { + public void copyToBuffer(Buffer buffer, ByteBuffer src, long size, long srcOffset, long dstOffset) { StagingBuffer stagingBuffer = Vulkan.getStagingBuffer(); - stagingBuffer.copyBuffer((int) bufferSize, byteBuffer); + stagingBuffer.copyBuffer((int) size, src); - DeviceManager.getTransferQueue().copyBufferCmd(stagingBuffer.id, stagingBuffer.offset, buffer.getId(), buffer.getUsedBytes(), bufferSize); + DeviceManager.getTransferQueue().copyBufferCmd(stagingBuffer.getId(), stagingBuffer.getOffset(), buffer.getId(), dstOffset, size); } @Override - void copyFromBuffer(Buffer buffer, long bufferSize, ByteBuffer byteBuffer) { + public void copyFromBuffer(Buffer buffer, long bufferSize, ByteBuffer byteBuffer) { // TODO } public long copyBuffer(Buffer src, Buffer dst) { - if (dst.bufferSize < src.bufferSize) { + if (dst.getBufferSize() < src.getBufferSize()) { throw new IllegalArgumentException("dst size is less than src size."); } - return DeviceManager.getTransferQueue().copyBufferCmd(src.getId(), 0, dst.getId(), 0, src.bufferSize); + return DeviceManager.getTransferQueue().copyBufferCmd(src.getId(), 0, dst.getId(), 0, src.getBufferSize()); } @Override - boolean mappable() { + public boolean mappable() { return false; } } @@ -103,45 +105,35 @@ static abstract class MappableMemory extends MemoryType { } @Override - void copyToBuffer(Buffer buffer, long bufferSize, ByteBuffer byteBuffer) { - VUtil.memcpy(byteBuffer, buffer.data.getByteBuffer(0, (int) buffer.bufferSize), (int) bufferSize, buffer.getUsedBytes()); + public void copyToBuffer(Buffer buffer, ByteBuffer src, long size, long srcOffset, long dstOffset) { + VUtil.memcpy(src, buffer, size, srcOffset, dstOffset); } @Override - void copyFromBuffer(Buffer buffer, long bufferSize, ByteBuffer byteBuffer) { - VUtil.memcpy(buffer.data.getByteBuffer(0, (int) buffer.bufferSize), byteBuffer, 0); + public void copyFromBuffer(Buffer buffer, long size, ByteBuffer byteBuffer) { + MemoryUtil.memCopy(buffer.getDataPtr(), MemoryUtil.memAddress(byteBuffer), size); + VUtil.memcpy(buffer, byteBuffer, size); } @Override - boolean mappable() { + public boolean mappable() { return true; } } - static class HostLocalCachedMemory extends MappableMemory { + static class HostCoherentMemory extends MappableMemory { - HostLocalCachedMemory(VkMemoryType vkMemoryType, VkMemoryHeap vkMemoryHeap) { + HostCoherentMemory(VkMemoryType vkMemoryType, VkMemoryHeap vkMemoryHeap) { super(Type.HOST_LOCAL, vkMemoryType, vkMemoryHeap); } @Override - void createBuffer(Buffer buffer, int size) { - + public void createBuffer(Buffer buffer, long size) { MemoryManager.getInstance().createBuffer(buffer, size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | buffer.usage, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT); - } - - void copyToBuffer(Buffer buffer, long dstOffset, long bufferSize, ByteBuffer byteBuffer) { - VUtil.memcpy(byteBuffer, buffer.data.getByteBuffer((int) 0, (int) buffer.bufferSize), (int) bufferSize, dstOffset); + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); } - void copyBuffer(Buffer src, Buffer dst) { - VUtil.memcpy(src.data.getByteBuffer(0, src.bufferSize), - dst.data.getByteBuffer(0, dst.bufferSize), src.bufferSize, 0); - -// copyBufferCmd(src.getId(), 0, dst.getId(), 0, src.bufferSize); - } } static class HostLocalFallbackMemory extends MappableMemory { @@ -151,7 +143,7 @@ static class HostLocalFallbackMemory extends MappableMemory { } @Override - void createBuffer(Buffer buffer, int size) { + public void createBuffer(Buffer buffer, long size) { MemoryManager.getInstance().createBuffer(buffer, size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | buffer.usage, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); @@ -165,7 +157,7 @@ static class DeviceMappableMemory extends MappableMemory { } @Override - void createBuffer(Buffer buffer, int size) { + public void createBuffer(Buffer buffer, long size) { MemoryManager.getInstance().createBuffer(buffer, size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | buffer.usage, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); diff --git a/src/main/java/net/vulkanmod/vulkan/memory/StagingBuffer.java b/src/main/java/net/vulkanmod/vulkan/memory/StagingBuffer.java deleted file mode 100644 index f90331087..000000000 --- a/src/main/java/net/vulkanmod/vulkan/memory/StagingBuffer.java +++ /dev/null @@ -1,53 +0,0 @@ -package net.vulkanmod.vulkan.memory; - -import net.vulkanmod.render.chunk.util.Util; -import net.vulkanmod.vulkan.util.VUtil; -import org.lwjgl.system.MemoryUtil; - -import java.nio.ByteBuffer; - -import static org.lwjgl.system.libc.LibCString.nmemcpy; -import static org.lwjgl.vulkan.VK10.*; - -public class StagingBuffer extends Buffer { - - public StagingBuffer(int bufferSize) { - super(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, MemoryTypes.HOST_MEM); - this.usedBytes = 0; - this.offset = 0; - - this.createBuffer(bufferSize); - } - - public void copyBuffer(int size, ByteBuffer byteBuffer) { - - if(size > this.bufferSize - this.usedBytes) { - resizeBuffer((this.bufferSize + size) * 2); - } - -// VUtil.memcpy(byteBuffer, this.data.getByteBuffer(0, this.bufferSize), this.usedBytes); - nmemcpy(this.data.get(0) + this.usedBytes, MemoryUtil.memAddress(byteBuffer), size); - - offset = usedBytes; - usedBytes += size; - - //createVertexBuffer(vertexSize, vertexCount, byteBuffer); - } - - public void align(int alignment) { - int alignedValue = Util.align(usedBytes, alignment); - - if(alignedValue > this.bufferSize) { - resizeBuffer((this.bufferSize) * 2); - } - - usedBytes = alignedValue; - } - - private void resizeBuffer(int newSize) { - MemoryManager.getInstance().addToFreeable(this); - this.createBuffer(newSize); - - System.out.println("resized staging buffer to: " + newSize); - } -} diff --git a/src/main/java/net/vulkanmod/vulkan/memory/VertexBuffer.java b/src/main/java/net/vulkanmod/vulkan/memory/VertexBuffer.java deleted file mode 100644 index 37f3ffc7f..000000000 --- a/src/main/java/net/vulkanmod/vulkan/memory/VertexBuffer.java +++ /dev/null @@ -1,40 +0,0 @@ -package net.vulkanmod.vulkan.memory; - -import java.nio.ByteBuffer; - -import static org.lwjgl.vulkan.VK10.VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - -public class VertexBuffer extends Buffer { - - public VertexBuffer(int size) { - this(size, MemoryTypes.HOST_MEM); - } - - public VertexBuffer(int size, MemoryType type) { - super(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, type); - this.createBuffer(size); - - } - - public void copyToVertexBuffer(long vertexSize, long vertexCount, ByteBuffer byteBuffer) { - int bufferSize = (int) (vertexSize * vertexCount); -// long bufferSize = byteBuffer.limit(); - - if(bufferSize > this.bufferSize - this.usedBytes) { - resizeBuffer((this.bufferSize + bufferSize) * 2); - } - - this.type.copyToBuffer(this, bufferSize, byteBuffer); - offset = usedBytes; - usedBytes += bufferSize; - - } - - private void resizeBuffer(int newSize) { - MemoryManager.getInstance().addToFreeable(this); - this.createBuffer(newSize); - -// System.out.println("resized vertexBuffer to: " + newSize); - } - -} diff --git a/src/main/java/net/vulkanmod/vulkan/memory/buffer/Buffer.java b/src/main/java/net/vulkanmod/vulkan/memory/buffer/Buffer.java new file mode 100644 index 000000000..ac8ac91e4 --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/memory/buffer/Buffer.java @@ -0,0 +1,109 @@ +package net.vulkanmod.vulkan.memory.buffer; + +import net.vulkanmod.vulkan.memory.MemoryManager; +import net.vulkanmod.vulkan.memory.MemoryType; + +import java.nio.ByteBuffer; + +public class Buffer { + public final MemoryType type; + public final int usage; + + protected long id; + protected long allocation; + + protected long bufferSize; + protected long usedBytes; + protected long offset; + + protected long dataPtr; + + public Buffer(int usage, MemoryType type) { + this.usage = usage; + this.type = type; + } + + public void createBuffer(long bufferSize) { + this.type.createBuffer(this, bufferSize); + + if (this.type.mappable()) { + this.dataPtr = MemoryManager.getInstance().Map(this.allocation).get(0); + } + } + + public void resizeBuffer(long newSize) { + MemoryManager.getInstance().addToFreeable(this); + this.createBuffer(newSize); + } + + public void copyBuffer(ByteBuffer byteBuffer, int size) { + if (size > this.bufferSize - this.usedBytes) { + resizeBuffer((this.bufferSize + size) * 2); + } + + this.type.copyToBuffer(this, byteBuffer, size, 0, this.usedBytes); + this.offset = this.usedBytes; + this.usedBytes += size; + } + + public void copyBuffer(ByteBuffer byteBuffer, int size, int dstOffset) { + if (size > this.bufferSize - dstOffset) { + resizeBuffer((this.bufferSize + size) * 2); + } + + this.type.copyToBuffer(this, byteBuffer, size, 0, dstOffset); + this.offset = dstOffset; + this.usedBytes = dstOffset + size; + } + + public void scheduleFree() { + MemoryManager.getInstance().addToFreeable(this); + } + + public void reset() { + usedBytes = 0; + } + + public long getAllocation() { + return allocation; + } + + public long getUsedBytes() { + return usedBytes; + } + + public long getOffset() { + return offset; + } + + public long getId() { + return id; + } + + public long getBufferSize() { + return bufferSize; + } + + public long getDataPtr() { + return dataPtr; + } + + public void setBufferSize(long size) { + this.bufferSize = size; + } + + public void setId(long id) { + this.id = id; + } + + public void setAllocation(long allocation) { + this.allocation = allocation; + } + + public BufferInfo getBufferInfo() { + return new BufferInfo(this.id, this.allocation, this.bufferSize, this.type.getType()); + } + + public record BufferInfo(long id, long allocation, long bufferSize, MemoryType.Type type) { + } +} diff --git a/src/main/java/net/vulkanmod/vulkan/memory/buffer/BufferSlice.java b/src/main/java/net/vulkanmod/vulkan/memory/buffer/BufferSlice.java new file mode 100644 index 000000000..8d3132f9b --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/memory/buffer/BufferSlice.java @@ -0,0 +1,25 @@ +package net.vulkanmod.vulkan.memory.buffer; + +public class BufferSlice { + Buffer buffer; + int offset; + int size; + + public void set(Buffer buffer, int offset, int size) { + this.buffer = buffer; + this.offset = offset; + this.size = size; + } + + public Buffer getBuffer() { + return buffer; + } + + public int getOffset() { + return offset; + } + + public int getSize() { + return size; + } +} diff --git a/src/main/java/net/vulkanmod/vulkan/memory/buffer/IndexBuffer.java b/src/main/java/net/vulkanmod/vulkan/memory/buffer/IndexBuffer.java new file mode 100644 index 000000000..1b2ad4c8b --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/memory/buffer/IndexBuffer.java @@ -0,0 +1,36 @@ +package net.vulkanmod.vulkan.memory.buffer; + +import net.vulkanmod.vulkan.memory.MemoryType; + +import static org.lwjgl.vulkan.VK10.*; + +public class IndexBuffer extends Buffer { + + public IndexType indexType; + + public IndexBuffer(int size, MemoryType type) { + this(size, type, IndexType.UINT16); + } + + public IndexBuffer(int size, MemoryType type, IndexType indexType) { + super(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, type); + this.indexType = indexType; + + this.createBuffer(size); + } + + public enum IndexType { + UINT16(2, VK_INDEX_TYPE_UINT16), + UINT32(4, VK_INDEX_TYPE_UINT32); + + public final int size; + public final int value; + + IndexType(int size, int value) { + this.size = size; + this.value = value; + } + } + + +} diff --git a/src/main/java/net/vulkanmod/vulkan/memory/IndirectBuffer.java b/src/main/java/net/vulkanmod/vulkan/memory/buffer/IndirectBuffer.java similarity index 76% rename from src/main/java/net/vulkanmod/vulkan/memory/IndirectBuffer.java rename to src/main/java/net/vulkanmod/vulkan/memory/buffer/IndirectBuffer.java index 811bddfb1..6b09cb0cb 100644 --- a/src/main/java/net/vulkanmod/vulkan/memory/IndirectBuffer.java +++ b/src/main/java/net/vulkanmod/vulkan/memory/buffer/IndirectBuffer.java @@ -1,8 +1,10 @@ -package net.vulkanmod.vulkan.memory; +package net.vulkanmod.vulkan.memory.buffer; import net.vulkanmod.vulkan.Synchronization; import net.vulkanmod.vulkan.Vulkan; import net.vulkanmod.vulkan.device.DeviceManager; +import net.vulkanmod.vulkan.memory.MemoryManager; +import net.vulkanmod.vulkan.memory.MemoryType; import net.vulkanmod.vulkan.queue.CommandPool; import net.vulkanmod.vulkan.queue.TransferQueue; @@ -22,11 +24,12 @@ public void recordCopyCmd(ByteBuffer byteBuffer) { int size = byteBuffer.remaining(); if (size > this.bufferSize - this.usedBytes) { - resizeBuffer(); + resizeBuffer((long) (this.bufferSize * 1.5f)); + this.usedBytes = 0; } if (this.type.mappable()) { - this.type.copyToBuffer(this, size, byteBuffer); + this.type.copyToBuffer(this, byteBuffer, size, 0, this.usedBytes); } else { if (commandBuffer == null) commandBuffer = DeviceManager.getTransferQueue().beginCommands(); @@ -41,13 +44,6 @@ public void recordCopyCmd(ByteBuffer byteBuffer) { usedBytes += size; } - private void resizeBuffer() { - MemoryManager.getInstance().addToFreeable(this); - int newSize = this.bufferSize + (this.bufferSize >> 1); - this.createBuffer(newSize); - this.usedBytes = 0; - } - public void submitUploads() { if (commandBuffer == null) return; @@ -57,8 +53,4 @@ public void submitUploads() { commandBuffer = null; } - //debug - public ByteBuffer getByteBuffer() { - return this.data.getByteBuffer(0, this.bufferSize); - } } diff --git a/src/main/java/net/vulkanmod/vulkan/memory/buffer/StagingBuffer.java b/src/main/java/net/vulkanmod/vulkan/memory/buffer/StagingBuffer.java new file mode 100644 index 000000000..03d764c5a --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/memory/buffer/StagingBuffer.java @@ -0,0 +1,65 @@ +package net.vulkanmod.vulkan.memory.buffer; + +import net.vulkanmod.render.chunk.buffer.UploadManager; +import net.vulkanmod.render.chunk.util.Util; +import net.vulkanmod.render.texture.ImageUploadHelper; +import net.vulkanmod.vulkan.Synchronization; +import net.vulkanmod.vulkan.memory.MemoryTypes; +import org.lwjgl.system.MemoryUtil; + +import java.nio.ByteBuffer; + +import static org.lwjgl.system.libc.LibCString.nmemcpy; +import static org.lwjgl.vulkan.VK10.*; + +public class StagingBuffer extends Buffer { + private static final long DEFAULT_SIZE = 64 * 1024 * 1024; + + public StagingBuffer() { + this(DEFAULT_SIZE); + } + + public StagingBuffer(long size) { + super(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, MemoryTypes.HOST_MEM); + this.createBuffer(size); + } + + public void copyBuffer(int size, ByteBuffer byteBuffer) { + this.copyBuffer(size, MemoryUtil.memAddress(byteBuffer)); + } + + public void copyBuffer(int size, long scrPtr) { + if (size > this.bufferSize) { + throw new IllegalArgumentException("Upload size is greater than staging buffer size."); + } + + if (size > this.bufferSize - this.usedBytes) { + submitUploads(); + } + + nmemcpy(this.dataPtr + this.usedBytes, scrPtr, size); + + this.offset = this.usedBytes; + this.usedBytes += size; + } + + public void align(int alignment) { + long alignedOffset = Util.align(usedBytes, alignment); + + if (alignedOffset > this.bufferSize) { + submitUploads(); + alignedOffset = 0; + } + + this.usedBytes = alignedOffset; + } + + private void submitUploads() { + // Submit and wait all recorded uploads before resetting the buffer + UploadManager.INSTANCE.submitUploads(); + ImageUploadHelper.INSTANCE.submitCommands(); + Synchronization.INSTANCE.waitFences(); + + this.reset(); + } +} diff --git a/src/main/java/net/vulkanmod/vulkan/memory/UniformBuffer.java b/src/main/java/net/vulkanmod/vulkan/memory/buffer/UniformBuffer.java similarity index 65% rename from src/main/java/net/vulkanmod/vulkan/memory/UniformBuffer.java rename to src/main/java/net/vulkanmod/vulkan/memory/buffer/UniformBuffer.java index fd6f80fe3..b9d102d18 100644 --- a/src/main/java/net/vulkanmod/vulkan/memory/UniformBuffer.java +++ b/src/main/java/net/vulkanmod/vulkan/memory/buffer/UniformBuffer.java @@ -1,16 +1,16 @@ -package net.vulkanmod.vulkan.memory; +package net.vulkanmod.vulkan.memory.buffer; import net.vulkanmod.vulkan.device.DeviceManager; +import net.vulkanmod.vulkan.memory.MemoryType; import static net.vulkanmod.vulkan.util.VUtil.align; import static org.lwjgl.vulkan.VK10.VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; public class UniformBuffer extends Buffer { - - private final static int minOffset = (int) DeviceManager.deviceProperties.limits().minUniformBufferOffsetAlignment(); + private final static int MIN_OFFSET_ALIGNMENT = (int) DeviceManager.deviceProperties.limits().minUniformBufferOffsetAlignment(); public static int getAlignedSize(int uploadSize) { - return align(uploadSize, minOffset); + return align(uploadSize, MIN_OFFSET_ALIGNMENT); } public UniformBuffer(int size, MemoryType memoryType) { @@ -28,12 +28,7 @@ public void updateOffset(int alignedSize) { usedBytes += alignedSize; } - private void resizeBuffer(int newSize) { - MemoryManager.getInstance().addToFreeable(this); - createBuffer(newSize); - } - public long getPointer() { - return this.data.get(0) + usedBytes; + return this.dataPtr + usedBytes; } } diff --git a/src/main/java/net/vulkanmod/vulkan/memory/buffer/VertexBuffer.java b/src/main/java/net/vulkanmod/vulkan/memory/buffer/VertexBuffer.java new file mode 100644 index 000000000..fb9858c9b --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/memory/buffer/VertexBuffer.java @@ -0,0 +1,19 @@ +package net.vulkanmod.vulkan.memory.buffer; + +import net.vulkanmod.vulkan.memory.MemoryType; +import net.vulkanmod.vulkan.memory.MemoryTypes; + +import static org.lwjgl.vulkan.VK10.VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + +public class VertexBuffer extends Buffer { + + public VertexBuffer(int size) { + this(size, MemoryTypes.HOST_MEM); + } + + public VertexBuffer(int size, MemoryType type) { + super(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, type); + this.createBuffer(size); + } + +} diff --git a/src/main/java/net/vulkanmod/vulkan/memory/AutoIndexBuffer.java b/src/main/java/net/vulkanmod/vulkan/memory/buffer/index/AutoIndexBuffer.java similarity index 66% rename from src/main/java/net/vulkanmod/vulkan/memory/AutoIndexBuffer.java rename to src/main/java/net/vulkanmod/vulkan/memory/buffer/index/AutoIndexBuffer.java index 98795ff19..d4aaa0a81 100644 --- a/src/main/java/net/vulkanmod/vulkan/memory/AutoIndexBuffer.java +++ b/src/main/java/net/vulkanmod/vulkan/memory/buffer/index/AutoIndexBuffer.java @@ -1,6 +1,8 @@ -package net.vulkanmod.vulkan.memory; +package net.vulkanmod.vulkan.memory.buffer.index; import net.vulkanmod.Initializer; +import net.vulkanmod.vulkan.memory.MemoryTypes; +import net.vulkanmod.vulkan.memory.buffer.IndexBuffer; import org.lwjgl.system.MemoryUtil; import java.nio.ByteBuffer; @@ -8,8 +10,8 @@ import java.nio.ShortBuffer; public class AutoIndexBuffer { - public static final int U16_MAX_INDEX_COUNT = 65536; - public static final int QUAD_U16_MAX_VERTEX_COUNT = U16_MAX_INDEX_COUNT * 3 / 2; + public static final int U16_MAX_VERTEX_COUNT = 65536; + public static final int QUAD_U16_MAX_INDEX_COUNT = U16_MAX_VERTEX_COUNT * 3 / 2; int vertexCount; DrawType drawType; @@ -25,41 +27,86 @@ private void createIndexBuffer(int vertexCount) { this.vertexCount = vertexCount; ByteBuffer buffer; - IndexBuffer.IndexType indexType = IndexBuffer.IndexType.SHORT; + IndexBuffer.IndexType indexType = IndexBuffer.IndexType.UINT16; + + if (vertexCount > U16_MAX_VERTEX_COUNT && + (this.drawType == DrawType.QUADS || this.drawType == DrawType.LINES)) { + indexType = IndexBuffer.IndexType.UINT32; + } switch (this.drawType) { case QUADS -> { - if (vertexCount <= QUAD_U16_MAX_VERTEX_COUNT) + if (indexType == IndexBuffer.IndexType.UINT16) buffer = genQuadIndices(vertexCount); else { - indexType = IndexBuffer.IndexType.INT; buffer = genIntQuadIndices(vertexCount); } } case TRIANGLE_FAN -> buffer = genTriangleFanIndices(vertexCount); case TRIANGLE_STRIP -> buffer = genTriangleStripIndices(vertexCount); - case LINES -> buffer = genLinesIndices(vertexCount); + case LINES -> { + if (indexType == IndexBuffer.IndexType.UINT16) + buffer = genLinesIndices(vertexCount); + else { + buffer = genIntLinesIndices(vertexCount); + } + } case DEBUG_LINE_STRIP -> buffer = genDebugLineStripIndices(vertexCount); default -> throw new IllegalArgumentException("Unsupported drawType: %s".formatted(this.drawType)); } int size = buffer.capacity(); this.indexBuffer = new IndexBuffer(size, MemoryTypes.GPU_MEM, indexType); - this.indexBuffer.copyBuffer(buffer); + this.indexBuffer.copyBuffer(buffer, buffer.remaining()); MemoryUtil.memFree(buffer); } public void checkCapacity(int vertexCount) { - if(vertexCount > this.vertexCount) { - int newVertexCount = this.vertexCount * 2; + if (vertexCount > this.vertexCount) { + int newVertexCount = Math.max(this.vertexCount * 2, vertexCount); Initializer.LOGGER.info("Reallocating AutoIndexBuffer from {} to {}", this.vertexCount, newVertexCount); - this.indexBuffer.freeBuffer(); + this.indexBuffer.scheduleFree(); createIndexBuffer(newVertexCount); } } + public IndexBuffer getIndexBuffer() { + return this.indexBuffer; + } + + public void freeBuffer() { + this.indexBuffer.scheduleFree(); + } + + public int getIndexCount(int vertexCount) { + return getIndexCount(this.drawType, vertexCount); + } + + public static int getIndexCount(DrawType drawType, int vertexCount) { + switch (drawType) { + case QUADS, LINES -> { + return vertexCount * 3 / 2; + } + case TRIANGLE_FAN, TRIANGLE_STRIP -> { + return (vertexCount - 2) * 3; + } + case DEBUG_LINE_STRIP -> { + return (vertexCount - 1) * 2; + } + default -> throw new RuntimeException(String.format("unknown drawMode: %s", drawType)); + } + } + + public static int maxVertexCount(DrawType drawType, int maxIndexCount) { + return switch (drawType) { + case QUADS, LINES -> maxIndexCount * 3 / 2; + + default -> maxIndexCount; + }; + } + public static ByteBuffer genQuadIndices(int vertexCount) { int indexCount = vertexCount * 3 / 2; indexCount = roundUpToDivisible(indexCount, 6); @@ -68,7 +115,7 @@ public static ByteBuffer genQuadIndices(int vertexCount) { ShortBuffer idxs = buffer.asShortBuffer(); int j = 0; - for(int i = 0; i < vertexCount; i += 4) { + for (int i = 0; i < vertexCount; i += 4) { idxs.put(j + 0, (short) (i)); idxs.put(j + 1, (short) (i + 1)); idxs.put(j + 2, (short) (i + 2)); @@ -90,7 +137,7 @@ public static ByteBuffer genIntQuadIndices(int vertexCount) { IntBuffer idxs = buffer.asIntBuffer(); int j = 0; - for(int i = 0; i < vertexCount; i += 4) { + for (int i = 0; i < vertexCount; i += 4) { idxs.put(j + 0, (i)); idxs.put(j + 1, (i + 1)); idxs.put(j + 2, (i + 2)); @@ -112,7 +159,7 @@ public static ByteBuffer genLinesIndices(int vertexCount) { ShortBuffer idxs = buffer.asShortBuffer(); int j = 0; - for(int i = 0; i < vertexCount; i += 4) { + for (int i = 0; i < vertexCount; i += 4) { idxs.put(j + 0, (short) (i)); idxs.put(j + 1, (short) (i + 1)); idxs.put(j + 2, (short) (i + 2)); @@ -126,6 +173,28 @@ public static ByteBuffer genLinesIndices(int vertexCount) { return buffer; } + public static ByteBuffer genIntLinesIndices(int vertexCount) { + int indexCount = vertexCount * 3 / 2; + indexCount = roundUpToDivisible(indexCount, 6); + + ByteBuffer buffer = MemoryUtil.memAlloc(indexCount * Integer.BYTES); + IntBuffer idxs = buffer.asIntBuffer(); + + int j = 0; + for (int i = 0; i < vertexCount; i += 4) { + idxs.put(j + 0, (i)); + idxs.put(j + 1, (i + 1)); + idxs.put(j + 2, (i + 2)); + idxs.put(j + 3, (i + 3)); + idxs.put(j + 4, (i + 2)); + idxs.put(j + 5, (i + 1)); + + j += 6; + } + + return buffer; + } + public static ByteBuffer genTriangleFanIndices(int vertexCount) { int indexCount = (vertexCount - 2) * 3; ByteBuffer buffer = MemoryUtil.memAlloc(indexCount * Short.BYTES); @@ -182,12 +251,6 @@ public static int roundUpToDivisible(int n, int d) { return ((n + d - 1) / d) * d; } - public IndexBuffer getIndexBuffer() { return this.indexBuffer; } - - public void freeBuffer() { - this.indexBuffer.freeBuffer(); - } - public enum DrawType { QUADS(7), TRIANGLE_FAN(6), @@ -202,14 +265,6 @@ public enum DrawType { this.n = n; } - public static int getIndexCount(DrawType drawType, int vertexCount) { - return switch (drawType) { - case QUADS, LINES -> vertexCount * 3 / 2; - case TRIANGLE_FAN, TRIANGLE_STRIP -> (vertexCount - 2) * 3; - default -> 0; - }; - } - public static int getQuadIndexCount(int vertexCount) { return vertexCount * 3 / 2; } diff --git a/src/main/java/net/vulkanmod/vulkan/pass/DefaultMainPass.java b/src/main/java/net/vulkanmod/vulkan/pass/DefaultMainPass.java index 59b1c2afe..d382fa563 100644 --- a/src/main/java/net/vulkanmod/vulkan/pass/DefaultMainPass.java +++ b/src/main/java/net/vulkanmod/vulkan/pass/DefaultMainPass.java @@ -1,9 +1,11 @@ package net.vulkanmod.vulkan.pass; -import com.mojang.blaze3d.pipeline.RenderTarget; -import net.minecraft.client.Minecraft; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.textures.GpuTexture; +import com.mojang.blaze3d.textures.GpuTextureView; +import net.vulkanmod.render.engine.VkGpuDevice; +import net.vulkanmod.render.engine.VkGpuTexture; import net.vulkanmod.vulkan.Renderer; -import net.vulkanmod.vulkan.Vulkan; import net.vulkanmod.vulkan.framebuffer.Framebuffer; import net.vulkanmod.vulkan.framebuffer.RenderPass; import net.vulkanmod.vulkan.framebuffer.SwapChain; @@ -12,7 +14,6 @@ import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.VkCommandBuffer; import org.lwjgl.vulkan.VkRect2D; -import org.lwjgl.vulkan.VkViewport; import static org.lwjgl.vulkan.KHRSwapchain.VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; import static org.lwjgl.vulkan.VK10.*; @@ -23,17 +24,20 @@ public static DefaultMainPass create() { return new DefaultMainPass(); } - private RenderTarget mainTarget; private final Framebuffer mainFramebuffer; private RenderPass mainRenderPass; private RenderPass auxRenderPass; + private GpuTexture[] colorAttachmentTextures; + private GpuTextureView[] colorAttachmentTextureViews; + private GpuTexture depthAttachmentTexture; + DefaultMainPass() { - this.mainTarget = Minecraft.getInstance().getMainRenderTarget(); - this.mainFramebuffer = Vulkan.getSwapChain(); + this.mainFramebuffer = Renderer.getInstance().getSwapChain(); createRenderPasses(); + createAttachmentTextures(); } private void createRenderPasses() { @@ -55,15 +59,14 @@ private void createRenderPasses() { @Override public void begin(VkCommandBuffer commandBuffer, MemoryStack stack) { - SwapChain framebuffer = Vulkan.getSwapChain(); + SwapChain framebuffer = Renderer.getInstance().getSwapChain(); VulkanImage colorAttachment = framebuffer.getColorAttachment(); colorAttachment.transitionImageLayout(stack, commandBuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - framebuffer.beginRenderPass(commandBuffer, this.mainRenderPass, stack); + Renderer.getInstance().beginRenderPass(this.mainRenderPass, framebuffer); - VkViewport.Buffer pViewport = framebuffer.viewport(stack); - vkCmdSetViewport(commandBuffer, 0, pViewport); + Renderer.setViewport(0, 0, framebuffer.getWidth(), framebuffer.getHeight(), stack); VkRect2D.Buffer pScissor = framebuffer.scissor(stack); vkCmdSetScissor(commandBuffer, 0, pScissor); @@ -73,42 +76,49 @@ public void begin(VkCommandBuffer commandBuffer, MemoryStack stack) { public void end(VkCommandBuffer commandBuffer) { Renderer.getInstance().endRenderPass(commandBuffer); - try(MemoryStack stack = MemoryStack.stackPush()) { - SwapChain framebuffer = Vulkan.getSwapChain(); + try (MemoryStack stack = MemoryStack.stackPush()) { + SwapChain framebuffer = Renderer.getInstance().getSwapChain(); framebuffer.getColorAttachment().transitionImageLayout(stack, commandBuffer, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); } int result = vkEndCommandBuffer(commandBuffer); - if(result != VK_SUCCESS) { + if (result != VK_SUCCESS) { throw new RuntimeException("Failed to record command buffer:" + result); } } + @Override + public void cleanUp() { + this.mainRenderPass.cleanUp(); + this.auxRenderPass.cleanUp(); + } + + @Override + public void onResize() { + this.createAttachmentTextures(); + } + public void rebindMainTarget() { - SwapChain swapChain = Vulkan.getSwapChain(); + SwapChain swapChain = Renderer.getInstance().getSwapChain(); VkCommandBuffer commandBuffer = Renderer.getCommandBuffer(); // Do not rebind if the framebuffer is already bound RenderPass boundRenderPass = Renderer.getInstance().getBoundRenderPass(); - if(boundRenderPass == this.mainRenderPass || boundRenderPass == this.auxRenderPass) + if (boundRenderPass == this.mainRenderPass || boundRenderPass == this.auxRenderPass) return; Renderer.getInstance().endRenderPass(commandBuffer); - - try(MemoryStack stack = MemoryStack.stackPush()) { - swapChain.beginRenderPass(commandBuffer, this.auxRenderPass, stack); - } - + Renderer.getInstance().beginRenderPass(this.auxRenderPass, swapChain); } @Override public void bindAsTexture() { - SwapChain swapChain = Vulkan.getSwapChain(); + SwapChain swapChain = Renderer.getInstance().getSwapChain(); VkCommandBuffer commandBuffer = Renderer.getCommandBuffer(); // Check if render pass is using the framebuffer RenderPass boundRenderPass = Renderer.getInstance().getBoundRenderPass(); - if(boundRenderPass == this.mainRenderPass || boundRenderPass == this.auxRenderPass) + if (boundRenderPass == this.mainRenderPass || boundRenderPass == this.auxRenderPass) Renderer.getInstance().endRenderPass(commandBuffer); try (MemoryStack stack = MemoryStack.stackPush()) { @@ -118,8 +128,41 @@ public void bindAsTexture() { VTextureSelector.bindTexture(swapChain.getColorAttachment()); } - public int getColorAttachmentGlId() { - SwapChain swapChain = Vulkan.getSwapChain(); - return swapChain.getColorAttachmentGlId(); + @Override + public GpuTexture getColorAttachment() { + return this.colorAttachmentTextures[Renderer.getCurrentImage()]; + } + + @Override + public GpuTextureView getColorAttachmentView() { + return this.colorAttachmentTextureViews[Renderer.getCurrentImage()]; + } + + @Override + public GpuTexture getDepthAttachment() { + return this.depthAttachmentTexture; + } + + private void createAttachmentTextures() { + VkGpuDevice device = (VkGpuDevice) RenderSystem.getDevice(); + + SwapChain swapChain = Renderer.getInstance().getSwapChain(); + var swapChainImages = swapChain.getImages(); + + if (swapChain.getWidth() == 0 && swapChain.getHeight() == 0) + return; + + int imageCount = swapChainImages.size(); + this.colorAttachmentTextures = new GpuTexture[imageCount]; + this.colorAttachmentTextureViews = new GpuTextureView[imageCount]; + + for (int i = 0; i < imageCount; ++i) { + VkGpuTexture attachmentTexture = device.gpuTextureFromVulkanImage(swapChainImages.get(i)); + GpuTextureView attachmentTextureView = device.createTextureView(attachmentTexture); + this.colorAttachmentTextures[i] = attachmentTexture; + this.colorAttachmentTextureViews[i] = attachmentTextureView; + } + + this.depthAttachmentTexture = device.gpuTextureFromVulkanImage(swapChain.getDepthAttachment()); } } diff --git a/src/main/java/net/vulkanmod/vulkan/pass/MainPass.java b/src/main/java/net/vulkanmod/vulkan/pass/MainPass.java index d62476f0b..d5e1b44c8 100644 --- a/src/main/java/net/vulkanmod/vulkan/pass/MainPass.java +++ b/src/main/java/net/vulkanmod/vulkan/pass/MainPass.java @@ -1,7 +1,7 @@ package net.vulkanmod.vulkan.pass; -import net.vulkanmod.vulkan.Vulkan; -import net.vulkanmod.vulkan.framebuffer.SwapChain; +import com.mojang.blaze3d.textures.GpuTexture; +import com.mojang.blaze3d.textures.GpuTextureView; import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.VkCommandBuffer; @@ -11,6 +11,10 @@ public interface MainPass { void end(VkCommandBuffer commandBuffer); + void cleanUp(); + + void onResize(); + default void mainTargetBindWrite() {} default void mainTargetUnbindWrite() {} @@ -19,7 +23,16 @@ default void rebindMainTarget() {} default void bindAsTexture() {} - default int getColorAttachmentGlId() { - return -1; + default GpuTexture getColorAttachment() { + return null; + } + + default GpuTextureView getColorAttachmentView() { + return null; } + + default GpuTexture getDepthAttachment() { + return null; + } + } diff --git a/src/main/java/net/vulkanmod/vulkan/queue/CommandPool.java b/src/main/java/net/vulkanmod/vulkan/queue/CommandPool.java index eff323b7f..bf30ebec6 100644 --- a/src/main/java/net/vulkanmod/vulkan/queue/CommandPool.java +++ b/src/main/java/net/vulkanmod/vulkan/queue/CommandPool.java @@ -23,13 +23,12 @@ public class CommandPool { this.createCommandPool(queueFamilyIndex); } - public void createCommandPool(int familyIndex) { - + public void createCommandPool(int queueFamily) { try (MemoryStack stack = stackPush()) { VkCommandPoolCreateInfo poolInfo = VkCommandPoolCreateInfo.calloc(stack); poolInfo.sType(VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO); - poolInfo.queueFamilyIndex(familyIndex); + poolInfo.queueFamilyIndex(queueFamily); poolInfo.flags(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); LongBuffer pCommandPool = stack.mallocLong(1); @@ -42,68 +41,51 @@ public void createCommandPool(int familyIndex) { } } - public CommandBuffer beginCommands() { - + public CommandBuffer getCommandBuffer() { try (MemoryStack stack = stackPush()) { - final int size = 10; - - if (availableCmdBuffers.isEmpty()) { - - VkCommandBufferAllocateInfo allocInfo = VkCommandBufferAllocateInfo.calloc(stack); - allocInfo.sType$Default(); - allocInfo.level(VK_COMMAND_BUFFER_LEVEL_PRIMARY); - allocInfo.commandPool(id); - allocInfo.commandBufferCount(size); - - PointerBuffer pCommandBuffer = stack.mallocPointer(size); - vkAllocateCommandBuffers(Vulkan.getVkDevice(), allocInfo, pCommandBuffer); - - VkFenceCreateInfo fenceInfo = VkFenceCreateInfo.calloc(stack); - fenceInfo.sType$Default(); - fenceInfo.flags(VK_FENCE_CREATE_SIGNALED_BIT); - - for (int i = 0; i < size; ++i) { - LongBuffer pFence = stack.mallocLong(size); - vkCreateFence(Vulkan.getVkDevice(), fenceInfo, null, pFence); - - CommandBuffer commandBuffer = new CommandBuffer(new VkCommandBuffer(pCommandBuffer.get(i), Vulkan.getVkDevice()), pFence.get(0)); - commandBuffer.handle = new VkCommandBuffer(pCommandBuffer.get(i), Vulkan.getVkDevice()); - commandBuffers.add(commandBuffer); - availableCmdBuffers.add(commandBuffer); - } - - } - - CommandBuffer commandBuffer = availableCmdBuffers.poll(); - - VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.calloc(stack); - beginInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO); - beginInfo.flags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); - - vkBeginCommandBuffer(commandBuffer.handle, beginInfo); - -// current++; + return getCommandBuffer(stack); + } + } - return commandBuffer; + public CommandBuffer getCommandBuffer(MemoryStack stack) { + if (availableCmdBuffers.isEmpty()) { + allocateCommandBuffers(stack); } + + CommandBuffer commandBuffer = availableCmdBuffers.poll(); + return commandBuffer; } - public long submitCommands(CommandBuffer commandBuffer, VkQueue queue) { + private void allocateCommandBuffers(MemoryStack stack) { + final int size = 10; - try (MemoryStack stack = stackPush()) { - long fence = commandBuffer.fence; + VkCommandBufferAllocateInfo allocInfo = VkCommandBufferAllocateInfo.calloc(stack); + allocInfo.sType$Default(); + allocInfo.level(VK_COMMAND_BUFFER_LEVEL_PRIMARY); + allocInfo.commandPool(id); + allocInfo.commandBufferCount(size); - vkEndCommandBuffer(commandBuffer.handle); + PointerBuffer pCommandBuffer = stack.mallocPointer(size); + vkAllocateCommandBuffers(Vulkan.getVkDevice(), allocInfo, pCommandBuffer); - vkResetFences(Vulkan.getVkDevice(), commandBuffer.fence); + VkFenceCreateInfo fenceInfo = VkFenceCreateInfo.calloc(stack); + fenceInfo.sType$Default(); + fenceInfo.flags(VK_FENCE_CREATE_SIGNALED_BIT); - VkSubmitInfo submitInfo = VkSubmitInfo.calloc(stack); - submitInfo.sType(VK_STRUCTURE_TYPE_SUBMIT_INFO); - submitInfo.pCommandBuffers(stack.pointers(commandBuffer.handle)); + VkSemaphoreCreateInfo semaphoreCreateInfo = VkSemaphoreCreateInfo.calloc(stack); + semaphoreCreateInfo.sType$Default(); - vkQueueSubmit(queue, submitInfo, fence); + for (int i = 0; i < size; ++i) { + LongBuffer pFence = stack.mallocLong(1); + vkCreateFence(Vulkan.getVkDevice(), fenceInfo, null, pFence); - return fence; + LongBuffer pSemaphore = stack.mallocLong(1); + vkCreateSemaphore(Vulkan.getVkDevice(), semaphoreCreateInfo, null, pSemaphore); + + VkCommandBuffer vkCommandBuffer = new VkCommandBuffer(pCommandBuffer.get(i), Vulkan.getVkDevice()); + CommandBuffer commandBuffer = new CommandBuffer(this, vkCommandBuffer, pFence.get(0), pSemaphore.get(0)); + commandBuffers.add(commandBuffer); + availableCmdBuffers.add(commandBuffer); } } @@ -114,20 +96,30 @@ public void addToAvailable(CommandBuffer commandBuffer) { public void cleanUp() { for (CommandBuffer commandBuffer : commandBuffers) { vkDestroyFence(Vulkan.getVkDevice(), commandBuffer.fence, null); + vkDestroySemaphore(Vulkan.getVkDevice(), commandBuffer.semaphore, null); } vkResetCommandPool(Vulkan.getVkDevice(), id, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT); vkDestroyCommandPool(Vulkan.getVkDevice(), id, null); } - public class CommandBuffer { - VkCommandBuffer handle; - long fence; + public long getId() { + return id; + } + + public static class CommandBuffer { + public final CommandPool commandPool; + public final VkCommandBuffer handle; + public final long fence; + public final long semaphore; + boolean submitted; boolean recording; - public CommandBuffer(VkCommandBuffer handle, long fence) { + public CommandBuffer(CommandPool commandPool, VkCommandBuffer handle, long fence, long semaphore) { + this.commandPool = commandPool; this.handle = handle; this.fence = fence; + this.semaphore = semaphore; } public VkCommandBuffer getHandle() { @@ -138,6 +130,10 @@ public long getFence() { return fence; } + public long getSemaphore() { + return semaphore; + } + public boolean isSubmitted() { return submitted; } @@ -146,10 +142,42 @@ public boolean isRecording() { return recording; } + public void begin(MemoryStack stack) { + VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.calloc(stack); + beginInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO); + beginInfo.flags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); + + vkBeginCommandBuffer(this.handle, beginInfo); + + this.recording = true; + } + + public long submitCommands(MemoryStack stack, VkQueue queue, boolean useSemaphore) { + long fence = this.fence; + + vkEndCommandBuffer(this.handle); + + vkResetFences(Vulkan.getVkDevice(), this.fence); + + VkSubmitInfo submitInfo = VkSubmitInfo.calloc(stack); + submitInfo.sType(VK_STRUCTURE_TYPE_SUBMIT_INFO); + submitInfo.pCommandBuffers(stack.pointers(this.handle)); + + if (useSemaphore) { + submitInfo.pSignalSemaphores(stack.longs(this.semaphore)); + } + + vkQueueSubmit(queue, submitInfo, fence); + + this.recording = false; + this.submitted = true; + return fence; + } + public void reset() { this.submitted = false; this.recording = false; - addToAvailable(this); + this.commandPool.addToAvailable(this); } } } diff --git a/src/main/java/net/vulkanmod/vulkan/queue/Queue.java b/src/main/java/net/vulkanmod/vulkan/queue/Queue.java index 4f68e0778..6169ed7fb 100644 --- a/src/main/java/net/vulkanmod/vulkan/queue/Queue.java +++ b/src/main/java/net/vulkanmod/vulkan/queue/Queue.java @@ -18,15 +18,20 @@ import static org.lwjgl.vulkan.VK10.*; public abstract class Queue { - private static VkDevice DEVICE; - + private static VkDevice device; private static QueueFamilyIndices queueFamilyIndices; - protected CommandPool commandPool; - private final VkQueue queue; + private final VkQueue vkQueue; + + protected CommandPool commandPool; public synchronized CommandPool.CommandBuffer beginCommands() { - return this.commandPool.beginCommands(); + try (MemoryStack stack = stackPush()) { + CommandPool.CommandBuffer commandBuffer = this.commandPool.getCommandBuffer(stack); + commandBuffer.begin(stack); + + return commandBuffer; + } } Queue(MemoryStack stack, int familyIndex) { @@ -36,18 +41,24 @@ public synchronized CommandPool.CommandBuffer beginCommands() { Queue(MemoryStack stack, int familyIndex, boolean initCommandPool) { PointerBuffer pQueue = stack.mallocPointer(1); vkGetDeviceQueue(DeviceManager.vkDevice, familyIndex, 0, pQueue); - this.queue = new VkQueue(pQueue.get(0), DeviceManager.vkDevice); + this.vkQueue = new VkQueue(pQueue.get(0), DeviceManager.vkDevice); if (initCommandPool) this.commandPool = new CommandPool(familyIndex); } - public synchronized long submitCommands(CommandPool.CommandBuffer commandBuffer) { - return this.commandPool.submitCommands(commandBuffer, queue); + public long submitCommands(CommandPool.CommandBuffer commandBuffer) { + return submitCommands(commandBuffer, false); } - public VkQueue queue() { - return this.queue; + public synchronized long submitCommands(CommandPool.CommandBuffer commandBuffer, boolean useSemaphore) { + try (MemoryStack stack = stackPush()) { + return commandBuffer.submitCommands(stack, vkQueue, useSemaphore); + } + } + + public VkQueue vkQueue() { + return this.vkQueue; } public void cleanUp() { @@ -56,7 +67,11 @@ public void cleanUp() { } public void waitIdle() { - vkQueueWaitIdle(queue); + vkQueueWaitIdle(vkQueue); + } + + public CommandPool getCommandPool() { + return commandPool; } public enum Family { @@ -66,17 +81,16 @@ public enum Family { } public static QueueFamilyIndices getQueueFamilies() { - if (DEVICE == null) - DEVICE = Vulkan.getVkDevice(); + if (device == null) + device = Vulkan.getVkDevice(); if (queueFamilyIndices == null) { - queueFamilyIndices = findQueueFamilies(DEVICE.getPhysicalDevice()); + queueFamilyIndices = findQueueFamilies(device.getPhysicalDevice()); } return queueFamilyIndices; } public static QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) { - QueueFamilyIndices indices = new QueueFamilyIndices(); try (MemoryStack stack = stackPush()) { @@ -130,30 +144,33 @@ public static QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) { Initializer.LOGGER.warn("Using compute queue as present fallback"); } + // In case there's no dedicated transfer queue, we need choose another one + // preferably a different one from the already selected queues if (indices.transferFamily == -1) { - int fallback = -1; + int transferIndex = -1; for (int i = 0; i < queueFamilies.capacity(); i++) { int queueFlags = queueFamilies.get(i).queueFlags(); if ((queueFlags & VK_QUEUE_TRANSFER_BIT) != 0) { - if (fallback == -1) - fallback = i; + if (transferIndex == -1) + transferIndex = i; if ((queueFlags & (VK_QUEUE_GRAPHICS_BIT)) == 0) { indices.transferFamily = i; if (i != indices.computeFamily) break; - fallback = i; + + transferIndex = i; } } + } - if (fallback == -1) - throw new RuntimeException("Failed to find queue family with transfer support"); + if (transferIndex == -1) + throw new RuntimeException("Failed to find queue family with transfer support"); - indices.transferFamily = fallback; - } + indices.transferFamily = transferIndex; } if (indices.computeFamily == -1) { diff --git a/src/main/java/net/vulkanmod/vulkan/shader/DescriptorSets.java b/src/main/java/net/vulkanmod/vulkan/shader/DescriptorSets.java new file mode 100644 index 000000000..deda2cd75 --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/shader/DescriptorSets.java @@ -0,0 +1,303 @@ +package net.vulkanmod.vulkan.shader; + +import net.vulkanmod.vulkan.Vulkan; +import net.vulkanmod.vulkan.memory.MemoryManager; +import net.vulkanmod.vulkan.memory.buffer.Buffer; +import net.vulkanmod.vulkan.memory.buffer.BufferSlice; +import net.vulkanmod.vulkan.memory.buffer.UniformBuffer; +import net.vulkanmod.vulkan.shader.descriptor.ImageDescriptor; +import net.vulkanmod.vulkan.shader.descriptor.UBO; +import net.vulkanmod.vulkan.texture.VulkanImage; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.system.MemoryUtil; +import org.lwjgl.vulkan.*; + +import java.nio.IntBuffer; +import java.nio.LongBuffer; +import java.util.Arrays; + +import static org.lwjgl.system.MemoryStack.stackPush; +import static org.lwjgl.vulkan.VK10.*; +import static org.lwjgl.vulkan.VK10.vkDestroyDescriptorPool; + +public class DescriptorSets { + private static final VkDevice DEVICE = Vulkan.getVkDevice(); + + private final Pipeline pipeline; + private int poolSize = 10; + private long descriptorPool = VK_NULL_HANDLE; + private long[] sets; + private long currentSet; + private int currentIdx = -1; + + private final long[] boundUBs; + private final ImageDescriptor.State[] boundTextures; + private final IntBuffer dynamicOffsets; + + DescriptorSets(Pipeline pipeline) { + this.pipeline = pipeline; + this.boundTextures = new ImageDescriptor.State[pipeline.imageDescriptors.size()]; + this.dynamicOffsets = MemoryUtil.memAllocInt(pipeline.buffers.size()); + this.boundUBs = new long[pipeline.buffers.size()]; + + Arrays.setAll(boundTextures, i -> new ImageDescriptor.State(0, 0)); + + try (MemoryStack stack = stackPush()) { + this.createDescriptorPool(stack); + this.createDescriptorSets(stack); + } + } + + public void bindSets(VkCommandBuffer commandBuffer, UniformBuffer uniformBuffer, int bindPoint) { + try (MemoryStack stack = stackPush()) { + + this.updateUniforms(uniformBuffer); + this.updateDescriptorSet(stack, uniformBuffer); + + vkCmdBindDescriptorSets(commandBuffer, bindPoint, pipeline.pipelineLayout, + 0, stack.longs(currentSet), dynamicOffsets); + } + } + + private void updateUniforms(UniformBuffer globalUB) { + int i = 0; + for (UBO ubo : pipeline.getBuffers()) { + // Prevent NPE in case UBO has no bound buffer slice + if (ubo.getBufferSlice().getBuffer() == null) { + ubo.setUseGlobalBuffer(true); + ubo.setUpdate(true); + } + + boolean useOwnUB = !ubo.useGlobalBuffer(); + + int offset; + if (useOwnUB) { + BufferSlice bufferSlice = ubo.getBufferSlice(); + offset = bufferSlice.getOffset(); + } + else { + offset = (int) globalUB.getUsedBytes(); + int alignedSize = UniformBuffer.getAlignedSize(ubo.getSize()); + globalUB.checkCapacity(alignedSize); + + if (ubo.shouldUpdate()) { + ubo.update(globalUB.getPointer()); + } + globalUB.updateOffset(alignedSize); + + BufferSlice bufferSlice = ubo.getBufferSlice(); + bufferSlice.set(globalUB, offset, alignedSize); + } + + this.dynamicOffsets.put(i, offset); + + ++i; + } + } + + private boolean needsUpdate(UniformBuffer uniformBuffer) { + if (currentIdx == -1) + return true; + + for (int j = 0; j < pipeline.imageDescriptors.size(); ++j) { + ImageDescriptor imageDescriptor = pipeline.imageDescriptors.get(j); + VulkanImage image = imageDescriptor.getImage(); + + if (image == null) { + throw new NullPointerException(); + } + + long view = imageDescriptor.getImageView(image); + long sampler = image.getSampler(); + + if (imageDescriptor.isReadOnlyLayout) + image.readOnlyLayout(); + + if (!this.boundTextures[j].isCurrentState(view, sampler)) { + return true; + } + } + + for (int j = 0; j < pipeline.buffers.size(); ++j) { + UBO ubo = pipeline.buffers.get(j); + Buffer uniformBufferI = ubo.getBufferSlice().getBuffer(); + + + if (uniformBufferI == null) + uniformBufferI = uniformBuffer; + + if (this.boundUBs[j] != uniformBufferI.getId()) { + return true; + } + } + + return false; + } + + private void checkPoolSize(MemoryStack stack) { + if (this.currentIdx >= this.poolSize) { + this.poolSize *= 2; + + this.createDescriptorPool(stack); + this.createDescriptorSets(stack); + this.currentIdx = 0; + } + } + + private void updateDescriptorSet(MemoryStack stack, UniformBuffer uniformBuffer) { + + // Check if update is needed + if (!needsUpdate(uniformBuffer)) + return; + + this.currentIdx++; + + // Check pool size + checkPoolSize(stack); + + this.currentSet = this.sets[this.currentIdx]; + + VkWriteDescriptorSet.Buffer descriptorWrites = VkWriteDescriptorSet.calloc(pipeline.buffers.size() + pipeline.imageDescriptors.size(), stack); + VkDescriptorBufferInfo.Buffer[] bufferInfos = new VkDescriptorBufferInfo.Buffer[pipeline.buffers.size()]; + + //TODO maybe ubo update is not needed everytime + int i = 0; + for (UBO ubo : pipeline.getBuffers()) { + Buffer ub = ubo.getBufferSlice().getBuffer(); + boundUBs[i] = ub.getId(); + + bufferInfos[i] = VkDescriptorBufferInfo.calloc(1, stack); + bufferInfos[i].buffer(boundUBs[i]); + bufferInfos[i].range(ubo.getSize()); + + VkWriteDescriptorSet descriptorWrite = descriptorWrites.get(i); + descriptorWrite.sType$Default(); + descriptorWrite.dstBinding(ubo.getBinding()); + descriptorWrite.dstArrayElement(0); + descriptorWrite.descriptorType(ubo.getType()); + descriptorWrite.descriptorCount(1); + descriptorWrite.pBufferInfo(bufferInfos[i]); + descriptorWrite.dstSet(currentSet); + + ++i; + } + + VkDescriptorImageInfo.Buffer[] imageInfo = new VkDescriptorImageInfo.Buffer[pipeline.imageDescriptors.size()]; + + for (int j = 0; j < pipeline.imageDescriptors.size(); ++j) { + ImageDescriptor imageDescriptor = pipeline.imageDescriptors.get(j); + VulkanImage image = imageDescriptor.getImage(); + + if (image == null) { + throw new NullPointerException(); + } + + long view = imageDescriptor.getImageView(image); + long sampler = image.getSampler(); + int layout = imageDescriptor.getLayout(); + + if (imageDescriptor.isReadOnlyLayout) + image.readOnlyLayout(); + + imageInfo[j] = VkDescriptorImageInfo.calloc(1, stack); + imageInfo[j].imageLayout(layout); + imageInfo[j].imageView(view); + + if (imageDescriptor.useSampler) { + imageInfo[j].sampler(sampler); + } + + VkWriteDescriptorSet descriptorWrite = descriptorWrites.get(i); + descriptorWrite.sType$Default(); + descriptorWrite.dstBinding(imageDescriptor.getBinding()); + descriptorWrite.dstArrayElement(0); + descriptorWrite.descriptorType(imageDescriptor.getType()); + descriptorWrite.descriptorCount(1); + descriptorWrite.pImageInfo(imageInfo[j]); + descriptorWrite.dstSet(currentSet); + + this.boundTextures[j].set(view, sampler); + ++i; + } + + vkUpdateDescriptorSets(DEVICE, descriptorWrites, null); + } + + private void createDescriptorSets(MemoryStack stack) { + LongBuffer layouts = MemoryUtil.memAllocLong(this.poolSize); + + for (int i = 0; i < this.poolSize; ++i) { + layouts.put(i, pipeline.descriptorSetLayout); + } + + VkDescriptorSetAllocateInfo allocInfo = VkDescriptorSetAllocateInfo.calloc(stack); + allocInfo.sType$Default(); + allocInfo.descriptorPool(descriptorPool); + allocInfo.pSetLayouts(layouts); + + // Not hotspot code, use heap array + this.sets = new long[this.poolSize]; + + int result = vkAllocateDescriptorSets(DEVICE, allocInfo, this.sets); + if (result != VK_SUCCESS) { + throw new RuntimeException("Failed to allocate descriptor sets. Result:" + result); + } + + MemoryUtil.memFree(layouts); + } + + private void createDescriptorPool(MemoryStack stack) { + int size = pipeline.buffers.size() + pipeline.imageDescriptors.size(); + + VkDescriptorPoolSize.Buffer poolSizes = VkDescriptorPoolSize.calloc(size, stack); + + int i = 0; + for (var buffer : pipeline.getBuffers()) { + VkDescriptorPoolSize uniformBufferPoolSize = poolSizes.get(i); + uniformBufferPoolSize.type(buffer.getType()); + uniformBufferPoolSize.descriptorCount(this.poolSize); + + ++i; + } + + for (var imageDescriptor : pipeline.getImageDescriptors()) { + VkDescriptorPoolSize textureSamplerPoolSize = poolSizes.get(i); + textureSamplerPoolSize.type(imageDescriptor.getType()); + textureSamplerPoolSize.descriptorCount(this.poolSize); + + ++i; + } + + VkDescriptorPoolCreateInfo poolInfo = VkDescriptorPoolCreateInfo.calloc(stack); + poolInfo.sType(VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO); + poolInfo.pPoolSizes(poolSizes); + poolInfo.maxSets(this.poolSize); + + LongBuffer pDescriptorPool = stack.mallocLong(1); + + if (vkCreateDescriptorPool(DEVICE, poolInfo, null, pDescriptorPool) != VK_SUCCESS) { + throw new RuntimeException("Failed to create descriptor pool"); + } + + if (this.descriptorPool != VK_NULL_HANDLE) { + final long oldDescriptorPool = this.descriptorPool; + MemoryManager.getInstance().addFrameOp(() -> { + vkDestroyDescriptorPool(DEVICE, oldDescriptorPool, null); + }); + } + + this.descriptorPool = pDescriptorPool.get(0); + } + + public void resetIdx() { + this.currentIdx = -1; + } + + public void cleanUp() { + vkResetDescriptorPool(DEVICE, descriptorPool, 0); + vkDestroyDescriptorPool(DEVICE, descriptorPool, null); + + MemoryUtil.memFree(this.dynamicOffsets); + } + +} \ No newline at end of file diff --git a/src/main/java/net/vulkanmod/vulkan/shader/GraphicsPipeline.java b/src/main/java/net/vulkanmod/vulkan/shader/GraphicsPipeline.java index 179ce47b3..abf9e7e07 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/GraphicsPipeline.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/GraphicsPipeline.java @@ -1,5 +1,6 @@ package net.vulkanmod.vulkan.shader; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormatElement; import it.unimi.dsi.fastutil.objects.Object2LongMap; @@ -16,7 +17,6 @@ import java.nio.LongBuffer; import java.util.List; -import static org.lwjgl.system.MemoryStack.stackGet; import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.*; @@ -80,8 +80,11 @@ private long createGraphicsPipeline(PipelineState state) { VkPipelineVertexInputStateCreateInfo vertexInputInfo = VkPipelineVertexInputStateCreateInfo.calloc(stack); vertexInputInfo.sType(VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO); - vertexInputInfo.pVertexBindingDescriptions(vertexInputDescription.bindingDescriptions); - vertexInputInfo.pVertexAttributeDescriptions(vertexInputDescription.attributeDescriptions); + + if (vertexInputDescription != null) { + vertexInputInfo.pVertexBindingDescriptions(vertexInputDescription.bindingDescriptions); + vertexInputInfo.pVertexAttributeDescriptions(vertexInputDescription.attributeDescriptions); + } // ===> ASSEMBLY STAGE <=== @@ -143,10 +146,10 @@ private long createGraphicsPipeline(PipelineState state) { colorBlendAttachment.blendEnable(true); colorBlendAttachment.srcColorBlendFactor(PipelineState.BlendState.getSrcRgbFactor(state.blendState_i)); colorBlendAttachment.dstColorBlendFactor(PipelineState.BlendState.getDstRgbFactor(state.blendState_i)); - colorBlendAttachment.colorBlendOp(VK_BLEND_OP_ADD); + colorBlendAttachment.colorBlendOp(PipelineState.BlendState.blendOp(state.blendState_i)); colorBlendAttachment.srcAlphaBlendFactor(PipelineState.BlendState.getSrcAlphaFactor(state.blendState_i)); colorBlendAttachment.dstAlphaBlendFactor(PipelineState.BlendState.getDstAlphaFactor(state.blendState_i)); - colorBlendAttachment.alphaBlendOp(VK_BLEND_OP_ADD); + colorBlendAttachment.alphaBlendOp(PipelineState.BlendState.blendOp(state.blendState_i)); } else { colorBlendAttachment.blendEnable(false); @@ -164,10 +167,15 @@ private long createGraphicsPipeline(PipelineState state) { VkPipelineDynamicStateCreateInfo dynamicStates = VkPipelineDynamicStateCreateInfo.calloc(stack); dynamicStates.sType(VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO); - if (topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST || polygonMode == VK_POLYGON_MODE_LINE) - dynamicStates.pDynamicStates(stack.ints(VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_LINE_WIDTH)); - else - dynamicStates.pDynamicStates(stack.ints(VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR)); + if (topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST || polygonMode == VK_POLYGON_MODE_LINE) { + dynamicStates.pDynamicStates( + stack.ints(VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, + VK_DYNAMIC_STATE_LINE_WIDTH)); + } + else { + dynamicStates.pDynamicStates( + stack.ints(VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR)); + } VkGraphicsPipelineCreateInfo.Buffer pipelineInfo = VkGraphicsPipelineCreateInfo.calloc(1, stack); pipelineInfo.sType(VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO); @@ -199,9 +207,8 @@ private long createGraphicsPipeline(PipelineState state) { LongBuffer pGraphicsPipeline = stack.mallocLong(1); - if (vkCreateGraphicsPipelines(DeviceManager.vkDevice, PIPELINE_CACHE, pipelineInfo, null, pGraphicsPipeline) != VK_SUCCESS) { - throw new RuntimeException("Failed to create graphics pipeline"); - } + Vulkan.checkResult(vkCreateGraphicsPipelines(DeviceManager.vkDevice, PIPELINE_CACHE, pipelineInfo, null, pGraphicsPipeline), + "Failed to create graphics pipeline " + this.name); return pGraphicsPipeline.get(0); } @@ -237,13 +244,21 @@ static class VertexInputDescription { final VkVertexInputBindingDescription.Buffer bindingDescriptions; VertexInputDescription(VertexFormat vertexFormat) { - this.bindingDescriptions = getBindingDescription(vertexFormat); - this.attributeDescriptions = getAttributeDescriptions(vertexFormat); + if (vertexFormat != DefaultVertexFormat.EMPTY) { + this.bindingDescriptions = getBindingDescription(vertexFormat); + this.attributeDescriptions = getAttributeDescriptions(vertexFormat); + } + else { + this.bindingDescriptions = null; + this.attributeDescriptions = null; + } } void cleanUp() { - MemoryUtil.memFree(this.bindingDescriptions); - MemoryUtil.memFree(this.attributeDescriptions); + if (this.bindingDescriptions != null) { + MemoryUtil.memFree(this.bindingDescriptions); + MemoryUtil.memFree(this.attributeDescriptions); + } } } @@ -302,10 +317,20 @@ private static VkVertexInputAttributeDescription.Buffer getAttributeDescriptions } case COLOR -> { - posDescription.format(VK_FORMAT_R8G8B8A8_UNORM); - posDescription.offset(offset); + switch (type) { + case UBYTE -> { + posDescription.format(VK_FORMAT_R8G8B8A8_UNORM); + posDescription.offset(offset); - offset += 4; + offset += 4; + } + case UINT -> { + posDescription.format(VK_FORMAT_R32_UINT); + posDescription.offset(offset); + + offset += 4; + } + } } case UV -> { @@ -326,6 +351,12 @@ private static VkVertexInputAttributeDescription.Buffer getAttributeDescriptions posDescription.format(VK_FORMAT_R16G16_UINT); posDescription.offset(offset); + offset += 4; + } + case UINT -> { + posDescription.format(VK_FORMAT_R32_UINT); + posDescription.offset(offset); + offset += 4; } } diff --git a/src/main/java/net/vulkanmod/vulkan/shader/Pipeline.java b/src/main/java/net/vulkanmod/vulkan/shader/Pipeline.java index f3f8bf326..8837c11f8 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/Pipeline.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/Pipeline.java @@ -10,7 +10,7 @@ import net.vulkanmod.vulkan.device.DeviceManager; import net.vulkanmod.vulkan.framebuffer.RenderPass; import net.vulkanmod.vulkan.memory.MemoryManager; -import net.vulkanmod.vulkan.memory.UniformBuffer; +import net.vulkanmod.vulkan.memory.buffer.UniformBuffer; import net.vulkanmod.vulkan.shader.SPIRVUtils.SPIRV; import net.vulkanmod.vulkan.shader.SPIRVUtils.ShaderKind; import net.vulkanmod.vulkan.shader.descriptor.ImageDescriptor; @@ -18,26 +18,22 @@ import net.vulkanmod.vulkan.shader.descriptor.UBO; import net.vulkanmod.vulkan.shader.layout.AlignedStruct; import net.vulkanmod.vulkan.shader.layout.PushConstants; +import net.vulkanmod.vulkan.shader.layout.Uniform; import net.vulkanmod.vulkan.texture.VTextureSelector; -import net.vulkanmod.vulkan.texture.VulkanImage; +import net.vulkanmod.vulkan.util.MappedBuffer; import org.apache.commons.lang3.Validate; import org.lwjgl.system.MemoryStack; -import org.lwjgl.system.MemoryUtil; import org.lwjgl.vulkan.*; -import java.io.InputStream; -import java.io.InputStreamReader; import java.nio.ByteBuffer; -import java.nio.IntBuffer; import java.nio.LongBuffer; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Arrays; import java.util.LinkedList; import java.util.List; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; -import static net.vulkanmod.vulkan.shader.SPIRVUtils.compileShader; -import static net.vulkanmod.vulkan.shader.SPIRVUtils.compileShaderAbsoluteFile; import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.*; @@ -167,7 +163,7 @@ public void scheduleCleanUp() { public abstract void cleanUp(); - void destroyDescriptorSets() { + protected void destroyDescriptorSets() { for (DescriptorSets descriptorSets : this.descriptorSets) { descriptorSets.cleanUp(); } @@ -193,6 +189,44 @@ public long getLayout() { return pipelineLayout; } + public List getBuffers() { + return buffers; + } + + public UBO getUBO(int binding) { + return getUBO(ubo -> ubo.binding == binding); + } + + public UBO getUBO(String name) { + return getUBO(ubo -> ubo.name.equals(name)); + } + + public UBO getUBO(Predicate fn) { + UBO ubo = null; + for (UBO ubo1 : this.buffers) { + if (fn.test(ubo1)) { + ubo = ubo1; + } + } + + return ubo; + } + + public ImageDescriptor getImageDescriptor(String name) { + return getImageDescriptor(imageDescriptor -> imageDescriptor.name.equals(name)); + } + + public ImageDescriptor getImageDescriptor(Predicate fn) { + ImageDescriptor descriptor = null; + for (ImageDescriptor descriptor1 : this.imageDescriptors) { + if (fn.test(descriptor1)) { + descriptor = descriptor1; + } + } + + return descriptor; + } + public List getImageDescriptors() { return imageDescriptors; } @@ -206,10 +240,8 @@ public void bindDescriptorSets(VkCommandBuffer commandBuffer, UniformBuffer unif this.descriptorSets[frame].bindSets(commandBuffer, uniformBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS); } - static long createShaderModule(ByteBuffer spirvCode) { - + protected static long createShaderModule(ByteBuffer spirvCode) { try (MemoryStack stack = stackPush()) { - VkShaderModuleCreateInfo createInfo = VkShaderModuleCreateInfo.calloc(stack); createInfo.sType(VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO); @@ -225,270 +257,7 @@ static long createShaderModule(ByteBuffer spirvCode) { } } - protected static class DescriptorSets { - private final Pipeline pipeline; - private int poolSize = 10; - private long descriptorPool; - private LongBuffer sets; - private long currentSet; - private int currentIdx = -1; - - private final long[] boundUBs; - private final ImageDescriptor.State[] boundTextures; - private final IntBuffer dynamicOffsets; - - DescriptorSets(Pipeline pipeline) { - this.pipeline = pipeline; - this.boundTextures = new ImageDescriptor.State[pipeline.imageDescriptors.size()]; - this.dynamicOffsets = MemoryUtil.memAllocInt(pipeline.buffers.size()); - this.boundUBs = new long[pipeline.buffers.size()]; - - Arrays.setAll(boundTextures, i -> new ImageDescriptor.State(0, 0)); - - try (MemoryStack stack = stackPush()) { - this.createDescriptorPool(stack); - this.createDescriptorSets(stack); - } - } - - protected void bindSets(VkCommandBuffer commandBuffer, UniformBuffer uniformBuffer, int bindPoint) { - try (MemoryStack stack = stackPush()) { - - this.updateUniforms(uniformBuffer); - this.updateDescriptorSet(stack, uniformBuffer); - - vkCmdBindDescriptorSets(commandBuffer, bindPoint, pipeline.pipelineLayout, - 0, stack.longs(currentSet), dynamicOffsets); - } - } - - private void updateUniforms(UniformBuffer globalUB) { - int i = 0; - for (UBO ubo : pipeline.buffers) { - boolean useOwnUB = ubo.getUniformBuffer() != null; - UniformBuffer ub = useOwnUB ? ubo.getUniformBuffer() : globalUB; - - int currentOffset = (int) ub.getUsedBytes(); - this.dynamicOffsets.put(i, currentOffset); - - // TODO: non mappable memory - - int alignedSize = UniformBuffer.getAlignedSize(ubo.getSize()); - ub.checkCapacity(alignedSize); - - if (!useOwnUB) { - ubo.update(ub.getPointer()); - ub.updateOffset(alignedSize); - } - - ++i; - } - } - - private boolean needsUpdate(UniformBuffer uniformBuffer) { - if (currentIdx == -1) - return true; - - for (int j = 0; j < pipeline.imageDescriptors.size(); ++j) { - ImageDescriptor imageDescriptor = pipeline.imageDescriptors.get(j); - VulkanImage image = imageDescriptor.getImage(); - long view = imageDescriptor.getImageView(image); - long sampler = image.getSampler(); - - if (imageDescriptor.isReadOnlyLayout) - image.readOnlyLayout(); - - if (!this.boundTextures[j].isCurrentState(view, sampler)) { - return true; - } - } - - for (int j = 0; j < pipeline.buffers.size(); ++j) { - UBO ubo = pipeline.buffers.get(j); - UniformBuffer uniformBufferI = ubo.getUniformBuffer(); - - if (uniformBufferI == null) - uniformBufferI = uniformBuffer; - - if (this.boundUBs[j] != uniformBufferI.getId()) { - return true; - } - } - - return false; - } - - private void checkPoolSize(MemoryStack stack) { - if (this.currentIdx >= this.poolSize) { - this.poolSize *= 2; - - this.createDescriptorPool(stack); - this.createDescriptorSets(stack); - this.currentIdx = 0; - - //debug -// System.out.println("resized descriptor pool to: " + this.poolSize); - } - } - - private void updateDescriptorSet(MemoryStack stack, UniformBuffer uniformBuffer) { - - //Check if update is needed - if (!needsUpdate(uniformBuffer)) - return; - - this.currentIdx++; - - //Check pool size - checkPoolSize(stack); - - this.currentSet = this.sets.get(this.currentIdx); - - VkWriteDescriptorSet.Buffer descriptorWrites = VkWriteDescriptorSet.calloc(pipeline.buffers.size() + pipeline.imageDescriptors.size(), stack); - VkDescriptorBufferInfo.Buffer[] bufferInfos = new VkDescriptorBufferInfo.Buffer[pipeline.buffers.size()]; - - //TODO maybe ubo update is not needed everytime - int i = 0; - for (UBO ubo : pipeline.buffers) { - UniformBuffer ub = ubo.getUniformBuffer(); - if (ub == null) - ub = uniformBuffer; - boundUBs[i] = ub.getId(); - - bufferInfos[i] = VkDescriptorBufferInfo.calloc(1, stack); - bufferInfos[i].buffer(boundUBs[i]); - bufferInfos[i].range(ubo.getSize()); - - VkWriteDescriptorSet uboDescriptorWrite = descriptorWrites.get(i); - uboDescriptorWrite.sType$Default(); - uboDescriptorWrite.dstBinding(ubo.getBinding()); - uboDescriptorWrite.dstArrayElement(0); - uboDescriptorWrite.descriptorType(ubo.getType()); - uboDescriptorWrite.descriptorCount(1); - uboDescriptorWrite.pBufferInfo(bufferInfos[i]); - uboDescriptorWrite.dstSet(currentSet); - - ++i; - } - - VkDescriptorImageInfo.Buffer[] imageInfo = new VkDescriptorImageInfo.Buffer[pipeline.imageDescriptors.size()]; - - for (int j = 0; j < pipeline.imageDescriptors.size(); ++j) { - ImageDescriptor imageDescriptor = pipeline.imageDescriptors.get(j); - VulkanImage image = imageDescriptor.getImage(); - long view = imageDescriptor.getImageView(image); - long sampler = image.getSampler(); - int layout = imageDescriptor.getLayout(); - - if (imageDescriptor.isReadOnlyLayout) - image.readOnlyLayout(); - - imageInfo[j] = VkDescriptorImageInfo.calloc(1, stack); - imageInfo[j].imageLayout(layout); - imageInfo[j].imageView(view); - - if (imageDescriptor.useSampler) - imageInfo[j].sampler(sampler); - - VkWriteDescriptorSet samplerDescriptorWrite = descriptorWrites.get(i); - samplerDescriptorWrite.sType(VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET); - samplerDescriptorWrite.dstBinding(imageDescriptor.getBinding()); - samplerDescriptorWrite.dstArrayElement(0); - samplerDescriptorWrite.descriptorType(imageDescriptor.getType()); - samplerDescriptorWrite.descriptorCount(1); - samplerDescriptorWrite.pImageInfo(imageInfo[j]); - samplerDescriptorWrite.dstSet(currentSet); - - this.boundTextures[j].set(view, sampler); - ++i; - } - - vkUpdateDescriptorSets(DEVICE, descriptorWrites, null); - } - - private void createDescriptorSets(MemoryStack stack) { - LongBuffer layout = stack.mallocLong(this.poolSize); -// layout.put(0, descriptorSetLayout); - - for (int i = 0; i < this.poolSize; ++i) { - layout.put(i, pipeline.descriptorSetLayout); - } - - VkDescriptorSetAllocateInfo allocInfo = VkDescriptorSetAllocateInfo.calloc(stack); - allocInfo.sType$Default(); - allocInfo.descriptorPool(descriptorPool); - allocInfo.pSetLayouts(layout); - - this.sets = MemoryUtil.memAllocLong(this.poolSize); - - int result = vkAllocateDescriptorSets(DEVICE, allocInfo, this.sets); - if (result != VK_SUCCESS) { - throw new RuntimeException("Failed to allocate descriptor sets. Result:" + result); - } - } - - private void createDescriptorPool(MemoryStack stack) { - int size = pipeline.buffers.size() + pipeline.imageDescriptors.size(); - - VkDescriptorPoolSize.Buffer poolSizes = VkDescriptorPoolSize.calloc(size, stack); - - int i; - for (i = 0; i < pipeline.buffers.size(); ++i) { - VkDescriptorPoolSize uniformBufferPoolSize = poolSizes.get(i); -// uniformBufferPoolSize.type(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); - uniformBufferPoolSize.type(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC); - uniformBufferPoolSize.descriptorCount(this.poolSize); - } - - for (; i < pipeline.buffers.size() + pipeline.imageDescriptors.size(); ++i) { - VkDescriptorPoolSize textureSamplerPoolSize = poolSizes.get(i); - textureSamplerPoolSize.type(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); - textureSamplerPoolSize.descriptorCount(this.poolSize); - } - - VkDescriptorPoolCreateInfo poolInfo = VkDescriptorPoolCreateInfo.calloc(stack); - poolInfo.sType(VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO); - poolInfo.pPoolSizes(poolSizes); - poolInfo.maxSets(this.poolSize); - - LongBuffer pDescriptorPool = stack.mallocLong(1); - - if (vkCreateDescriptorPool(DEVICE, poolInfo, null, pDescriptorPool) != VK_SUCCESS) { - throw new RuntimeException("Failed to create descriptor pool"); - } - - if (this.descriptorPool != VK_NULL_HANDLE) { - final long oldDescriptorPool = this.descriptorPool; - MemoryManager.getInstance().addFrameOp(() -> { - vkDestroyDescriptorPool(DEVICE, oldDescriptorPool, null); - }); - } - - this.descriptorPool = pDescriptorPool.get(0); - } - - public void resetIdx() { - this.currentIdx = -1; - } - - private void cleanUp() { - vkResetDescriptorPool(DEVICE, descriptorPool, 0); - vkDestroyDescriptorPool(DEVICE, descriptorPool, null); - - MemoryUtil.memFree(this.dynamicOffsets); - } - - } - public static class Builder { - - public static GraphicsPipeline createGraphicsPipeline(VertexFormat format, String path) { - Pipeline.Builder pipelineBuilder = new Pipeline.Builder(format, path); - pipelineBuilder.parseBindingsJSON(); - pipelineBuilder.compileShaders(); - return pipelineBuilder.createGraphicsPipeline(); - } - final VertexFormat vertexFormat; final String shaderPath; List UBOs; @@ -502,6 +271,8 @@ public static GraphicsPipeline createGraphicsPipeline(VertexFormat format, Strin RenderPass renderPass; + Function> uniformSupplierGetter; + public Builder(VertexFormat vertexFormat, String path) { this.vertexFormat = vertexFormat; this.shaderPath = path; @@ -511,10 +282,14 @@ public Builder(VertexFormat vertexFormat) { this(vertexFormat, null); } + public Builder() { + this(null, null); + } + public GraphicsPipeline createGraphicsPipeline() { Validate.isTrue(this.imageDescriptors != null && this.UBOs != null && this.vertShaderSPIRV != null && this.fragShaderSPIRV != null, - "Cannot create Pipeline: resources missing"); + "Cannot create Pipeline: resources missing"); if (this.manualUBO != null) this.UBOs.add(this.manualUBO); @@ -532,34 +307,23 @@ public void setSPIRVs(SPIRV vertShaderSPIRV, SPIRV fragShaderSPIRV) { this.fragShaderSPIRV = fragShaderSPIRV; } - public void compileShaders() { - String resourcePath = SPIRVUtils.class.getResource("/assets/vulkanmod/shaders/").toExternalForm(); - - this.vertShaderSPIRV = compileShaderAbsoluteFile(String.format("%s%s.vsh", resourcePath, this.shaderPath), ShaderKind.VERTEX_SHADER); - this.fragShaderSPIRV = compileShaderAbsoluteFile(String.format("%s%s.fsh", resourcePath, this.shaderPath), ShaderKind.FRAGMENT_SHADER); + public void compileShaders(String name, String vsh, String fsh) { + this.vertShaderSPIRV = SPIRVUtils.compileShader(String.format("%s.vsh", name), vsh, ShaderKind.VERTEX_SHADER); + this.fragShaderSPIRV = SPIRVUtils.compileShader(String.format("%s.fsh", name), fsh, ShaderKind.FRAGMENT_SHADER); } - public void compileShaders(String name, String vsh, String fsh) { - this.vertShaderSPIRV = compileShader(String.format("%s.vsh", name), vsh, ShaderKind.VERTEX_SHADER); - this.fragShaderSPIRV = compileShader(String.format("%s.fsh", name), fsh, ShaderKind.FRAGMENT_SHADER); + public void setVertShaderSPIRV(SPIRV vertShaderSPIRV) { + this.vertShaderSPIRV = vertShaderSPIRV; } - public void parseBindingsJSON() { - Validate.notNull(this.shaderPath, "Cannot parse bindings: shaderPath is null"); + public void setFragShaderSPIRV(SPIRV fragShaderSPIRV) { + this.fragShaderSPIRV = fragShaderSPIRV; + } + public void parseBindings(JsonObject jsonObject) { this.UBOs = new ArrayList<>(); this.imageDescriptors = new ArrayList<>(); - JsonObject jsonObject; - - String resourcePath = String.format("/assets/vulkanmod/shaders/%s.json", this.shaderPath); - InputStream stream = Pipeline.class.getResourceAsStream(resourcePath); - - if (stream == null) - throw new NullPointerException(String.format("Failed to load: %s", resourcePath)); - - jsonObject = GsonHelper.parse(new InputStreamReader(stream, StandardCharsets.UTF_8)); - JsonArray jsonUbos = GsonHelper.getAsJsonArray(jsonObject, "UBOs", null); JsonArray jsonManualUbos = GsonHelper.getAsJsonArray(jsonObject, "ManualUBOs", null); JsonArray jsonSamplers = GsonHelper.getAsJsonArray(jsonObject, "samplers", null); @@ -586,25 +350,56 @@ public void parseBindingsJSON() { } } + public void setUniformSupplierGetter(Function> uniformSupplierGetter) { + this.uniformSupplierGetter = uniformSupplierGetter; + } + private void parseUboNode(JsonElement jsonelement) { - JsonObject jsonobject = GsonHelper.convertToJsonObject(jsonelement, "UBO"); - int binding = GsonHelper.getAsInt(jsonobject, "binding"); - int type = getStageFromString(GsonHelper.getAsString(jsonobject, "type")); - JsonArray fields = GsonHelper.getAsJsonArray(jsonobject, "fields"); + JsonObject uboJson = GsonHelper.convertToJsonObject(jsonelement, "UBO"); + int binding = GsonHelper.getAsInt(uboJson, "binding"); + int type = getStageFromString(GsonHelper.getAsString(uboJson, "type")); - AlignedStruct.Builder builder = new AlignedStruct.Builder(); + UBO ubo; + if (GsonHelper.isArrayNode(uboJson, "fields")) { + JsonArray fields = GsonHelper.getAsJsonArray(uboJson, "fields"); - for (JsonElement jsonelement2 : fields) { - JsonObject jsonobject2 = GsonHelper.convertToJsonObject(jsonelement2, "uniform"); - //need to store some infos - String name = GsonHelper.getAsString(jsonobject2, "name"); - String type2 = GsonHelper.getAsString(jsonobject2, "type"); - int j = GsonHelper.getAsInt(jsonobject2, "count"); + AlignedStruct.Builder builder = new AlignedStruct.Builder(); + + for (JsonElement field : fields) { + JsonObject fieldObject = GsonHelper.convertToJsonObject(field, "uniform"); + String name = GsonHelper.getAsString(fieldObject, "name"); + String type2 = GsonHelper.getAsString(fieldObject, "type"); + int count = GsonHelper.getAsInt(fieldObject, "count"); - builder.addUniformInfo(type2, name, j); + Uniform.Info uniformInfo = Uniform.createUniformInfo(type2, name, count); + uniformInfo.setupSupplier(); + if (!uniformInfo.hasSupplier()) { + if (this.uniformSupplierGetter != null) { + var uniformSupplier = this.uniformSupplierGetter.apply(uniformInfo); + + if (uniformSupplier == null) { + throw new IllegalStateException("No uniform supplier found for uniform: (%s:%s)".formatted(type2, name)); + } + + uniformInfo.setBufferSupplier(uniformSupplier); + } + else { + throw new IllegalStateException("No uniform supplier found for uniform: (%s:%s)".formatted(type2, name)); + } + } + + builder.addUniformInfo(uniformInfo); + } + + ubo = builder.buildUBO(binding, type); + } + else { + int size = GsonHelper.getAsInt(uboJson, "size"); + + ubo = new UBO("UBO %d".formatted(binding), binding, type, size, null); + ubo.setUseGlobalBuffer(false); } - UBO ubo = builder.buildUBO(binding, type); if (binding >= this.nextBinding) this.nextBinding = binding + 1; @@ -637,13 +432,16 @@ private void parsePushConstantNode(JsonArray jsonArray) { AlignedStruct.Builder builder = new AlignedStruct.Builder(); for (JsonElement jsonelement : jsonArray) { - JsonObject jsonobject2 = GsonHelper.convertToJsonObject(jsonelement, "PC"); + JsonObject jsonobject2 = GsonHelper.convertToJsonObject(jsonelement, "PushConstants"); String name = GsonHelper.getAsString(jsonobject2, "name"); String type2 = GsonHelper.getAsString(jsonobject2, "type"); - int j = GsonHelper.getAsInt(jsonobject2, "count"); + int count = GsonHelper.getAsInt(jsonobject2, "count"); + + Uniform.Info uniformInfo = Uniform.createUniformInfo(type2, name, count); + uniformInfo.setupSupplier(); - builder.addUniformInfo(type2, name, j); + builder.addUniformInfo(uniformInfo); } this.pushConstants = builder.buildPushConstant(); diff --git a/src/main/java/net/vulkanmod/vulkan/shader/PipelineState.java b/src/main/java/net/vulkanmod/vulkan/shader/PipelineState.java index af857d070..1c7d0e5cd 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/PipelineState.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/PipelineState.java @@ -1,13 +1,11 @@ package net.vulkanmod.vulkan.shader; -import com.mojang.blaze3d.platform.GlStateManager; -import net.vulkanmod.vulkan.framebuffer.RenderPass; import net.vulkanmod.vulkan.VRenderSystem; +import net.vulkanmod.vulkan.framebuffer.RenderPass; import java.util.Objects; import static org.lwjgl.vulkan.VK10.*; -import static org.lwjgl.vulkan.VK10.VK_COMPARE_OP_EQUAL; public class PipelineState { private static final int DEFAULT_DEPTH_OP = 515; @@ -26,7 +24,7 @@ public static PipelineState getCurrentPipelineState(RenderPass renderPass) { int depthState = getDepthState(); int logicOp = getLogicOpState(); - if(currentState.checkEquals(assemblyRasterState, blendState, depthState, logicOp, currentColorMask, renderPass)) + if (currentState.checkEquals(assemblyRasterState, blendState, depthState, logicOp, currentColorMask, renderPass)) return currentState; else return currentState = new PipelineState(assemblyRasterState, blendState, depthState, logicOp, currentColorMask, renderPass); @@ -69,7 +67,8 @@ public static int getLogicOpState() { int colorMask_i; int logicOp_i; - public PipelineState(int assemblyRasterState, int blendState, int depthState, int logicOp, int colorMask, RenderPass renderPass) { + public PipelineState(int assemblyRasterState, int blendState, int depthState, int logicOp, int colorMask, + RenderPass renderPass) { this.renderPass = renderPass; this.assemblyRasterState = assemblyRasterState; @@ -79,11 +78,12 @@ public PipelineState(int assemblyRasterState, int blendState, int depthState, in this.logicOp_i = logicOp; } - private boolean checkEquals(int assemblyRasterState, int blendState, int depthState, int logicOp, int colorMask, RenderPass renderPass) { + private boolean checkEquals(int assemblyRasterState, int blendState, int depthState, int logicOp, int colorMask, + RenderPass renderPass) { return (blendState == this.blendState_i) && (depthState == this.depthState_i) - && renderPass == this.renderPass && logicOp == this.logicOp_i - && (assemblyRasterState == this.assemblyRasterState) - && colorMask == this.colorMask_i; + && renderPass == this.renderPass && logicOp == this.logicOp_i + && (assemblyRasterState == this.assemblyRasterState) + && colorMask == this.colorMask_i; } @Override @@ -95,9 +95,9 @@ public boolean equals(Object o) { PipelineState that = (PipelineState) o; return (blendState_i == that.blendState_i) && (depthState_i == that.depthState_i) - && this.renderPass == that.renderPass && logicOp_i == that.logicOp_i - && this.assemblyRasterState == that.assemblyRasterState - && this.colorMask_i == that.colorMask_i; + && this.renderPass == that.renderPass && logicOp_i == that.logicOp_i + && this.assemblyRasterState == that.assemblyRasterState + && this.colorMask_i == that.colorMask_i; } @Override @@ -107,7 +107,7 @@ public int hashCode() { public static BlendInfo defaultBlendInfo() { return new BlendInfo(true, VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, - VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD); + VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD); } public static class BlendInfo { @@ -118,7 +118,8 @@ public static class BlendInfo { public int dstAlphaFactor; public int blendOp; - public BlendInfo(boolean enabled, int srcRgbFactor, int dstRgbFactor, int srcAlphaFactor, int dstAlphaFactor, int blendOp) { + public BlendInfo(boolean enabled, int srcRgbFactor, int dstRgbFactor, int srcAlphaFactor, int dstAlphaFactor, + int blendOp) { this.enabled = enabled; this.srcRgbFactor = srcRgbFactor; this.dstRgbFactor = dstRgbFactor; @@ -127,20 +128,6 @@ public BlendInfo(boolean enabled, int srcRgbFactor, int dstRgbFactor, int srcAlp this.blendOp = blendOp; } - public void setBlendFunction(GlStateManager.SourceFactor sourceFactor, GlStateManager.DestFactor destFactor) { - this.srcRgbFactor = glToVulkanBlendFactor(sourceFactor.value); - this.srcAlphaFactor = glToVulkanBlendFactor(sourceFactor.value); - this.dstRgbFactor = glToVulkanBlendFactor(destFactor.value); - this.dstAlphaFactor = glToVulkanBlendFactor(destFactor.value); - } - - public void setBlendFuncSeparate(GlStateManager.SourceFactor srcRgb, GlStateManager.DestFactor dstRgb, GlStateManager.SourceFactor srcAlpha, GlStateManager.DestFactor dstAlpha) { - this.srcRgbFactor = glToVulkanBlendFactor(srcRgb.value); - this.srcAlphaFactor = glToVulkanBlendFactor(srcAlpha.value); - this.dstRgbFactor = glToVulkanBlendFactor(dstRgb.value); - this.dstAlphaFactor = glToVulkanBlendFactor(dstAlpha.value); - } - /* gl to Vulkan conversion */ public void setBlendFunction(int sourceFactor, int destFactor) { this.srcRgbFactor = glToVulkanBlendFactor(sourceFactor); @@ -269,7 +256,7 @@ public static int getDstAlphaFactor(int s) { } public static int blendOp(int state) { - return state >>> FUN_OFFSET; + return decode(state, FUN_OFFSET, OP_MASK); } } @@ -340,9 +327,9 @@ public static abstract class ColorMask { public static int getColorMask(boolean r, boolean g, boolean b, boolean a) { return (r ? VK_COLOR_COMPONENT_R_BIT : 0) - | (g ? VK_COLOR_COMPONENT_G_BIT : 0) - | (b ? VK_COLOR_COMPONENT_B_BIT : 0) - | (a ? VK_COLOR_COMPONENT_A_BIT : 0); + | (g ? VK_COLOR_COMPONENT_G_BIT : 0) + | (b ? VK_COLOR_COMPONENT_B_BIT : 0) + | (a ? VK_COLOR_COMPONENT_A_BIT : 0); } } diff --git a/src/main/java/net/vulkanmod/vulkan/shader/SPIRVUtils.java b/src/main/java/net/vulkanmod/vulkan/shader/SPIRVUtils.java index f1d8001e6..6e4c72f66 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/SPIRVUtils.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/SPIRVUtils.java @@ -2,7 +2,6 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.lwjgl.system.MemoryStack; -import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.NativeResource; import org.lwjgl.util.shaderc.ShadercIncludeResolveI; import org.lwjgl.util.shaderc.ShadercIncludeResult; @@ -10,7 +9,6 @@ import org.lwjgl.vulkan.VK12; import java.io.IOException; -import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; @@ -24,8 +22,8 @@ import static org.lwjgl.util.shaderc.Shaderc.*; public class SPIRVUtils { - private static final boolean DEBUG = false; - private static final boolean OPTIMIZATIONS = true; + private static final boolean DEBUG = true; + private static final boolean OPTIMIZATIONS = false; private static long compiler; private static long options; @@ -37,8 +35,6 @@ public class SPIRVUtils { private static ObjectArrayList includePaths; - private static float time = 0.0f; - static { initCompiler(); } @@ -46,23 +42,23 @@ public class SPIRVUtils { private static void initCompiler() { compiler = shaderc_compiler_initialize(); - if(compiler == NULL) { + if (compiler == NULL) { throw new RuntimeException("Failed to create shader compiler"); } options = shaderc_compile_options_initialize(); - if(options == NULL) { + if (options == NULL) { throw new RuntimeException("Failed to create compiler options"); } - if(OPTIMIZATIONS) + if (OPTIMIZATIONS) shaderc_compile_options_set_optimization_level(options, shaderc_optimization_level_performance); - if(DEBUG) + if (DEBUG) shaderc_compile_options_set_generate_debug_info(options); - shaderc_compile_options_set_target_env(options, shaderc_env_version_vulkan_1_2, VK12.VK_API_VERSION_1_2); + shaderc_compile_options_set_target_env(options, shaderc_env_version_vulkan_1_1, VK12.VK_API_VERSION_1_1); shaderc_compile_options_set_include_callbacks(options, SHADER_INCLUDER, SHADER_RELEASER, pUserData); includePaths = new ObjectArrayList<>(); @@ -72,52 +68,29 @@ private static void initCompiler() { public static void addIncludePath(String path) { URL url = SPIRVUtils.class.getResource(path); - if(url != null) + if (url != null) includePaths.add(url.toExternalForm()); } - public static SPIRV compileShaderAbsoluteFile(String shaderFile, ShaderKind shaderKind) { - try { - String source = new String(Files.readAllBytes(Paths.get(new URI(shaderFile)))); - return compileShader(shaderFile, source, shaderKind); - } catch (IOException | URISyntaxException e) { - e.printStackTrace(); - } - return null; - } - public static SPIRV compileShader(String filename, String source, ShaderKind shaderKind) { - long startTime = System.nanoTime(); + if (source == null) { + throw new NullPointerException("source for %s.%s is null".formatted(filename, shaderKind)); + } long result = shaderc_compile_into_spv(compiler, source, shaderKind.kind, filename, "main", options); - if(result == NULL) { + if (result == NULL) { throw new RuntimeException("Failed to compile shader " + filename + " into SPIR-V"); } - if(shaderc_result_get_compilation_status(result) != shaderc_compilation_status_success) { - throw new RuntimeException("Failed to compile shader " + filename + " into SPIR-V:\n" + shaderc_result_get_error_message(result)); + if (shaderc_result_get_compilation_status(result) != shaderc_compilation_status_success) { + String errorMessage = shaderc_result_get_error_message(result); + throw new RuntimeException("Failed to compile shader %s into SPIR-V:\n\t%s".formatted(filename, errorMessage)); } - time += (System.nanoTime() - startTime) / 1000000.0f; - return new SPIRV(result, shaderc_result_get_bytes(result)); } - private static SPIRV readFromStream(InputStream inputStream) { - try { - byte[] bytes = inputStream.readAllBytes(); - ByteBuffer buffer = MemoryUtil.memAlloc(bytes.length); - buffer.put(bytes); - buffer.position(0); - - return new SPIRV(MemoryUtil.memAddress(buffer), buffer); - } catch (Exception e) { - e.printStackTrace(); - } - throw new RuntimeException("unable to read inputStream"); - } - public enum ShaderKind { VERTEX_SHADER(shaderc_glsl_vertex_shader), GEOMETRY_SHADER(shaderc_glsl_geometry_shader), @@ -140,19 +113,19 @@ public long invoke(long user_data, long requested_source, int type, long request var requesting = memASCII(requesting_source); var requested = memASCII(requested_source); - try(MemoryStack stack = MemoryStack.stackPush()) { + try (MemoryStack stack = MemoryStack.stackPush()) { Path path; - for(String includePath : includePaths) { + for (String includePath : includePaths) { path = Paths.get(new URI(String.format("%s%s", includePath, requested))); - if(Files.exists(path)) { + if (Files.exists(path)) { byte[] bytes = Files.readAllBytes(path); return ShadercIncludeResult.malloc(stack) - .source_name(stack.ASCII(requested)) - .content(stack.bytes(bytes)) - .user_data(user_data).address(); + .source_name(stack.ASCII(requested)) + .content(stack.bytes(bytes)) + .user_data(user_data).address(); } } } catch (IOException | URISyntaxException e) { diff --git a/src/main/java/net/vulkanmod/vulkan/shader/Uniforms.java b/src/main/java/net/vulkanmod/vulkan/shader/Uniforms.java index e233046d7..e7e81619d 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/Uniforms.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/Uniforms.java @@ -3,6 +3,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap; import net.vulkanmod.vulkan.VRenderSystem; +import net.vulkanmod.vulkan.shader.layout.Uniform; import net.vulkanmod.vulkan.util.MappedBuffer; import java.util.function.Supplier; @@ -28,14 +29,17 @@ public static void setupDefaultUniforms() { //Vec1i vec1i_uniformMap.put("EndPortalLayers", () -> 15); - vec1i_uniformMap.put("FogShape", () -> RenderSystem.getShaderFogShape().getIndex()); //Vec1 - vec1f_uniformMap.put("FogStart", RenderSystem::getShaderFogStart); - vec1f_uniformMap.put("FogEnd", RenderSystem::getShaderFogEnd); + vec1f_uniformMap.put("FogStart", () -> VRenderSystem.getFogData().renderDistanceStart); + vec1f_uniformMap.put("FogEnd", () -> VRenderSystem.getFogData().renderDistanceEnd); + vec1f_uniformMap.put("FogEnvironmentalStart", () -> VRenderSystem.getFogData().environmentalStart); + vec1f_uniformMap.put("FogEnvironmentalEnd", () -> VRenderSystem.getFogData().environmentalEnd); + vec1f_uniformMap.put("FogRenderDistanceStart", () -> VRenderSystem.getFogData().renderDistanceStart); + vec1f_uniformMap.put("FogRenderDistanceEnd", () -> VRenderSystem.getFogData().renderDistanceEnd); + vec1f_uniformMap.put("FogSkyEnd", () -> VRenderSystem.getFogData().skyEnd); + vec1f_uniformMap.put("FogCloudsEnd", () -> VRenderSystem.getFogData().cloudEnd); vec1f_uniformMap.put("LineWidth", RenderSystem::getShaderLineWidth); - vec1f_uniformMap.put("GameTime", RenderSystem::getShaderGameTime); - vec1f_uniformMap.put("GlintAlpha", RenderSystem::getShaderGlintAlpha); vec1f_uniformMap.put("AlphaCutout", () -> VRenderSystem.alphaCutout); //Vec2 @@ -44,11 +48,23 @@ public static void setupDefaultUniforms() { //Vec3 vec3f_uniformMap.put("Light0_Direction", () -> VRenderSystem.lightDirection0); vec3f_uniformMap.put("Light1_Direction", () -> VRenderSystem.lightDirection1); - vec3f_uniformMap.put("ChunkOffset", () -> VRenderSystem.ChunkOffset); + vec3f_uniformMap.put("ModelOffset", () -> VRenderSystem.modelOffset); + vec3f_uniformMap.put("ChunkOffset", () -> VRenderSystem.modelOffset); //Vec4 vec4f_uniformMap.put("ColorModulator", VRenderSystem::getShaderColor); vec4f_uniformMap.put("FogColor", VRenderSystem::getShaderFogColor); } + + public static Supplier getUniformSupplier(String type, String name) { + return switch (type) { + case "mat4" -> Uniforms.mat4f_uniformMap.get(name); + case "vec4" -> Uniforms.vec4f_uniformMap.get(name); + case "vec3" -> Uniforms.vec3f_uniformMap.get(name); + case "vec2" -> Uniforms.vec2f_uniformMap.get(name); + + default -> null; + }; + } } diff --git a/src/main/java/net/vulkanmod/vulkan/shader/converter/Attribute.java b/src/main/java/net/vulkanmod/vulkan/shader/converter/Attribute.java new file mode 100644 index 000000000..4bce3fb51 --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/shader/converter/Attribute.java @@ -0,0 +1,29 @@ +package net.vulkanmod.vulkan.shader.converter; + +public class Attribute { + + String ioType; + String type; + String id; + int location; + + public Attribute(String ioType, String type, String id) { + switch (ioType) { + case "in", "out" -> {} + default -> throw new IllegalArgumentException(); + } + + this.ioType = ioType; + this.type = type; + this.id = id; + } + + public void setLocation(int location) { + this.location = location; + } + + public GLSLParser.Node getNode() { + return new GLSLParser.Node("attribute", "layout(location = %d) %s %s %s;\n".formatted(location, ioType, type, id)); + } + +} diff --git a/src/main/java/net/vulkanmod/vulkan/shader/converter/GLSLParser.java b/src/main/java/net/vulkanmod/vulkan/shader/converter/GLSLParser.java new file mode 100644 index 000000000..49c5b592c --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/shader/converter/GLSLParser.java @@ -0,0 +1,531 @@ +package net.vulkanmod.vulkan.shader.converter; + +import com.mojang.blaze3d.vertex.VertexFormat; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.vulkanmod.Initializer; +import net.vulkanmod.vulkan.shader.descriptor.ImageDescriptor; +import net.vulkanmod.vulkan.shader.descriptor.UBO; +import net.vulkanmod.vulkan.shader.layout.AlignedStruct; +import net.vulkanmod.vulkan.shader.layout.Uniform; +import net.vulkanmod.vulkan.texture.VTextureSelector; +import org.lwjgl.vulkan.VK11; + +import java.util.*; + +/** + * Simple parser used to convert GLSL shader code to make it Vulkan compatible + */ +public class GLSLParser { + private Lexer lexer; + private List tokens; + private int currentTokenIdx; + private Token currentToken; + + private Stage stage; + State state = State.DEFAULT; + + LinkedList vsStream = new LinkedList<>(); + LinkedList fsStream = new LinkedList<>(); + + int currentUniformLocation = 0; + List uniformBlocks = new ArrayList<>(); + Map uniformBlockMap = new HashMap<>(); + List samplers = new ArrayList<>(); + Map samplerMap = new HashMap<>(); + + VertexFormat vertexFormat; + int currentInAtt = 0, currentOutAtt = 0; + ArrayList vertInAttributes = new ArrayList<>(); + ArrayList vertOutAttributes = new ArrayList<>(); + ArrayList fragInAttributes = new ArrayList<>(); + ArrayList fragOutAttributes = new ArrayList<>(); + + public GLSLParser() {} + + public void setVertexFormat(VertexFormat vertexFormat) { + this.vertexFormat = vertexFormat; + } + + public void parse(Lexer lexer, Stage stage) { + this.stage = stage; + this.lexer = lexer; + this.tokens = this.lexer.tokenize(); + this.currentTokenIdx = 0; + + this.currentInAtt = 0; + this.currentOutAtt = 0; + + nextToken(); + + // Parse version + if (currentToken.type != Token.TokenType.PREPROCESSOR && !currentToken.value.startsWith("#version")) { + throw new IllegalStateException("First glsl line must contain version"); + } + appendToken(new Token(Token.TokenType.PREPROCESSOR, "#version 450\n")); + nextToken(); + + + while (currentToken.type != Token.TokenType.EOF) { + switch (currentToken.type) { + case PREPROCESSOR -> parsePreprocessor(); + + case IDENTIFIER -> { + switch (currentToken.value) { + case "layout" -> parseUniformBlock(); + case "uniform" -> parseUniform(); + case "in", "out" -> parseAttribute(); + default -> appendToken(currentToken); + } + } + + case OPERATOR -> { + // TODO: need to parse expressions to replace % operator + appendToken(currentToken); + } + + default -> appendToken(currentToken); + } + + nextToken(); + } + } + + private void parsePreprocessor() { + if (!currentToken.value.startsWith("#line")) { + appendToken(currentToken); + } + } + + private void parseUniform() { + nextToken(true); + + if (currentToken.type != Token.TokenType.IDENTIFIER) { + throw new IllegalStateException(); + } + + switch (currentToken.value) { + case "sampler2D" -> parseSampler(Sampler.Type.SAMPLER_2D); + case "samplerCube" -> parseSampler(Sampler.Type.SAMPLER_CUBE); + case "isamplerBuffer" -> parseSampler(Sampler.Type.I_SAMPLER_BUFFER); + + default -> throw new IllegalStateException("Unrecognized value: %s".formatted(currentToken.value)); + } + // TODO: parse uniform + } + + private void parseSampler(Sampler.Type type) { + nextToken(true); + + if (currentToken.type != Token.TokenType.IDENTIFIER) { + throw new IllegalStateException(); + } + + String name = currentToken.value; + + nextToken(true); + if (currentToken.type != Token.TokenType.SEMICOLON) { + throw new IllegalStateException(); + } + + Token next = this.tokens.get(currentTokenIdx); + if (next.type == Token.TokenType.SPACING) { + if (Objects.equals(next.value, "\n")) { + currentTokenIdx++; + } + else { + int i = next.value.indexOf("\n"); + if (i >= 0) { + next.value = next.value.substring(i + 1); + } + } + } + + Sampler sampler = new Sampler(type, name); + + if (samplerMap.get(name) != null) { + sampler = samplerMap.get(name); + } + else { + sampler.setBinding(currentUniformLocation++); + this.samplerMap.put(name, sampler); + this.samplers.add(sampler); + } + + appendNode(sampler.getNode()); + } + + private void parseUniformBlock() { + this.state = State.LAYOUT; + + nextToken(true); + + if (currentToken.type != Token.TokenType.LEFT_PARENTHESIS) { + throw new IllegalStateException(); + } + + do { + nextToken(true); + } while (currentToken.type != Token.TokenType.RIGHT_PARENTHESIS); + + nextToken(true); + + if (!Objects.equals(this.currentToken.value, "uniform")) { + throw new IllegalStateException(); + } + + nextToken(true); + String name = currentToken.value; + + UniformBlock ub = new UniformBlock(name); + + nextToken(true); + if (currentToken.type != Token.TokenType.LEFT_BRACE) { + throw new IllegalStateException(); + } + + nextToken(true); + + // Recognize fields + while (currentToken.type != Token.TokenType.RIGHT_BRACE) { + if (currentToken.type != Token.TokenType.IDENTIFIER) { + throw new IllegalStateException(); + } + String fieldType = this.currentToken.value; + + nextToken(true); + if (currentToken.type != Token.TokenType.IDENTIFIER) { + throw new IllegalStateException(); + } + String fieldName = this.currentToken.value; + + nextToken(true); + if (currentToken.type != Token.TokenType.SEMICOLON) { + throw new IllegalStateException(); + } + + // Add field + ub.addField(new UniformBlock.Field(fieldType, fieldName)); + + nextToken(true); + } + + nextToken(true); + + switch (currentToken.type) { + case SEMICOLON -> {} + + case IDENTIFIER -> { + ub.setAlias(currentToken.value); + + nextToken(true); + if (currentToken.type != Token.TokenType.SEMICOLON) { + throw new IllegalStateException(); + } + } + + default -> throw new IllegalStateException(); + } + + Token next = this.tokens.get(currentTokenIdx); + if (next.type == Token.TokenType.SPACING) { + if (Objects.equals(next.value, "\n")) { + currentTokenIdx++; + } + else { + int i = next.value.indexOf("\n"); + if (i >= 0) { + next.value = next.value.substring(i + 1); + } + } + } + + if (uniformBlockMap.get(ub.name) != null) { + ub = uniformBlockMap.get(ub.name); + } + else { + ub.setBinding(this.currentUniformLocation++); + this.uniformBlockMap.put(ub.name, ub); + this.uniformBlocks.add(ub); + } + + appendNode(ub.getNode()); + } + + private void parseAttribute() { + this.state = State.ATTRIBUTE; + + Token prevToken = this.prevToken(true); + + // Check if we are at the beginning of a statement + if (prevToken != null && prevToken.type != Token.TokenType.SPACING && + prevToken.type != Token.TokenType.SEMICOLON && prevToken.type != Token.TokenType.RIGHT_BRACE && + !(prevToken.type == Token.TokenType.IDENTIFIER && Objects.equals(prevToken.value, "flat"))) + { + return; + } + + String ioType = this.currentToken.value; + + nextToken(true); + if (currentToken.type != Token.TokenType.IDENTIFIER) { + throw new IllegalStateException(); + } + String type = this.currentToken.value; + + nextToken(true); + if (currentToken.type != Token.TokenType.IDENTIFIER) { + throw new IllegalStateException(); + } + String id = this.currentToken.value; + + nextToken(true); + if (currentToken.type != Token.TokenType.SEMICOLON) { + throw new IllegalStateException(); + } + + Token next = this.tokens.get(currentTokenIdx); + if (next.type == Token.TokenType.SPACING) { + if (Objects.equals(next.value, "\n")) { + currentTokenIdx++; + } + else { + int i = next.value.indexOf("\n"); + if (i >= 0) { + next.value = next.value.substring(i + 1); + } + } + } + + Attribute attribute = new Attribute(ioType, type, id); + + switch (this.stage) { + case VERTEX -> { + switch (attribute.ioType) { + case "in" -> { + int attributeLocation; + if (this.vertexFormat != null) { + var attributeNames = this.vertexFormat.getElementAttributeNames(); + attributeLocation = attributeNames.indexOf(attribute.id); + + if (attributeLocation == -1) { + Initializer.LOGGER.error("Element %s not found in elements %s".formatted(attribute.id, attributeNames)); + attributeLocation = currentInAtt; + } + + currentInAtt++; + } else { + attributeLocation = currentInAtt++; + } + + attribute.setLocation(attributeLocation); + vertInAttributes.add(attribute); + } + case "out" -> { + attribute.setLocation(currentOutAtt++); + vertOutAttributes.add(attribute); + } + default -> throw new IllegalStateException(); + } + } + case FRAGMENT -> { + switch (attribute.ioType) { + case "in" -> { + // Find matching vertex out attribute + final var vertAttribute = getVertAttribute(attribute); + + if (vertAttribute != null) { + attribute.setLocation(vertAttribute.location); + fragInAttributes.add(attribute); + } + else { + return; + } + } + case "out" -> { + if (currentOutAtt > 0) { + throw new UnsupportedOperationException("Multiple outputs not currently supported."); + } + + attribute.setLocation(currentOutAtt++); + fragOutAttributes.add(attribute); + } + default -> throw new IllegalStateException(); + } + } + } + + this.appendNode(attribute.getNode()); + } + + private Attribute getVertAttribute(Attribute attribute) { + Attribute vertAttribute = null; + for (var attribute1 : vertOutAttributes) { + if (Objects.equals(attribute1.id, attribute.id)) { + vertAttribute = attribute1; + } + } + + if (vertAttribute == null) { +// throw new IllegalStateException("No match found for attribute %s in vertex attribute outputs.".formatted(attribute.id)); + } + return vertAttribute; + } + + private void nextToken() { + nextToken(false); + } + + private void nextToken(boolean skipSpace) { + this.currentToken = this.tokens.get(this.currentTokenIdx++); + + while (skipSpace && this.currentToken.type == Token.TokenType.SPACING) { + this.currentToken = this.tokens.get(this.currentTokenIdx++); + } + } + + private Token prevToken(boolean skipSpace) { + int tokenIdx = this.currentTokenIdx - 1; + Token token; + + if (tokenIdx == 0) { + return null; + } + + tokenIdx--; + token = this.tokens.get(tokenIdx); + + while (skipSpace && tokenIdx != 0 && + (token.type == Token.TokenType.SPACING || token.type == Token.TokenType.PREPROCESSOR || token.type == Token.TokenType.COMMENT)) + { + tokenIdx--; + token = this.tokens.get(tokenIdx); + } + + if (skipSpace && (token.type == Token.TokenType.SPACING || token.type == Token.TokenType.COMMENT || token.type == Token.TokenType.PREPROCESSOR)) { + return null; + } + + return token; + } + + private void appendToken(Token token) { + this.appendNode(Node.fromToken(token)); + } + + private void appendNode(Node node) { + this.getNodeStream().add(node); + } + + private LinkedList getNodeStream() { + return switch (this.stage) { + case VERTEX -> this.vsStream; + case FRAGMENT -> this.fsStream; + }; + } + + public String getOutput(Stage stage) { + StringBuilder stringBuilder = new StringBuilder(); + + var stream = switch (stage) { + case VERTEX -> this.vsStream; + case FRAGMENT -> this.fsStream; + }; + + // Version + Node node = stream.getFirst(); + stringBuilder.append(node.value); + stringBuilder.append("\n"); + + switch (stage) { + case VERTEX -> { + stringBuilder.append("#define gl_VertexID gl_VertexIndex\n\n"); + } + } + + // Rename glsl reserved keywords + stringBuilder.append("#define sampler sampler1\n\n"); + stringBuilder.append("#define sample sample1\n\n"); + + for (int i = 1; i < stream.size(); i++) { + node = stream.get(i); + stringBuilder.append(node.value); + } + + return stringBuilder.toString(); + } + + public UBO[] createUBOs() { + if (this.uniformBlockMap.isEmpty()) { + return new UBO[0]; + } + + int uboCount = this.uniformBlockMap.size(); + UBO[] ubos = new UBO[uboCount]; + + int i = 0; + for (var uniformBlock : this.uniformBlocks) { + AlignedStruct.Builder builder = new AlignedStruct.Builder(); + + for (var field : uniformBlock.fields) { + String name = field.name; + String type = field.type; + + Uniform.Info uniformInfo = Uniform.createUniformInfo(type, name); + + builder.addUniformInfo(uniformInfo); + } + + ubos[i] = builder.buildUBO(uniformBlock.name, uniformBlock.binding, VK11.VK_SHADER_STAGE_ALL); + ++i; + } + + return ubos; + } + + public List getSamplerList() { + List imageDescriptors = new ObjectArrayList<>(); + + int imageIdx = 0; + for (Sampler sampler : this.samplers) { + + int descriptorType = switch (sampler.type) { + case SAMPLER_2D, SAMPLER_CUBE -> VK11.VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + case I_SAMPLER_BUFFER -> VK11.VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + }; + + imageDescriptors.add(new ImageDescriptor(sampler.binding, "sampler2D", sampler.id, imageIdx, descriptorType)); + imageIdx++; + } + + return imageDescriptors; + } + + enum State { + LAYOUT, + UNIFORM, + UNIFORM_BLOCK, + ATTRIBUTE, + DEFAULT + } + + public enum Stage { + VERTEX, + FRAGMENT + } + + public static class Node { + String type; + String value; + + public Node(String type, String value) { + this.type = type; + this.value = value; + } + + public static Node fromToken(Token token) { + return new Node("token:%s".formatted(token.type), token.value); + } + } +} + + diff --git a/src/main/java/net/vulkanmod/vulkan/shader/converter/Lexer.java b/src/main/java/net/vulkanmod/vulkan/shader/converter/Lexer.java new file mode 100644 index 000000000..1a443e726 --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/shader/converter/Lexer.java @@ -0,0 +1,283 @@ +package net.vulkanmod.vulkan.shader.converter; + +import java.util.ArrayList; +import java.util.List; + +public class Lexer { + private final String input; + private int currentPosition; + private char currentChar; + + private State state; + + public Lexer(String input) { + this.input = input; + this.currentPosition = 0; + this.currentChar = !input.isEmpty() ? input.charAt(0) : '\0'; + } + + private void advance() { + advance(1); + } + + private void advance(int i) { + for (int j = 0; j < i; j++) { + currentPosition++; + if (currentPosition >= input.length()) { + currentChar = '\0'; + break; + } else { + currentChar = input.charAt(currentPosition); + } + } + } + + private char peek() { + int peekPosition = currentPosition + 1; + if (peekPosition < input.length()) { + return input.charAt(peekPosition); + } + return '\0'; + } + + public List tokenize() { + List tokens = new ArrayList<>(); + + while (currentPosition < input.length()) { + char currentChar = input.charAt(currentPosition); + + Token token = nextToken(); + if (token != null) { + tokens.add(token); + } else { + throw new RuntimeException("Unknown character: " + currentChar); + } + } + + tokens.add(new Token(Token.TokenType.EOF, null)); + + return tokens; + } + + public Token nextToken() { + if (!checkEOF()) { + return new Token(Token.TokenType.EOF, null); + } + + // Comment + if (currentChar == '/') { + switch (peek()) { + case '/' -> { + return this.lineComment(); + } + case '*' -> { + return this.multiLineComment(); + } + } + } + + // Handle multi-character operators + switch (currentChar) { + case '=': + if (peek() == '=') { + advance(2); + return new Token(Token.TokenType.OPERATOR, "=="); + } + break; + case '!': + if (peek() == '=') { + advance(2); + return new Token(Token.TokenType.OPERATOR, "!="); + } + break; + case '<': + switch (peek()) { + case '=' -> { + advance(2); + return new Token(Token.TokenType.OPERATOR, "<="); + } + case '<' -> { + advance(2); + return new Token(Token.TokenType.OPERATOR, "<<"); + } + } + break; + case '>': + switch (peek()) { + case '=' -> { + advance(2); + return new Token(Token.TokenType.OPERATOR, ">="); + } + case '>' -> { + advance(2); + return new Token(Token.TokenType.OPERATOR, ">>"); + } + } + break; + } + + Token token = switch (currentChar) { + case '{' -> new Token(Token.TokenType.LEFT_BRACE, "{"); + case '}' -> new Token(Token.TokenType.RIGHT_BRACE, "}"); + case '(' -> new Token(Token.TokenType.LEFT_PARENTHESIS, "("); + case ')' -> new Token(Token.TokenType.RIGHT_PARENTHESIS, ")"); + case ':' -> new Token(Token.TokenType.COLON, ":"); + case ';' -> new Token(Token.TokenType.SEMICOLON, ";"); + case '.' -> new Token(Token.TokenType.DOT, "."); + case ',' -> new Token(Token.TokenType.COMMA, ","); + + case '=' -> new Token(Token.TokenType.OPERATOR, "="); + case '+' -> new Token(Token.TokenType.OPERATOR, "+"); + case '-' -> new Token(Token.TokenType.OPERATOR, "-"); + case '*' -> new Token(Token.TokenType.OPERATOR, "*"); + case '/' -> new Token(Token.TokenType.OPERATOR, "/"); + case '%' -> new Token(Token.TokenType.OPERATOR, "%"); + case '<' -> new Token(Token.TokenType.OPERATOR, "<"); + case '>' -> new Token(Token.TokenType.OPERATOR, ">"); + case '!' -> new Token(Token.TokenType.OPERATOR, "!"); + case '&' -> new Token(Token.TokenType.OPERATOR, "&"); + case '|' -> new Token(Token.TokenType.OPERATOR, "|"); + case '^' -> new Token(Token.TokenType.OPERATOR, "^"); + case '?' -> new Token(Token.TokenType.OPERATOR, "?"); + case '[' -> new Token(Token.TokenType.OPERATOR, "["); + case ']' -> new Token(Token.TokenType.OPERATOR, "]"); + + case '#' -> { + StringBuilder sb = new StringBuilder(); + + while (checkEOF() && currentChar != '\n') { + sb.append(currentChar); + advance(); + } + sb.append('\n'); + + String value = sb.toString(); + yield new Token(Token.TokenType.PREPROCESSOR, value); + } + + case '\"' -> string(); + + default -> null; + }; + + if (token == null) { + if (Character.isJavaIdentifierStart(currentChar)) { + return identifier(); + } + + if (Character.isDigit(currentChar)) { + return literal(); + } + + if (Character.isWhitespace(currentChar)) { + return spacing(); + } + } + + if (token == null) { + throw new IllegalStateException("Unrecognized char: " + currentChar); + } + + advance(); + + return token; + } + + private Token lineComment() { + StringBuilder sb = new StringBuilder(); + sb.append("//"); + this.advance(2); + + while (checkEOF() && currentChar != '\n') { + sb.append(currentChar); + advance(); + } + sb.append(currentChar); + advance(); + + String value = sb.toString(); + return new Token(Token.TokenType.COMMENT, value); + } + + private Token multiLineComment() { + StringBuilder sb = new StringBuilder(); + sb.append("/*"); + this.advance(2); + + while (checkEOF() && currentChar != '*' && this.peek() != '/') { + sb.append(currentChar); + advance(); + } + sb.append(currentChar); + advance(); + sb.append(currentChar); + advance(); + + String value = sb.toString(); + return new Token(Token.TokenType.COMMENT, value); + } + + private Token identifier() { + StringBuilder sb = new StringBuilder(); + while (checkEOF() && Character.isJavaIdentifierPart(currentChar)) { + sb.append(currentChar); + advance(); + } + String value = sb.toString(); + return new Token(Token.TokenType.IDENTIFIER, value); + } + + private Token literal() { + StringBuilder sb = new StringBuilder(); + while (Character.isDigit(currentChar)) { + sb.append(currentChar); + advance(); + } + + if (currentChar == '.') { + sb.append(currentChar); + advance(); + } + + while (Character.isDigit(currentChar)) { + sb.append(currentChar); + advance(); + } + + String value = sb.toString(); + return new Token(Token.TokenType.LITERAL, value); + } + + private Token string() { + StringBuilder sb = new StringBuilder(); + while (checkEOF() && currentChar != '\"') { + sb.append(currentChar); + advance(); + } + sb.append(currentChar); + advance(); + + String value = sb.toString(); + return new Token(Token.TokenType.COMMENT, value); + } + + private Token spacing() { + StringBuilder sb = new StringBuilder(); + while (currentChar != '\0' && Character.isWhitespace(currentChar)) { + sb.append(currentChar); + advance(); + } + String value = sb.toString(); + return new Token(Token.TokenType.SPACING, value); + } + + private boolean checkEOF() { + return currentChar != '\0'; + } + + enum State { + UNIFORM_BLOCK, + CODE, + DEFAULT + } +} diff --git a/src/main/java/net/vulkanmod/vulkan/shader/converter/Sampler.java b/src/main/java/net/vulkanmod/vulkan/shader/converter/Sampler.java new file mode 100644 index 000000000..e54ea5d2e --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/shader/converter/Sampler.java @@ -0,0 +1,32 @@ +package net.vulkanmod.vulkan.shader.converter; + +public class Sampler { + final Type type; + final String id; + int binding; + + public Sampler(Type type, String id) { + this.type = type; + this.id = id; + } + + public void setBinding(int binding) { + this.binding = binding; + } + + public GLSLParser.Node getNode() { + return new GLSLParser.Node("sampler", "layout(binding = %d) uniform %s %s;\n".formatted(binding, type.name, id)); + } + + public enum Type { + SAMPLER_2D("sampler2D"), + SAMPLER_CUBE("samplerCube"), + I_SAMPLER_BUFFER("isamplerBuffer"); + + public final String name; + + Type(String name) { + this.name = name; + } + } +} diff --git a/src/main/java/net/vulkanmod/vulkan/shader/converter/Token.java b/src/main/java/net/vulkanmod/vulkan/shader/converter/Token.java new file mode 100644 index 000000000..560f9df07 --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/shader/converter/Token.java @@ -0,0 +1,49 @@ +package net.vulkanmod.vulkan.shader.converter; + +public class Token { + + public enum TokenType { + PREPROCESSOR, + KEYWORD, + IDENTIFIER, + LITERAL, + OPERATOR, + PUNCTUATION, + SPACING, + COMMENT, + + // Symbols + LEFT_BRACE, // { + RIGHT_BRACE, // } + LEFT_PARENTHESIS, // ( + RIGHT_PARENTHESIS, // ) + COLON, // : + SEMICOLON, // ; + DOT, // . + COMMA, // , + + // Data Types + TYPE, + + // GLSL + LAYOUT, + + EOF + } + + public final TokenType type; + public String value; + + public Token(TokenType type, String value) { + this.type = type; + this.value = value; + } + + @Override + public String toString() { + return "Token{" + + "type=" + type + + ", value='" + value + '\'' + + '}'; + } +} diff --git a/src/main/java/net/vulkanmod/vulkan/shader/converter/UniformBlock.java b/src/main/java/net/vulkanmod/vulkan/shader/converter/UniformBlock.java new file mode 100644 index 000000000..26ef62a57 --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/shader/converter/UniformBlock.java @@ -0,0 +1,61 @@ +package net.vulkanmod.vulkan.shader.converter; + +import java.util.ArrayList; +import java.util.List; + +public class UniformBlock { + int binding; + String name; + String alias; + List fields = new ArrayList<>(); + + public UniformBlock(String name) { + this.name = name; + } + + public void addField(Field field) { + this.fields.add(field); + } + + public void setBinding(int binding) { + this.binding = binding; + } + + public void setAlias(String alias) { + this.alias = alias; + } + + public GLSLParser.Node getNode() { + StringBuilder sb = new StringBuilder(); + + sb.append("layout(binding = %d) uniform %s {\n".formatted(binding, name)); + + for (int i = 0, fieldsSize = fields.size(); i < fieldsSize; i++) { + Field field = fields.get(i); + sb.append("\t%s %s;".formatted(field.type, field.name)); + + if (i < fieldsSize - 1) { + sb.append("\n"); + } + } + + sb.append("\n}"); + + if (this.alias != null) { + sb.append(" %s ".formatted(this.alias)); + } + + sb.append(";\n"); + + return new GLSLParser.Node("uniform_block", sb.toString()); + } + + public static class Field { + final String type, name; + + public Field(String type, String name) { + this.type = type; + this.name = name; + } + } +} diff --git a/src/main/java/net/vulkanmod/vulkan/shader/descriptor/ImageDescriptor.java b/src/main/java/net/vulkanmod/vulkan/shader/descriptor/ImageDescriptor.java index 40ad7b070..0354402ac 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/descriptor/ImageDescriptor.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/descriptor/ImageDescriptor.java @@ -13,7 +13,6 @@ public class ImageDescriptor implements Descriptor { public final String name; public final int imageIdx; - public final boolean isStorageImage; public boolean useSampler; public boolean isReadOnlyLayout; private int layout; @@ -24,14 +23,23 @@ public ImageDescriptor(int binding, String type, String name, int imageIdx) { } public ImageDescriptor(int binding, String type, String name, int imageIdx, boolean isStorageImage) { + this(binding, type, name, imageIdx, isStorageImage ? VK_DESCRIPTOR_TYPE_STORAGE_IMAGE : VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); + } + + public ImageDescriptor(int binding, String type, String name, int imageIdx, int descriptorType) { this.binding = binding; this.qualifier = type; this.name = name; - this.isStorageImage = isStorageImage; - this.useSampler = !isStorageImage; this.imageIdx = imageIdx; - descriptorType = isStorageImage ? VK_DESCRIPTOR_TYPE_STORAGE_IMAGE : VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + if (this.imageIdx == -1) { + throw new IllegalArgumentException(); + } + + this.descriptorType = descriptorType; + + boolean isStorageImage = isStorageImage(); + this.useSampler = !isStorageImage; setLayout(isStorageImage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); } @@ -74,7 +82,7 @@ public VulkanImage getImage() { public long getImageView(VulkanImage image) { long view; - if(mipLevel == -1) + if (mipLevel == -1) view = image.getImageView(); else view = image.getLevelImageView(mipLevel); @@ -82,6 +90,10 @@ public long getImageView(VulkanImage image) { return view; } + public boolean isStorageImage() { + return this.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + } + public static class State { long imageView, sampler; diff --git a/src/main/java/net/vulkanmod/vulkan/shader/descriptor/ManualUBO.java b/src/main/java/net/vulkanmod/vulkan/shader/descriptor/ManualUBO.java index 83db956f6..09ed1e259 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/descriptor/ManualUBO.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/descriptor/ManualUBO.java @@ -10,7 +10,7 @@ public class ManualUBO extends UBO { private boolean update = true; public ManualUBO(int binding, int type, int size) { - super(binding, type, size * 4, null); + super("manual UBO: %d".formatted(binding), binding, type, size * 4, null); } @Override diff --git a/src/main/java/net/vulkanmod/vulkan/shader/descriptor/UBO.java b/src/main/java/net/vulkanmod/vulkan/shader/descriptor/UBO.java index 4614285fe..1229f1ada 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/descriptor/UBO.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/descriptor/UBO.java @@ -1,6 +1,6 @@ package net.vulkanmod.vulkan.shader.descriptor; -import net.vulkanmod.vulkan.memory.UniformBuffer; +import net.vulkanmod.vulkan.memory.buffer.BufferSlice; import net.vulkanmod.vulkan.shader.layout.AlignedStruct; import net.vulkanmod.vulkan.shader.layout.Uniform; @@ -9,15 +9,30 @@ import static org.lwjgl.vulkan.VK10.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; public class UBO extends AlignedStruct implements Descriptor { - private final int binding; - private final int stages; + public final String name; + public final int binding; + public final int stages; + public final BufferSlice bufferSlice; + private boolean useGlobalBuffer; + private boolean update; - private UniformBuffer uniformBuffer; - - public UBO(int binding, int stages, int size, List infoList) { + public UBO(String name, int binding, int stages, int size, List infoList) { super(infoList, size); + this.name = name; this.binding = binding; this.stages = stages; + this.update = true; + + this.bufferSlice = new BufferSlice(); + } + + @Override + public String toString() { + return "UBO{" + + "name='" + name + '\'' + + ", binding=" + binding + + ", useGlobalBuffer=" + useGlobalBuffer + + '}'; } public int getBinding() { @@ -33,11 +48,23 @@ public int getStages() { return stages; } - public UniformBuffer getUniformBuffer() { - return uniformBuffer; + public BufferSlice getBufferSlice() { + return bufferSlice; + } + + public boolean useGlobalBuffer() { + return useGlobalBuffer; + } + + public void setUseGlobalBuffer(boolean useGlobalBuffer) { + this.useGlobalBuffer = useGlobalBuffer; + } + + public boolean shouldUpdate() { + return update; } - public void setUniformBuffer(UniformBuffer uniformBuffer) { - this.uniformBuffer = uniformBuffer; + public void setUpdate(boolean update) { + this.update = update; } } diff --git a/src/main/java/net/vulkanmod/vulkan/shader/layout/AlignedStruct.java b/src/main/java/net/vulkanmod/vulkan/shader/layout/AlignedStruct.java index 89c015da5..3236f70f8 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/layout/AlignedStruct.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/layout/AlignedStruct.java @@ -11,20 +11,23 @@ public abstract class AlignedStruct { protected int size; protected AlignedStruct(List infoList, int size) { + if (size <= 0) { + throw new IllegalArgumentException("Struct size cannot be <= 0"); + } + this.size = size; - if(infoList == null) + if (infoList == null) return; - for(Uniform.Info info : infoList) { - + for (Uniform.Info info : infoList) { Uniform uniform = Uniform.createField(info); this.uniforms.add(uniform); } } public void update(long ptr) { - for(Uniform uniform : this.uniforms) { + for (Uniform uniform : this.uniforms) { uniform.update(ptr); } } @@ -39,33 +42,40 @@ public int getSize() { public static class Builder { - final List uniformsInfo = new ArrayList<>(); + final List uniforms = new ArrayList<>(); protected int currentOffset = 0; public void addUniformInfo(String type, String name, int count) { Uniform.Info info = Uniform.createUniformInfo(type, name, count); - - this.currentOffset = info.computeAlignmentOffset(this.currentOffset); - this.currentOffset += info.size; - this.uniformsInfo.add(info); + addUniformInfo(info); } public void addUniformInfo(String type, String name) { Uniform.Info info = Uniform.createUniformInfo(type, name); + addUniformInfo(info); + } - this.currentOffset = info.computeAlignmentOffset(this.currentOffset); - this.currentOffset += info.size; - this.uniformsInfo.add(info); + public void addUniformInfo(Uniform.Info uniformInfo) { + this.currentOffset = uniformInfo.computeAlignmentOffset(this.currentOffset); + this.currentOffset += uniformInfo.size; + this.uniforms.add(uniformInfo); } public UBO buildUBO(int binding, int stages) { + return this.buildUBO("UBO: %d".formatted(binding), binding, stages); + } + + public UBO buildUBO(String name, int binding, int stages) { //offset is expressed in floats/ints - return new UBO(binding, stages, this.currentOffset * 4, this.uniformsInfo); + return new UBO(name, binding, stages, this.currentOffset * 4, this.uniforms); } public PushConstants buildPushConstant() { - if(this.uniformsInfo.isEmpty()) return null; - return new PushConstants(this.uniformsInfo, this.currentOffset * 4); + if (this.uniforms.isEmpty()) { + return null; + } + + return new PushConstants(this.uniforms, this.currentOffset * 4); } } diff --git a/src/main/java/net/vulkanmod/vulkan/shader/layout/Uniform.java b/src/main/java/net/vulkanmod/vulkan/shader/layout/Uniform.java index c0f07797c..6feaf1dbe 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/layout/Uniform.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/layout/Uniform.java @@ -17,18 +17,12 @@ public class Uniform { this.info = info; this.offset = info.offset * 4L; this.size = info.size * 4; - this.setSupplier(); - } - void setSupplier() { - this.values = switch (info.type) { - case "mat4" -> Uniforms.mat4f_uniformMap.get(info.name); - case "vec4" -> Uniforms.vec4f_uniformMap.get(info.name); - case "vec3" -> Uniforms.vec3f_uniformMap.get(info.name); - case "vec2" -> Uniforms.vec2f_uniformMap.get(info.name); + this.setupSupplier(); + } - default -> null; - }; + protected void setupSupplier() { + this.values = this.info.bufferSupplier; } public void setSupplier(Supplier supplier) { @@ -40,6 +34,10 @@ public String getName() { } void update(long ptr) { + if (this.values == null) { + return; + } + MappedBuffer src = values.get(); MemoryUtil.memCopy(src.ptr, ptr + this.offset, this.size); @@ -47,7 +45,7 @@ void update(long ptr) { public static Uniform createField(Info info) { return switch (info.type) { - case "mat4", "vec3", "vec4", "vec2" -> new Uniform(info); + case "mat4", "vec3", "vec4", "vec2", "ivec3", "ivec2" -> new Uniform(info); case "mat3" -> new Mat3(info); case "float" -> new Vec1f(info); case "int" -> new Vec1i(info); @@ -61,11 +59,14 @@ public int getOffset() { public int getSize() { return info.size; } + public Info getInfo() { + return info; + } + public String toString() { return String.format("%s: %s offset: %d", info.type, info.name, info.offset); } - //TODO public static Info createUniformInfo(String type, String name, int count) { return switch (type) { case "matrix4x4" -> new Info("mat4", name, 4, 16); @@ -77,7 +78,14 @@ public static Info createUniformInfo(String type, String name, int count) { default -> throw new IllegalStateException("Unexpected value: " + count); }; - case "int" -> new Info("int", name, 1, 1); + case "int" -> switch (count) { + case 4 -> new Info("ivec4", name, 4, 4); + case 3 -> new Info("ivec3", name, 4, 3); + case 2 -> new Info("ivec2", name, 2, 2); + case 1 -> new Info("int", name, 1, 1); + + default -> throw new IllegalStateException("Unexpected value: " + count); + }; default -> throw new RuntimeException("not admitted type.."); }; } @@ -88,8 +96,8 @@ public static Info createUniformInfo(String type, String name) { case "mat3" -> new Info(type, name, 4, 9); case "vec4" -> new Info(type, name, 4, 4); - case "vec3" -> new Info(type, name, 4, 3); - case "vec2" -> new Info(type, name, 2, 2); + case "vec3", "ivec3" -> new Info(type, name, 4, 3); + case "vec2", "ivec2" -> new Info(type, name, 2, 2); case "float", "int" -> new Info(type, name, 1, 1); @@ -98,12 +106,16 @@ public static Info createUniformInfo(String type, String name) { } public static class Info { - final String type; - final String name; - final int align; - final int size; + public final String type; + public final String name; + public final int align; + public final int size; int offset; + Supplier bufferSupplier; + Supplier intSupplier; + Supplier floatSupplier; + Info(String type, String name, int align, int size) { this.type = type; this.name = name; @@ -116,5 +128,26 @@ public static class Info { int computeAlignmentOffset(int builderOffset) { return this.offset = builderOffset + ((align - (builderOffset % align)) % align); } + + public void setupSupplier() { + switch (this.type) { + case "float" -> this.floatSupplier = Uniforms.vec1f_uniformMap.get(this.name); + case "int" -> this.intSupplier = Uniforms.vec1i_uniformMap.get(this.name); + default -> this.bufferSupplier = Uniforms.getUniformSupplier(this.type, this.name); + } + } + + public boolean hasSupplier() { + return switch (this.type) { + case "float" -> this.floatSupplier != null || this.bufferSupplier != null; + case "int" -> this.intSupplier != null || this.bufferSupplier != null; + default -> this.bufferSupplier != null; + }; + } + + public void setBufferSupplier(Supplier supplier) { + this.bufferSupplier = supplier; + } + } } diff --git a/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec1f.java b/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec1f.java index 4e9a2084c..484861490 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec1f.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec1f.java @@ -1,8 +1,6 @@ package net.vulkanmod.vulkan.shader.layout; -import net.vulkanmod.vulkan.shader.Uniforms; import net.vulkanmod.vulkan.util.MappedBuffer; -import org.apache.commons.lang3.Validate; import org.lwjgl.system.MemoryUtil; import java.util.function.Supplier; @@ -14,8 +12,12 @@ public Vec1f(Info info) { super(info); } - void setSupplier() { - this.floatSupplier = Uniforms.vec1f_uniformMap.get(this.info.name); + protected void setupSupplier() { + if (this.info.floatSupplier != null) { + this.floatSupplier = this.info.floatSupplier; + } else { + this.setSupplier(this.info.bufferSupplier); + } } @Override diff --git a/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec1i.java b/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec1i.java index 995076cb2..700fd00bf 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec1i.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec1i.java @@ -14,8 +14,12 @@ public Vec1i(Info info) { super(info); } - void setSupplier() { - this.intSupplier = Uniforms.vec1i_uniformMap.get(this.info.name); + protected void setupSupplier() { + if (this.info.intSupplier != null) { + this.intSupplier = this.info.intSupplier; + } else { + this.setSupplier(this.info.bufferSupplier); + } } @Override diff --git a/src/main/java/net/vulkanmod/vulkan/shader/parser/CodeParser.java b/src/main/java/net/vulkanmod/vulkan/shader/parser/CodeParser.java deleted file mode 100644 index b6f95f752..000000000 --- a/src/main/java/net/vulkanmod/vulkan/shader/parser/CodeParser.java +++ /dev/null @@ -1,82 +0,0 @@ -package net.vulkanmod.vulkan.shader.parser; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - -import java.util.LinkedList; -import java.util.List; -import java.util.StringTokenizer; - -public abstract class CodeParser { - - /* TODO: this is not a proper parser, it just serves the purpose of converting glsl shaders - to solve some simple and common compatibility issues. - Implementing an AST would be a better solution. - */ - public static String parseCodeLine(String line) { - LinkedList tokens = new LinkedList<>(); - StringTokenizer tokenizer = new StringTokenizer(line, " \t\n\r\f,(){}%", true); - - String delims = " \t\n\r\f"; - - String token; - while (tokenizer.hasMoreTokens()) { - token = tokenizer.nextToken(); - - if (!delims.contains(token)) - tokens.add(token); - } - - List processed = new ObjectArrayList<>(); - boolean changed = false; - - int i = 0; - while (i < tokens.size()) { - token = tokens.get(i); - - if (token.equals("%")) { - processed.removeLast(); - - String prevToken = tokens.get(i - 1); - String nextToken = tokens.get(i + 1); - - prevToken = checkTokenMapping(prevToken); - nextToken = checkTokenMapping(nextToken); - - String newToken = "mod(%s, %s)".formatted(prevToken, nextToken); - processed.add(newToken); - - changed = true; - - i += 2; - continue; - } - - String remappedToken = checkTokenMapping(token); - - if (!remappedToken.equals(token)) - changed = true; - - processed.add(remappedToken + " "); - i++; - } - - if (changed) { - StringBuilder stringBuilder = new StringBuilder(); - - for (String s : processed) { - stringBuilder.append(s); - } - - return stringBuilder.toString(); - } else { - return line; - } - } - - private static String checkTokenMapping(String token) { - return switch (token) { - case "gl_VertexID" -> "gl_VertexIndex"; - default -> token; - }; - } -} diff --git a/src/main/java/net/vulkanmod/vulkan/shader/parser/GlslConverter.java b/src/main/java/net/vulkanmod/vulkan/shader/parser/GlslConverter.java deleted file mode 100644 index f934a5def..000000000 --- a/src/main/java/net/vulkanmod/vulkan/shader/parser/GlslConverter.java +++ /dev/null @@ -1,163 +0,0 @@ -package net.vulkanmod.vulkan.shader.parser; - -import net.vulkanmod.vulkan.shader.descriptor.ImageDescriptor; -import net.vulkanmod.vulkan.shader.descriptor.UBO; - -import java.util.*; - -public class GlslConverter { - - ShaderStage shaderStage; - private State state; - - private UniformParser uniformParser; - private InputOutputParser inOutParser; - - private String vshConverted; - private String fshConverted; - - public void process(String vertShader, String fragShader) { - this.uniformParser = new UniformParser(this); - this.inOutParser = new InputOutputParser(this); - - StringBuilder vshOut = new StringBuilder(); - StringBuilder fshOut = new StringBuilder(); - - this.setShaderStage(ShaderStage.Vertex); - - String[] lines = vertShader.split("\n"); - - var iterator = Arrays.stream(lines).iterator(); - - while (iterator.hasNext()) { - String line = iterator.next(); - - String parsedLine = this.parseLine(line); - if (parsedLine != null) { - vshOut.append(parsedLine); - vshOut.append("\n"); - } - - } - - vshOut.insert(0, this.inOutParser.createInOutCode()); - - this.setShaderStage(ShaderStage.Fragment); - - lines = fragShader.split("\n"); - - iterator = Arrays.stream(lines).iterator(); - - while (iterator.hasNext()) { - String line = iterator.next(); - - String parsedLine = this.parseLine(line); - if (parsedLine != null) { - fshOut.append(parsedLine); - fshOut.append("\n"); - } - } - - fshOut.insert(0, this.inOutParser.createInOutCode()); - - String uniformBlock = this.uniformParser.createUniformsCode(); - vshOut.insert(0, uniformBlock); - fshOut.insert(0, uniformBlock); - - String samplersVertCode = this.uniformParser.createSamplersCode(ShaderStage.Vertex); - String samplersFragCode = this.uniformParser.createSamplersCode(ShaderStage.Fragment); - - vshOut.insert(0, samplersVertCode); - fshOut.insert(0, samplersFragCode); - - vshOut.insert(0, "#version 450\n\n"); - fshOut.insert(0, "#version 450\n\n"); - - this.vshConverted = vshOut.toString(); - this.fshConverted = fshOut.toString(); - - } - - private String parseLine(String line) { - - StringTokenizer tokenizer = new StringTokenizer(line); - - // empty line - if (!tokenizer.hasMoreTokens()) - return "\n"; - - String token = tokenizer.nextToken(); - - switch (token) { - case "uniform" -> this.state = State.MATCHING_UNIFORM; - case "in", "out" -> this.state = State.MATCHING_IN_OUT; - case "#version" -> { - return null; - } - case "#moj_import" -> { - if (tokenizer.countTokens() != 1) { - throw new IllegalArgumentException("Token count != 1"); - } - - return String.format("#include %s", tokenizer.nextToken()); - } - - default -> { - return CodeParser.parseCodeLine(line); - } - } - - if (tokenizer.countTokens() < 2) { - throw new IllegalArgumentException("Less than 3 tokens present"); - } - - feedToken(token); - - while (tokenizer.hasMoreTokens()) { - token = tokenizer.nextToken(); - - feedToken(token); - } - - return null; - } - - private void feedToken(String token) { - switch (this.state) { - case MATCHING_UNIFORM -> this.uniformParser.parseToken(token); - case MATCHING_IN_OUT -> this.inOutParser.parseToken(token); - } - } - - private void setShaderStage(ShaderStage shaderStage) { - this.shaderStage = shaderStage; - this.uniformParser.setCurrentUniforms(this.shaderStage); - this.inOutParser.setShaderStage(this.shaderStage); - } - - public UBO getUBO() { - return this.uniformParser.getUbo(); - } - - public List getSamplerList() { - return this.uniformParser.getSamplers(); - } - - public String getVshConverted() { - return vshConverted; - } - - public String getFshConverted() { - return fshConverted; - } - - enum ShaderStage { - Vertex, - Fragment - } - - enum State { - MATCHING_UNIFORM, - MATCHING_IN_OUT - } -} diff --git a/src/main/java/net/vulkanmod/vulkan/shader/parser/InputOutputParser.java b/src/main/java/net/vulkanmod/vulkan/shader/parser/InputOutputParser.java deleted file mode 100644 index aa8c5c0fe..000000000 --- a/src/main/java/net/vulkanmod/vulkan/shader/parser/InputOutputParser.java +++ /dev/null @@ -1,120 +0,0 @@ -package net.vulkanmod.vulkan.shader.parser; - -import com.mojang.blaze3d.vertex.VertexFormat; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - -import java.util.List; -import java.util.Objects; - -import static net.vulkanmod.vulkan.shader.parser.UniformParser.removeSemicolon; - -public class InputOutputParser { - private final GlslConverter converterInstance; - private VertexFormat vertexFormat; - - private final AttributeSet vertInAttributes = new AttributeSet(); - private final AttributeSet vertOutAttributes = new AttributeSet(); - - private GlslConverter.ShaderStage shaderStage; - - private int currentLocation = 0; - private String ioType; - private String type; - private String name; - - public InputOutputParser(GlslConverter converterInstance) { - this.converterInstance = converterInstance; - } - - public boolean parseToken(String token) { - - if (this.ioType == null) - this.ioType = token; - else if (this.type == null) - this.type = token; - else if (this.name == null) { - token = removeSemicolon(token); - - this.name = token; - - if(this.shaderStage == GlslConverter.ShaderStage.Vertex) { - switch (this.ioType) { - case "in" -> this.vertInAttributes.add(this.type, this.name); - case "out" -> this.vertOutAttributes.add(this.type, this.name); - } - } - else { - switch (this.ioType) { - case "in" -> { - if(!this.vertOutAttributes.contains(this.type, this.name)) - throw new RuntimeException("fragment in attribute does not match vertex output"); - } - case "out" -> { - //TODO check output - } - } - } - this.resetState(); - return true; - } - - return false; - } - - private void resetState() { - this.ioType = null; - this.type = null; - this.name = null; - } - - public String createInOutCode() { - //TODO - StringBuilder builder = new StringBuilder(); - - if(this.shaderStage == GlslConverter.ShaderStage.Vertex) { - //In - for(Attribute attribute : this.vertInAttributes.attributes) { - builder.append(String.format("layout(location = %d) in %s %s;\n", attribute.location, attribute.type, attribute.name)); - } - builder.append("\n"); - - //Out - for(Attribute attribute : this.vertOutAttributes.attributes) { - builder.append(String.format("layout(location = %d) out %s %s;\n", attribute.location, attribute.type, attribute.name)); - } - builder.append("\n"); - } - else { - //In - for(Attribute attribute : this.vertOutAttributes.attributes) { - builder.append(String.format("layout(location = %d) in %s %s;\n", attribute.location, attribute.type, attribute.name)); - } - builder.append("\n"); - - //TODO multi attachments? - builder.append(String.format("layout(location = 0) out vec4 fragColor;\n\n")); - } - - return builder.toString(); - } - - public void setShaderStage(GlslConverter.ShaderStage shaderStage) { - this.shaderStage = shaderStage; - } - - public record Attribute(int location, String type, String name) {} - - static class AttributeSet { - List attributes = new ObjectArrayList<>(); - int currentLocation = 0; - - void add(String type, String name) { - this.attributes.add(new Attribute(this.currentLocation, type, name)); - this.currentLocation++; - } - - boolean contains(String type, String name) { - return this.attributes.stream().anyMatch(attribute -> Objects.equals(attribute.name, name) && Objects.equals(attribute.type, type)); - } - } -} diff --git a/src/main/java/net/vulkanmod/vulkan/shader/parser/UniformParser.java b/src/main/java/net/vulkanmod/vulkan/shader/parser/UniformParser.java deleted file mode 100644 index cc5087ce0..000000000 --- a/src/main/java/net/vulkanmod/vulkan/shader/parser/UniformParser.java +++ /dev/null @@ -1,153 +0,0 @@ -package net.vulkanmod.vulkan.shader.parser; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import net.vulkanmod.vulkan.shader.Pipeline; -import net.vulkanmod.vulkan.shader.descriptor.ImageDescriptor; -import net.vulkanmod.vulkan.shader.layout.AlignedStruct; -import net.vulkanmod.vulkan.shader.descriptor.UBO; - -import java.util.ArrayList; -import java.util.List; - -public class UniformParser { - - private final GlslConverter converterInstance; - private final StageUniforms[] stageUniforms = new StageUniforms[GlslConverter.ShaderStage.values().length]; - private StageUniforms currentUniforms; - List globalUniforms = new ArrayList<>(); - - private String type; - private String name; - - private UBO ubo; - private List imageDescriptors; - - public UniformParser(GlslConverter converterInstance) { - this.converterInstance = converterInstance; - - for(int i = 0; i < this.stageUniforms.length; ++i) { - this.stageUniforms[i] = new StageUniforms(); - } - } - - public boolean parseToken(String token) { - if(token.matches("uniform")) return false; - - if (this.type == null) { - this.type = token; - - } - else if (this.name == null) { - token = removeSemicolon(token); - - this.name = token; - - //TODO check if already present - Uniform uniform = new Uniform(this.type, this.name); - if ("sampler2D".equals(this.type)) { - if (!this.currentUniforms.samplers.contains(uniform)) - this.currentUniforms.samplers.add(uniform); - } else { - if (!this.globalUniforms.contains(uniform)) - this.globalUniforms.add(uniform); - } - - this.resetSate(); - return true; - } - - return false; - } - - public void setCurrentUniforms(GlslConverter.ShaderStage shaderStage) { - this.currentUniforms = stageUniforms[shaderStage.ordinal()]; - } - - private void resetSate() { - this.type = null; - this.name = null; -// this.state = State.None; - } - - public String createUniformsCode() { - StringBuilder builder = new StringBuilder(); - - this.ubo = this.createUBO(); - - //hardcoded 0 binding as it should always be 0 in this case - builder.append(String.format("layout(binding = %d) uniform UniformBufferObject {\n", 0)); - for(Uniform uniform : this.globalUniforms) { - builder.append(String.format("%s %s;\n", uniform.type, uniform.name)); - } - builder.append("};\n\n"); - - return builder.toString(); - } - - public String createSamplersCode(GlslConverter.ShaderStage shaderStage) { - StringBuilder builder = new StringBuilder(); - - this.imageDescriptors = createSamplerList(); - - for(ImageDescriptor imageDescriptor : this.imageDescriptors) { - builder.append(String.format("layout(binding = %d) uniform %s %s;\n", imageDescriptor.getBinding(), imageDescriptor.qualifier, imageDescriptor.name)); - } - builder.append("\n"); - - return builder.toString(); - } - - private UBO createUBO() { - AlignedStruct.Builder builder = new AlignedStruct.Builder(); - - for(Uniform uniform : this.globalUniforms) { - builder.addUniformInfo(uniform.type, uniform.name); - } - - //hardcoded 0 binding as it should always be 0 in this case - return builder.buildUBO(0, Pipeline.Builder.getStageFromString("all")); - } - - private List createSamplerList() { - int currentLocation = 1; - - List imageDescriptors = new ObjectArrayList<>(); - - for(StageUniforms stageUniforms : this.stageUniforms) { - for(Uniform uniform : stageUniforms.samplers) { - int imageIdx = currentLocation - 1; - imageDescriptors.add(new ImageDescriptor(currentLocation, uniform.type, uniform.name, imageIdx)); - currentLocation++; - } - } - - return imageDescriptors; - } - - public static String removeSemicolon(String s) { - int last = s.length() - 1; - if((s.charAt(last)) != ';' ) - throw new IllegalArgumentException("last char is not ;"); - return s.substring(0, last); - } - - public UBO getUbo() { - return this.ubo; - } - - public List getSamplers() { - return this.imageDescriptors; - } - - public record Uniform(String type, String name) {} - - private static class StageUniforms { - List samplers = new ArrayList<>(); - } - - enum State { - Uniform, - Sampler, - None - } -} diff --git a/src/main/java/net/vulkanmod/vulkan/texture/ImageUtil.java b/src/main/java/net/vulkanmod/vulkan/texture/ImageUtil.java index 151969d06..84a5665bc 100644 --- a/src/main/java/net/vulkanmod/vulkan/texture/ImageUtil.java +++ b/src/main/java/net/vulkanmod/vulkan/texture/ImageUtil.java @@ -1,7 +1,9 @@ package net.vulkanmod.vulkan.texture; +import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.device.DeviceManager; import net.vulkanmod.vulkan.memory.MemoryManager; +import net.vulkanmod.vulkan.memory.buffer.Buffer; import net.vulkanmod.vulkan.queue.CommandPool; import net.vulkanmod.vulkan.util.VUtil; import org.lwjgl.PointerBuffer; @@ -15,23 +17,22 @@ public abstract class ImageUtil { - public static void copyBufferToImageCmd(VkCommandBuffer commandBuffer, long buffer, long image, int mipLevel, int width, int height, int xOffset, int yOffset, int bufferOffset, int bufferRowLenght, int bufferImageHeight) { - - try (MemoryStack stack = stackPush()) { - - VkBufferImageCopy.Buffer region = VkBufferImageCopy.calloc(1, stack); - region.bufferOffset(bufferOffset); - region.bufferRowLength(bufferRowLenght); // Tightly packed - region.bufferImageHeight(bufferImageHeight); // Tightly packed - region.imageSubresource().aspectMask(VK_IMAGE_ASPECT_COLOR_BIT); - region.imageSubresource().mipLevel(mipLevel); - region.imageSubresource().baseArrayLayer(0); - region.imageSubresource().layerCount(1); - region.imageOffset().set(xOffset, yOffset, 0); - region.imageExtent(VkExtent3D.calloc(stack).set(width, height, 1)); - - vkCmdCopyBufferToImage(commandBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, region); - } + public static void copyBufferToImageCmd(MemoryStack stack, VkCommandBuffer commandBuffer, long buffer, + long image, int arrayLayer, + int mipLevel, int width, int height, int xOffset, int yOffset, + int bufferOffset, int bufferRowLenght, int bufferImageHeight) { + VkBufferImageCopy.Buffer region = VkBufferImageCopy.calloc(1, stack); + region.bufferOffset(bufferOffset); + region.bufferRowLength(bufferRowLenght); + region.bufferImageHeight(bufferImageHeight); + region.imageSubresource().aspectMask(VK_IMAGE_ASPECT_COLOR_BIT); + region.imageSubresource().mipLevel(mipLevel); + region.imageSubresource().baseArrayLayer(arrayLayer); + region.imageSubresource().layerCount(1); + region.imageOffset().set(xOffset, yOffset, 0); + region.imageExtent(VkExtent3D.calloc(stack).set(width, height, 1)); + + vkCmdCopyBufferToImage(commandBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, region); } public static void downloadTexture(VulkanImage image, long ptr) { @@ -44,41 +45,93 @@ public static void downloadTexture(VulkanImage image, long ptr) { LongBuffer pStagingBuffer = stack.mallocLong(1); PointerBuffer pStagingAllocation = stack.pointers(0L); - MemoryManager.getInstance().createBuffer(imageSize, - VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - pStagingBuffer, - pStagingAllocation); + MemoryManager.getInstance().createBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + pStagingBuffer, pStagingAllocation); - copyImageToBuffer(commandBuffer.getHandle(), pStagingBuffer.get(0), image.getId(), 0, image.width, image.height, 0, 0, 0, 0, 0); + copyImageToBufferCmd(stack, commandBuffer.getHandle(), pStagingBuffer.get(0), image.getId(), 0, image.width, + image.height, 0, 0, 0, 0, 0); image.transitionImageLayout(stack, commandBuffer.getHandle(), prevLayout); long fence = DeviceManager.getGraphicsQueue().submitCommands(commandBuffer); vkWaitForFences(DeviceManager.vkDevice, fence, true, VUtil.UINT64_MAX); MemoryManager.MapAndCopy(pStagingAllocation.get(0), - (data) -> VUtil.memcpy(data.getByteBuffer(0, (int) imageSize), ptr) - ); + (data) -> VUtil.memcpy(data.getByteBuffer(0, (int) imageSize), ptr)); MemoryManager.freeBuffer(pStagingBuffer.get(0), pStagingAllocation.get(0)); } } - public static void copyImageToBuffer(VkCommandBuffer commandBuffer, long buffer, long image, int mipLevel, int width, int height, int xOffset, int yOffset, int bufferOffset, int bufferRowLenght, int bufferImageHeight) { + public static void copyImageToBuffer(VulkanImage image, Buffer buffer, int mipLevel, + int width, int height, int xOffset, int yOffset, + int bufferOffset, int bufferRowLength, int bufferImageHeight) { try (MemoryStack stack = stackPush()) { + int prevLayout = image.getCurrentLayout(); + CommandPool.CommandBuffer commandBuffer = DeviceManager.getGraphicsQueue().beginCommands(); + image.transitionImageLayout(stack, commandBuffer.getHandle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + copyImageToBufferCmd(stack, commandBuffer.getHandle(), buffer.getId(), image.getId(), mipLevel, width, + height, xOffset, yOffset, bufferOffset, bufferRowLength, bufferImageHeight); + image.transitionImageLayout(stack, commandBuffer.getHandle(), prevLayout); + + long fence = DeviceManager.getGraphicsQueue().submitCommands(commandBuffer); + vkWaitForFences(DeviceManager.vkDevice, fence, true, VUtil.UINT64_MAX); + } + } + + public static void copyImageToBufferCmd(MemoryStack stack, VkCommandBuffer commandBuffer, long buffer, long image, + int mipLevel, int width, int height, int xOffset, int yOffset, int bufferOffset, + int bufferRowLength, int bufferImageHeight) { + VkBufferImageCopy.Buffer region = VkBufferImageCopy.calloc(1, stack); + region.bufferOffset(bufferOffset); + region.bufferRowLength(bufferRowLength); + region.bufferImageHeight(bufferImageHeight); + region.imageSubresource().aspectMask(VK_IMAGE_ASPECT_COLOR_BIT); + region.imageSubresource().mipLevel(mipLevel); + region.imageSubresource().baseArrayLayer(0); + region.imageSubresource().layerCount(1); + region.imageOffset().set(xOffset, yOffset, 0); + region.imageExtent().set(width, height, 1); + + vkCmdCopyImageToBuffer(commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, region); + } + + public static void blitFramebuffer(VulkanImage dstImage, int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1) { + try (MemoryStack stack = stackPush()) { + + VkCommandBuffer commandBuffer = Renderer.getCommandBuffer(); + + Renderer.getInstance().endRenderPass(commandBuffer); + + dstImage.transitionImageLayout(stack, commandBuffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + // TODO: hardcoded srcImage + VulkanImage srcImage = Renderer.getInstance().getSwapChain().getColorAttachment(); + + srcImage.transitionImageLayout(stack, commandBuffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + VkImageBlit.Buffer blit = VkImageBlit.calloc(1, stack); + blit.srcOffsets(0, VkOffset3D.calloc(stack).set(0, 0, 0)); + blit.srcOffsets(1, VkOffset3D.calloc(stack).set(srcImage.width, srcImage.height, 1)); + blit.srcSubresource() + .aspectMask(VK_IMAGE_ASPECT_COLOR_BIT) + .mipLevel(0) + .baseArrayLayer(0) + .layerCount(1); + + blit.dstOffsets(0, VkOffset3D.calloc(stack).set(0, 0, 0)); + blit.dstOffsets(1, VkOffset3D.calloc(stack).set(dstImage.width, dstImage.height, 1)); + blit.dstSubresource().aspectMask(VK_IMAGE_ASPECT_COLOR_BIT).mipLevel(0).baseArrayLayer(0) + .layerCount(1); + + vkCmdBlitImage(commandBuffer, srcImage.getId(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + dstImage.getId(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, blit, VK_FILTER_LINEAR); + + dstImage.transitionImageLayout(stack, commandBuffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + Renderer.getInstance().getMainPass().rebindMainTarget(); - VkBufferImageCopy.Buffer region = VkBufferImageCopy.calloc(1, stack); - region.bufferOffset(bufferOffset); - region.bufferRowLength(bufferRowLenght); // Tightly packed - region.bufferImageHeight(bufferImageHeight); // Tightly packed - region.imageSubresource().aspectMask(VK_IMAGE_ASPECT_COLOR_BIT); - region.imageSubresource().mipLevel(mipLevel); - region.imageSubresource().baseArrayLayer(0); - region.imageSubresource().layerCount(1); - region.imageOffset().set(xOffset, yOffset, 0); - region.imageExtent().set(width, height, 1); - - vkCmdCopyImageToBuffer(commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, region); } } @@ -112,12 +165,8 @@ public static void generateMipmaps(VulkanImage image) { barrier.srcAccessMask(VK_ACCESS_TRANSFER_WRITE_BIT); barrier.dstAccessMask(VK_ACCESS_TRANSFER_READ_BIT); - vkCmdPipelineBarrier(commandBuffer.getHandle(), - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, - null, - null, - barrier); + vkCmdPipelineBarrier(commandBuffer.getHandle(), VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, null, null, barrier); prevLevel = level - 1; @@ -125,24 +174,18 @@ public static void generateMipmaps(VulkanImage image) { blit.srcOffsets(0, VkOffset3D.calloc(stack).set(0, 0, 0)); blit.srcOffsets(1, VkOffset3D.calloc(stack).set(image.width >> prevLevel, image.height >> prevLevel, 1)); blit.srcSubresource() - .aspectMask(VK_IMAGE_ASPECT_COLOR_BIT) - .mipLevel(prevLevel) - .baseArrayLayer(0) - .layerCount(1); + .aspectMask(VK_IMAGE_ASPECT_COLOR_BIT) + .mipLevel(prevLevel) + .baseArrayLayer(0) + .layerCount(1); blit.dstOffsets(0, VkOffset3D.calloc(stack).set(0, 0, 0)); blit.dstOffsets(1, VkOffset3D.calloc(stack).set(image.width >> level, image.height >> level, 1)); - blit.dstSubresource() - .aspectMask(VK_IMAGE_ASPECT_COLOR_BIT) - .mipLevel(level) - .baseArrayLayer(0) - .layerCount(1); - - vkCmdBlitImage(commandBuffer.getHandle(), - image.getId(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - image.getId(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - blit, - VK_FILTER_LINEAR); + blit.dstSubresource().aspectMask(VK_IMAGE_ASPECT_COLOR_BIT).mipLevel(level).baseArrayLayer(0) + .layerCount(1); + + vkCmdBlitImage(commandBuffer.getHandle(), image.getId(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + image.getId(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, blit, VK_FILTER_LINEAR); } @@ -165,22 +208,20 @@ public static void generateMipmaps(VulkanImage image) { barrier.dstAccessMask(VK_ACCESS_SHADER_READ_BIT); vkCmdPipelineBarrier(commandBuffer.getHandle(), - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, - null, - null, - barrier); + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + 0, + null, null, + barrier); barrier.oldLayout(VK_IMAGE_USAGE_TRANSFER_DST_BIT); barrier.subresourceRange().baseMipLevel(image.mipLevels - 1); barrier.subresourceRange().levelCount(1); vkCmdPipelineBarrier(commandBuffer.getHandle(), - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, - null, - null, - barrier); + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + 0, + null, null, + barrier); image.setCurrentLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); diff --git a/src/main/java/net/vulkanmod/vulkan/texture/SamplerManager.java b/src/main/java/net/vulkanmod/vulkan/texture/SamplerManager.java index f58fb4255..2698f6229 100644 --- a/src/main/java/net/vulkanmod/vulkan/texture/SamplerManager.java +++ b/src/main/java/net/vulkanmod/vulkan/texture/SamplerManager.java @@ -1,9 +1,8 @@ package net.vulkanmod.vulkan.texture; -import it.unimi.dsi.fastutil.shorts.Short2LongMap; -import it.unimi.dsi.fastutil.shorts.Short2LongOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2LongMap; +import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import net.vulkanmod.vulkan.device.DeviceManager; -import org.apache.commons.lang3.Validate; import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.VkSamplerCreateInfo; import org.lwjgl.vulkan.VkSamplerReductionModeCreateInfo; @@ -13,81 +12,86 @@ import static net.vulkanmod.vulkan.Vulkan.getVkDevice; import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.*; -import static org.lwjgl.vulkan.VK12.VK_SAMPLER_REDUCTION_MODE_MAX; -import static org.lwjgl.vulkan.VK12.VK_SAMPLER_REDUCTION_MODE_MIN; public abstract class SamplerManager { + public static final int ADDRESS_MODE_BITS = 2; + public static final int REDUCTION_MODE_BITS = 2; + + public static final int ADDRESS_MODE_U_OFFSET = 0; + public static final int ADDRESS_MODE_V_OFFSET = 2; + public static final int MIN_FILTER_OFFSET = 4; + public static final int MAG_FILTER_OFFSET = 5; + public static final int MIPMAP_MODE_OFFSET = 6; + public static final int ANISOTROPY_OFFSET = 7; + public static final int REDUCTION_MODE_ENABLE_OFFSET = 8; + public static final int REDUCTION_MODE_OFFSET = 9; + static final float MIP_BIAS = -0.5f; - static final Short2LongMap SAMPLERS = new Short2LongOpenHashMap(); + static final Object2LongMap SAMPLERS = new Object2LongOpenHashMap<>(); + + public static long getSampler(boolean clamp, boolean linearFiltering, int maxLod) { + return getSampler(clamp, linearFiltering, maxLod, false, 0); + } + + public static long getSampler(boolean clamp, boolean linearFiltering, int maxLod, boolean anisotropy, int maxAnisotropy) { + int addressMode = clamp ? VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : VK_SAMPLER_ADDRESS_MODE_REPEAT; + int filter = linearFiltering ? VK_FILTER_LINEAR : VK_FILTER_NEAREST; + int mipmapMode = linearFiltering ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST; + + return getSampler(addressMode, addressMode, filter, filter, mipmapMode, maxLod, anisotropy, maxAnisotropy, -1); + } + + public static long getSampler(int addressModeU, int addressModeV, + int minFilter, int magFilter, int mipmapMode, float maxLod, + boolean anisotropy, float maxAnisotropy, int reductionMode) { + SamplerInfo samplerInfo = new SamplerInfo(addressModeU, addressModeV, minFilter, magFilter, mipmapMode, maxLod, anisotropy, maxAnisotropy, reductionMode); - public static long getTextureSampler(byte maxLod, byte flags) { - short key = (short) (flags | (maxLod << 8)); - long sampler = SAMPLERS.getOrDefault(key, 0L); + long sampler = SAMPLERS.getOrDefault(samplerInfo, 0L); if (sampler == 0L) { - sampler = createTextureSampler(maxLod, flags); - SAMPLERS.put(key, sampler); + sampler = createTextureSampler(samplerInfo); + SAMPLERS.put(samplerInfo, sampler); } return sampler; } - private static long createTextureSampler(byte maxLod, byte flags) { - Validate.isTrue( - (flags & (REDUCTION_MIN_BIT | REDUCTION_MAX_BIT)) != (REDUCTION_MIN_BIT | REDUCTION_MAX_BIT) - ); + public static long getDefaultSampler() { + return getSampler(false, false, 0); + } - try (MemoryStack stack = stackPush()) { + private static long createTextureSampler(SamplerInfo sampler) { + int state = sampler.encodedState; + try (MemoryStack stack = stackPush()) { VkSamplerCreateInfo samplerInfo = VkSamplerCreateInfo.calloc(stack); samplerInfo.sType(VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO); - if ((flags & LINEAR_FILTERING_BIT) != 0) { - samplerInfo.magFilter(VK_FILTER_LINEAR); - samplerInfo.minFilter(VK_FILTER_LINEAR); - } else { - samplerInfo.magFilter(VK_FILTER_NEAREST); - samplerInfo.minFilter(VK_FILTER_NEAREST); - } + samplerInfo.magFilter(sampler.getMagFilter()); + samplerInfo.minFilter(sampler.getMinFilter()); - if ((flags & CLAMP_BIT) != 0) { - samplerInfo.addressModeU(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE); - samplerInfo.addressModeV(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE); - samplerInfo.addressModeW(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE); - } else { - samplerInfo.addressModeU(VK_SAMPLER_ADDRESS_MODE_REPEAT); - samplerInfo.addressModeV(VK_SAMPLER_ADDRESS_MODE_REPEAT); - samplerInfo.addressModeW(VK_SAMPLER_ADDRESS_MODE_REPEAT); - } + samplerInfo.addressModeU(sampler.getAddressModeU()); + samplerInfo.addressModeV(sampler.getAddressModeV()); + samplerInfo.addressModeW(VK_SAMPLER_ADDRESS_MODE_REPEAT); - samplerInfo.anisotropyEnable(false); - //samplerInfo.maxAnisotropy(16.0f); + samplerInfo.anisotropyEnable(sampler.getAnisotropy()); + samplerInfo.maxAnisotropy(sampler.getMaxAnisotropy()); samplerInfo.borderColor(VK_BORDER_COLOR_INT_OPAQUE_WHITE); samplerInfo.unnormalizedCoordinates(false); samplerInfo.compareEnable(false); samplerInfo.compareOp(VK_COMPARE_OP_ALWAYS); - if ((flags & USE_MIPMAPS_BIT) == 0) { - samplerInfo.mipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST); - samplerInfo.maxLod(0.0F); - samplerInfo.minLod(0.0F); - } else { - if ((flags & MIPMAP_LINEAR_FILTERING_BIT) != 0) { - samplerInfo.mipmapMode(VK_SAMPLER_MIPMAP_MODE_LINEAR); - } else { - samplerInfo.mipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST); - } - samplerInfo.maxLod(maxLod); - samplerInfo.minLod(0.0F); - samplerInfo.mipLodBias(MIP_BIAS); - } + samplerInfo.mipmapMode(sampler.getMipmapMode()); + samplerInfo.maxLod(sampler.getMaxLod()); + samplerInfo.minLod(0.0F); + samplerInfo.mipLodBias(MIP_BIAS); - //Reduction Mode - if ((flags & (REDUCTION_MAX_BIT | REDUCTION_MIN_BIT)) != 0) { + // Reduction Mode + if (sampler.hasReductionMode()) { VkSamplerReductionModeCreateInfo reductionModeInfo = VkSamplerReductionModeCreateInfo.calloc(stack); reductionModeInfo.sType$Default(); - reductionModeInfo.reductionMode((flags & REDUCTION_MAX_BIT) != 0 ? VK_SAMPLER_REDUCTION_MODE_MAX : VK_SAMPLER_REDUCTION_MODE_MIN); + reductionModeInfo.reductionMode(sampler.getReductionMode()); samplerInfo.pNext(reductionModeInfo.address()); } @@ -107,10 +111,91 @@ public static void cleanUp() { } } - public static final byte LINEAR_FILTERING_BIT = 0b1; - public static final byte CLAMP_BIT = 0b10; - public static final byte USE_MIPMAPS_BIT = 0b100; - public static final byte MIPMAP_LINEAR_FILTERING_BIT = 0b1000; - public static final byte REDUCTION_MIN_BIT = 0b10000; - public static final byte REDUCTION_MAX_BIT = 0b100000; + public static class SamplerInfo { + final int encodedState; + final int maxLod; + final int maxAnisotropy; + + public SamplerInfo() { + this(VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, + VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST, + 0, false, 0, -1); + } + + + + public SamplerInfo(int addressModeU, int addressModeV, int minFilter, int magFilter, int mipmapMode, + float maxLod, boolean anisotropy, float maxAnisotropy, int reductionMode) { + this.maxLod = (int) maxLod; + this.maxAnisotropy = (int) maxAnisotropy; + + int encodedState = (addressModeU & ADDRESS_MODE_BITS) << ADDRESS_MODE_U_OFFSET; + encodedState |= (addressModeV & ADDRESS_MODE_BITS) << ADDRESS_MODE_V_OFFSET; + encodedState |= (minFilter & 1) << MIN_FILTER_OFFSET; + encodedState |= (magFilter & 1) << MAG_FILTER_OFFSET; + encodedState |= (mipmapMode & 1) << MIPMAP_MODE_OFFSET; + encodedState |= ((anisotropy ? 1 : 0) & 1) << ANISOTROPY_OFFSET; + encodedState |= (reductionMode != -1 ? 1 : 0) << REDUCTION_MODE_ENABLE_OFFSET; + encodedState |= (reductionMode & REDUCTION_MODE_BITS) << REDUCTION_MODE_OFFSET; + + this.encodedState = encodedState; + } + + public int getAddressModeU() { + return (this.encodedState >> ADDRESS_MODE_U_OFFSET) & ADDRESS_MODE_BITS; + } + + public int getAddressModeV() { + return (this.encodedState >> ADDRESS_MODE_V_OFFSET) & ADDRESS_MODE_BITS; + } + + public int getMinFilter() { + return (this.encodedState >> MIN_FILTER_OFFSET) & 1; + } + + public int getMagFilter() { + return (this.encodedState >> MAG_FILTER_OFFSET) & 1; + } + + public int getMipmapMode() { + return (this.encodedState >> MIPMAP_MODE_OFFSET) & 1; + } + + public boolean getAnisotropy() { + return ((this.encodedState >> ANISOTROPY_OFFSET) & 1) != 0; + } + + public boolean hasReductionMode() { + return ((this.encodedState >> REDUCTION_MODE_ENABLE_OFFSET) & 1) != 0; + } + + public int getReductionMode() { + return (this.encodedState >> REDUCTION_MODE_OFFSET) & REDUCTION_MODE_BITS; + } + + public int getMaxAnisotropy() { + return maxAnisotropy; + } + + public int getMaxLod() { + return maxLod; + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + + SamplerInfo samplerInfo = (SamplerInfo) o; + return maxLod == samplerInfo.maxLod && maxAnisotropy == samplerInfo.maxAnisotropy && encodedState == samplerInfo.encodedState; + } + + @Override + public int hashCode() { + int result = encodedState; + result = 31 * result + maxLod; + result = 31 * result + maxAnisotropy; + return result; + } + } + } diff --git a/src/main/java/net/vulkanmod/vulkan/texture/VTextureSelector.java b/src/main/java/net/vulkanmod/vulkan/texture/VTextureSelector.java index 0b3903d7f..5d580d369 100644 --- a/src/main/java/net/vulkanmod/vulkan/texture/VTextureSelector.java +++ b/src/main/java/net/vulkanmod/vulkan/texture/VTextureSelector.java @@ -1,11 +1,13 @@ package net.vulkanmod.vulkan.texture; import com.mojang.blaze3d.systems.RenderSystem; -import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite; import net.vulkanmod.Initializer; -import net.vulkanmod.gl.GlTexture; +import net.vulkanmod.gl.VkGlTexture; +import net.vulkanmod.render.engine.VkGpuTexture; +import net.vulkanmod.render.texture.SpriteUpdateUtil; import net.vulkanmod.vulkan.shader.Pipeline; import net.vulkanmod.vulkan.shader.descriptor.ImageDescriptor; +import org.lwjgl.system.MemoryUtil; import java.nio.ByteBuffer; @@ -25,7 +27,7 @@ public static void bindTexture(VulkanImage texture) { } public static void bindTexture(int i, VulkanImage texture) { - if(i < 0 || i >= SIZE) { + if (i < 0 || i >= SIZE) { Initializer.LOGGER.error(String.format("On Texture binding: index %d out of range [0, %d]", i, SIZE - 1)); return; } @@ -35,7 +37,7 @@ public static void bindTexture(int i, VulkanImage texture) { } public static void bindImage(int i, VulkanImage texture, int level) { - if(i < 0 || i > 7) { + if (i < 0 || i > 7) { Initializer.LOGGER.error(String.format("On Texture binding: index %d out of range [0, %d]", i, SIZE - 1)); return; } @@ -44,26 +46,38 @@ public static void bindImage(int i, VulkanImage texture, int level) { levels[i] = level; } - public static void uploadSubTexture(int mipLevel, int width, int height, int xOffset, int yOffset, int unpackSkipRows, int unpackSkipPixels, int unpackRowLength, ByteBuffer buffer) { + public static void uploadSubTexture(int mipLevel, int width, int height, int xOffset, int yOffset, + int unpackSkipRows, int unpackSkipPixels, int unpackRowLength, + ByteBuffer buffer) { + uploadSubTexture(mipLevel, 0, width, height, xOffset, yOffset, unpackSkipRows, unpackSkipPixels, unpackRowLength, + MemoryUtil.memAddress(buffer)); + } + + public static void uploadSubTexture(int mipLevel, int arrayLayer, int width, int height, int xOffset, int yOffset, + int unpackSkipRows, int unpackSkipPixels, int unpackRowLength, + long bufferPtr) { VulkanImage texture = boundTextures[activeTexture]; - if(texture == null) + if (texture == null) throw new NullPointerException("Texture is null at index: " + activeTexture); - texture.uploadSubTextureAsync(mipLevel, width, height, xOffset, yOffset, unpackSkipRows, unpackSkipPixels, unpackRowLength, buffer); + SpriteUpdateUtil.addTransitionedLayout(texture); + + texture.uploadSubTextureAsync(mipLevel, arrayLayer, width, height, xOffset, yOffset, unpackSkipRows, unpackSkipPixels, + unpackRowLength, bufferPtr); } public static int getTextureIdx(String name) { return switch (name) { - case "Sampler0", "DiffuseSampler" -> 0; - case "Sampler1" -> 1; + case "Sampler0", "DiffuseSampler", "InSampler", "CloudFaces" -> 0; + case "Sampler1", "BlurSampler" -> 1; case "Sampler2" -> 2; case "Sampler3" -> 3; case "Sampler4" -> 4; case "Sampler5" -> 5; case "Sampler6" -> 6; case "Sampler7" -> 7; - default -> throw new IllegalStateException("Unknown sampler name: " + name); + default -> -1; }; } @@ -71,17 +85,25 @@ public static void bindShaderTextures(Pipeline pipeline) { var imageDescriptors = pipeline.getImageDescriptors(); for (ImageDescriptor state : imageDescriptors) { - final int shaderTexture = RenderSystem.getShaderTexture(state.imageIdx); + var textureView = RenderSystem.getShaderTexture(state.imageIdx); - GlTexture texture = GlTexture.getTexture(shaderTexture); + if (textureView == null) + continue; + + VkGpuTexture gpuTexture = (VkGpuTexture) textureView.texture(); + gpuTexture.flushModeChanges(); + + final int shaderTexture = gpuTexture.glId(); + VkGlTexture texture = VkGlTexture.getTexture(shaderTexture); if (texture != null && texture.getVulkanImage() != null) { VTextureSelector.bindTexture(state.imageIdx, texture.getVulkanImage()); } - else { - texture = GlTexture.getTexture(MissingTextureAtlasSprite.getTexture().getId()); - VTextureSelector.bindTexture(state.imageIdx, texture.getVulkanImage()); - } + // TODO +// else { +// texture = GlTexture.getTexture(MissingTextureAtlasSprite.getTexture().getId()); +// VTextureSelector.bindTexture(state.imageIdx, texture.getVulkanImage()); +// } } } @@ -98,14 +120,23 @@ public static void setOverlayTexture(VulkanImage texture) { } public static void setActiveTexture(int activeTexture) { - if(activeTexture < 0 || activeTexture >= SIZE) { - Initializer.LOGGER.error(String.format("On Texture binding: index %d out of range [0, %d]", activeTexture, SIZE - 1)); + if (activeTexture < 0 || activeTexture >= SIZE) { + Initializer.LOGGER.error( + String.format("On Texture binding: index %d out of range [0, %d]", activeTexture, SIZE - 1)); } VTextureSelector.activeTexture = activeTexture; } - public static VulkanImage getBoundTexture(int i) { return boundTextures[i]; } + public static VulkanImage getBoundTexture() { + return boundTextures[activeTexture]; + } + + public static VulkanImage getBoundTexture(int i) { + return boundTextures[i]; + } - public static VulkanImage getWhiteTexture() { return whiteTexture; } + public static VulkanImage getWhiteTexture() { + return whiteTexture; + } } diff --git a/src/main/java/net/vulkanmod/vulkan/texture/VulkanImage.java b/src/main/java/net/vulkanmod/vulkan/texture/VulkanImage.java index 440f1ec56..29b07a0b7 100644 --- a/src/main/java/net/vulkanmod/vulkan/texture/VulkanImage.java +++ b/src/main/java/net/vulkanmod/vulkan/texture/VulkanImage.java @@ -1,24 +1,20 @@ package net.vulkanmod.vulkan.texture; -import com.mojang.blaze3d.platform.NativeImage; -import net.vulkanmod.vulkan.Synchronization; +import net.vulkanmod.render.texture.ImageUploadHelper; +import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.Vulkan; -import net.vulkanmod.vulkan.device.DeviceManager; import net.vulkanmod.vulkan.memory.MemoryManager; -import net.vulkanmod.vulkan.memory.StagingBuffer; +import net.vulkanmod.vulkan.memory.buffer.StagingBuffer; import net.vulkanmod.vulkan.queue.CommandPool; import org.lwjgl.PointerBuffer; import org.lwjgl.system.MemoryStack; -import org.lwjgl.vulkan.VkCommandBuffer; -import org.lwjgl.vulkan.VkDevice; -import org.lwjgl.vulkan.VkImageMemoryBarrier; -import org.lwjgl.vulkan.VkImageViewCreateInfo; +import org.lwjgl.system.MemoryUtil; +import org.lwjgl.vulkan.*; import java.nio.ByteBuffer; import java.nio.LongBuffer; import java.util.Arrays; -import static net.vulkanmod.vulkan.texture.SamplerManager.*; import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.KHRSwapchain.VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; import static org.lwjgl.vulkan.VK10.*; @@ -28,29 +24,35 @@ public class VulkanImage { private static final VkDevice DEVICE = Vulkan.getVkDevice(); - private long id; - private long allocation; - private long mainImageView; - - private long[] levelImageViews; - - private long sampler; - + public final String name; public final int format; public final int aspect; + public final int arrayLayers; public final int mipLevels; public final int width; public final int height; public final int formatSize; - private final int usage; + public final int usage; + public final int viewType; + public final int size; + + private long id; + private long allocation; + private long mainImageView; + + private final long[] levelImageViews; + + private long sampler; private int currentLayout; - //Used for swap chain images - public VulkanImage(long id, int format, int mipLevels, int width, int height, int formatSize, int usage, long imageView) { + // Used for already allocated images e.g. swap chain images + public VulkanImage(String name, long id, int format, int mipLevels, int width, int height, int formatSize, int usage, long imageView) { this.id = id; this.mainImageView = imageView; + this.name = name; + this.arrayLayers = 1; this.mipLevels = mipLevels; this.width = width; this.height = height; @@ -58,46 +60,48 @@ public VulkanImage(long id, int format, int mipLevels, int width, int height, in this.format = format; this.usage = usage; this.aspect = getAspect(this.format); + this.viewType = VK_IMAGE_VIEW_TYPE_2D; + + this.size = width * height * formatSize; + this.levelImageViews = new long[mipLevels]; - this.sampler = SamplerManager.getTextureSampler((byte) this.mipLevels, (byte) 0); + this.sampler = SamplerManager.getDefaultSampler(); } private VulkanImage(Builder builder) { + this.name = builder.name; this.mipLevels = builder.mipLevels; this.width = builder.width; this.height = builder.height; + this.arrayLayers = builder.arrayLayers; this.formatSize = builder.formatSize; this.format = builder.format; this.usage = builder.usage; this.aspect = getAspect(this.format); + this.viewType = builder.viewType; + + this.size = width * height * formatSize; + this.levelImageViews = new long[builder.mipLevels]; } public static VulkanImage createTextureImage(Builder builder) { VulkanImage image = new VulkanImage(builder); - image.createImage(builder.mipLevels, builder.width, builder.height, builder.format, builder.usage); - image.mainImageView = createImageView(image.id, builder.format, image.aspect, builder.mipLevels); - - image.sampler = SamplerManager.getTextureSampler(builder.mipLevels, builder.samplerFlags); + image.createImage(); + image.mainImageView = createImageView(image.id, image.viewType, image.format, image.aspect, image.arrayLayers, 0, image.mipLevels); - if (builder.levelViews) { - image.levelImageViews = new long[builder.mipLevels]; - - for (int i = 0; i < builder.mipLevels; ++i) { - image.levelImageViews[i] = createImageView(image.id, image.format, image.aspect, i, 1); - } - } + image.sampler = SamplerManager.getSampler(builder.clamp, builder.linearFiltering, builder.mipLevels - 1); return image; } public static VulkanImage createDepthImage(int format, int width, int height, int usage, boolean blur, boolean clamp) { VulkanImage image = VulkanImage.builder(width, height) - .setFormat(format) - .setUsage(usage) - .setLinearFiltering(blur) - .setClamp(clamp) - .createVulkanImage(); + .setFormat(format) + .setUsage(usage) + .setLinearFiltering(blur) + .setClamp(clamp) + .createVulkanImage(); return image; } @@ -109,35 +113,39 @@ public static VulkanImage createWhiteTexture() { buffer.putInt(0, i); VulkanImage image = VulkanImage.builder(1, 1) - .setFormat(DefaultFormat) - .setUsage(VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT) - .setLinearFiltering(false) - .setClamp(false) - .createVulkanImage(); - image.uploadSubTextureAsync(0, image.width, image.height, 0, 0, 0, 0, 0, buffer); + .setFormat(DefaultFormat) + .setUsage(VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT) + .setLinearFiltering(false) + .setClamp(false) + .createVulkanImage(); + image.uploadSubTextureAsync(0, 0, image.width, image.height, 0, 0, 0, 0, 0, buffer); return image; -// return createTextureImage(1, 1, 4, false, false, buffer); } } - private void createImage(int mipLevels, int width, int height, int format, int usage) { - + private void createImage() { try (MemoryStack stack = stackPush()) { - LongBuffer pTextureImage = stack.mallocLong(1); PointerBuffer pAllocation = stack.pointers(0L); - MemoryManager.createImage(width, height, mipLevels, - format, VK_IMAGE_TILING_OPTIMAL, - usage, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - pTextureImage, - pAllocation); + int flags = viewType == VK_IMAGE_VIEW_TYPE_CUBE ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0; + + MemoryManager.getInstance() + .createImage(width, height, arrayLayers, mipLevels, + format, VK_IMAGE_TILING_OPTIMAL, + usage, flags, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + pTextureImage, + pAllocation); id = pTextureImage.get(0); allocation = pAllocation.get(0); MemoryManager.addImage(this); + + if (this.name != null) { + Vulkan.setDebugLabel(stack, VK_OBJECT_TYPE_IMAGE, pTextureImage.get(), this.name); + } } } @@ -162,24 +170,22 @@ public static boolean isDepthFormat(int format) { }; } - public static long createImageView(long image, int format, int aspectFlags, int mipLevels) { - return createImageView(image, format, aspectFlags, 0, mipLevels); + public static long createImageView(long image, int format, int aspectFlags, int arrayLayers, int mipLevels) { + return createImageView(image, VK_IMAGE_VIEW_TYPE_2D, format, aspectFlags, arrayLayers, 0, mipLevels); } - public static long createImageView(long image, int format, int aspectFlags, int baseMipLevel, int mipLevels) { - + public static long createImageView(long image, int viewType, int format, int aspectFlags, int arrayLayers, int baseMipLevel, int mipLevels) { try (MemoryStack stack = stackPush()) { - VkImageViewCreateInfo viewInfo = VkImageViewCreateInfo.calloc(stack); viewInfo.sType(VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO); viewInfo.image(image); - viewInfo.viewType(VK_IMAGE_VIEW_TYPE_2D); + viewInfo.viewType(viewType); viewInfo.format(format); viewInfo.subresourceRange().aspectMask(aspectFlags); viewInfo.subresourceRange().baseMipLevel(baseMipLevel); viewInfo.subresourceRange().levelCount(mipLevels); viewInfo.subresourceRange().baseArrayLayer(0); - viewInfo.subresourceRange().layerCount(1); + viewInfo.subresourceRange().layerCount(arrayLayers); LongBuffer pImageView = stack.mallocLong(1); @@ -191,26 +197,64 @@ public static long createImageView(long image, int format, int aspectFlags, int } } - public void uploadSubTextureAsync(int mipLevel, int width, int height, int xOffset, int yOffset, int unpackSkipRows, int unpackSkipPixels, int unpackRowLength, ByteBuffer buffer) { - long imageSize = buffer.limit(); + public void uploadSubTextureAsync(int mipLevel, + int width, int height, + int xOffset, int yOffset, + int unpackSkipRows, int unpackSkipPixels, int unpackRowLength, + ByteBuffer buffer) + { + this.uploadSubTextureAsync(mipLevel, 0, width, height, + xOffset, yOffset, + unpackSkipRows, unpackSkipPixels, unpackRowLength, + MemoryUtil.memAddress(buffer)); + } + + public void uploadSubTextureAsync(int mipLevel, int arrayLayer, + int width, int height, + int xOffset, int yOffset, + int unpackSkipRows, int unpackSkipPixels, int unpackRowLength, + ByteBuffer buffer) + { + this.uploadSubTextureAsync(mipLevel, arrayLayer, width, height, + xOffset, yOffset, + unpackSkipRows, unpackSkipPixels, unpackRowLength, + MemoryUtil.memAddress(buffer)); + } + + public void uploadSubTextureAsync(int mipLevel, int arrayLayer, + int width, int height, + int xOffset, int yOffset, + int unpackSkipRows, int unpackSkipPixels, int unpackRowLength, + long srcPtr) + { + long uploadSize = (long) (unpackRowLength * height - unpackSkipPixels) * this.formatSize; - CommandPool.CommandBuffer commandBuffer = DeviceManager.getGraphicsQueue().getCommandBuffer(); - try (MemoryStack stack = stackPush()) { - transferDstLayout(stack, commandBuffer.getHandle()); + StagingBuffer stagingBuffer = Vulkan.getStagingBuffer(); + + // Use a temporary staging buffer if the upload size is greater than + // the default staging buffer + if (uploadSize > stagingBuffer.getBufferSize()) { + stagingBuffer = new StagingBuffer(uploadSize); + stagingBuffer.scheduleFree(); } - StagingBuffer stagingBuffer = Vulkan.getStagingBuffer(); + srcPtr += ((long) unpackRowLength * unpackSkipRows + unpackSkipPixels) * this.formatSize; + stagingBuffer.align(this.formatSize); + stagingBuffer.copyBuffer((int) uploadSize, srcPtr); - stagingBuffer.copyBuffer((int) imageSize, buffer); + long bufferId = stagingBuffer.getId(); + + VkCommandBuffer commandBuffer = ImageUploadHelper.INSTANCE.getOrStartCommandBuffer().getHandle(); + try (MemoryStack stack = stackPush()) { + transferDstLayout(stack, commandBuffer); - ImageUtil.copyBufferToImageCmd(commandBuffer.getHandle(), stagingBuffer.getId(), id, mipLevel, width, height, xOffset, yOffset, - (int) (stagingBuffer.getOffset() + (unpackRowLength * unpackSkipRows + unpackSkipPixels) * this.formatSize), unpackRowLength, height); + final int srcOffset = (int) (stagingBuffer.getOffset()); - long fence = DeviceManager.getGraphicsQueue().endIfNeeded(commandBuffer); - if (fence != VK_NULL_HANDLE) -// Synchronization.INSTANCE.addFence(fence); - Synchronization.INSTANCE.addCommandBuffer(commandBuffer); + ImageUtil.copyBufferToImageCmd(stack, commandBuffer, bufferId, this.id, + arrayLayer, mipLevel, width, height, xOffset, yOffset, + srcOffset, unpackRowLength, height); + } } private void transferDstLayout(MemoryStack stack, VkCommandBuffer commandBuffer) { @@ -221,32 +265,25 @@ public void readOnlyLayout() { if (this.currentLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) return; - CommandPool.CommandBuffer commandBuffer = DeviceManager.getGraphicsQueue().getCommandBuffer(); try (MemoryStack stack = MemoryStack.stackPush()) { - readOnlyLayout(stack, commandBuffer.getHandle()); + if (Renderer.getInstance().getBoundRenderPass() != null) { + CommandPool.CommandBuffer commandBuffer = ImageUploadHelper.INSTANCE.getOrStartCommandBuffer(); + VkCommandBuffer vkCommandBuffer = commandBuffer.getHandle(); + + readOnlyLayout(stack, vkCommandBuffer); + } + else { + readOnlyLayout(stack, Renderer.getCommandBuffer()); + } } - DeviceManager.getGraphicsQueue().submitCommands(commandBuffer); - Synchronization.INSTANCE.addCommandBuffer(commandBuffer); } public void readOnlyLayout(MemoryStack stack, VkCommandBuffer commandBuffer) { transitionImageLayout(stack, commandBuffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); } - public void updateTextureSampler(boolean blur, boolean clamp, boolean mipmaps) { - byte flags = blur ? LINEAR_FILTERING_BIT : 0; - flags |= clamp ? CLAMP_BIT : 0; - flags |= (byte) (mipmaps ? USE_MIPMAPS_BIT | MIPMAP_LINEAR_FILTERING_BIT : 0); - - this.updateTextureSampler(flags); - } - - public void updateTextureSampler(byte flags) { - updateTextureSampler(this.mipLevels - 1, flags); - } - - public void updateTextureSampler(int maxLod, byte flags) { - this.sampler = SamplerManager.getTextureSampler((byte) maxLod, flags); + public void setSampler(long sampler) { + this.sampler = sampler; } public void transitionImageLayout(MemoryStack stack, VkCommandBuffer commandBuffer, int newLayout) { @@ -255,7 +292,6 @@ public void transitionImageLayout(MemoryStack stack, VkCommandBuffer commandBuff public static void transitionImageLayout(MemoryStack stack, VkCommandBuffer commandBuffer, VulkanImage image, int newLayout) { if (image.currentLayout == newLayout) { -// System.out.println("new layout is equal to current layout"); return; } @@ -317,13 +353,13 @@ public static void transitionImageLayout(MemoryStack stack, VkCommandBuffer comm } transitionLayout(stack, commandBuffer, image, image.currentLayout, newLayout, - sourceStage, srcAccessMask, destinationStage, dstAccessMask); + sourceStage, srcAccessMask, destinationStage, dstAccessMask); } public static void transitionLayout(MemoryStack stack, VkCommandBuffer commandBuffer, VulkanImage image, int oldLayout, int newLayout, int sourceStage, int srcAccessMask, int destinationStage, int dstAccessMask) { transitionLayout(stack, commandBuffer, image, 0, oldLayout, newLayout, - sourceStage, srcAccessMask, destinationStage, dstAccessMask); + sourceStage, srcAccessMask, destinationStage, dstAccessMask); } public static void transitionLayout(MemoryStack stack, VkCommandBuffer commandBuffer, VulkanImage image, int baseLevel, int oldLayout, int newLayout, @@ -348,11 +384,11 @@ public static void transitionLayout(MemoryStack stack, VkCommandBuffer commandBu barrier.dstAccessMask(dstAccessMask); vkCmdPipelineBarrier(commandBuffer, - sourceStage, destinationStage, - 0, - null, - null, - barrier); + sourceStage, destinationStage, + 0, + null, + null, + barrier); image.currentLayout = newLayout; } @@ -375,7 +411,11 @@ public void doFree() { if (this.levelImageViews != null) Arrays.stream(this.levelImageViews).forEach( - imageView -> vkDestroyImageView(Vulkan.getVkDevice(), this.mainImageView, null)); + imageView -> { + if (imageView != 0L) { + vkDestroyImageView(Vulkan.getVkDevice(), imageView, null); + } + }); this.id = 0L; } @@ -401,6 +441,9 @@ public long getImageView() { } public long getLevelImageView(int i) { + if (this.levelImageViews[i] == 0L) { + this.levelImageViews[i] = createImageView(this.id, VK_IMAGE_VIEW_TYPE_2D, this.format, this.aspect, this.arrayLayers, i, 1); + } return levelImageViews[i]; } @@ -420,36 +463,41 @@ public static class Builder { final int width; final int height; + String name; int format = VulkanImage.DefaultFormat; int formatSize; + int arrayLayers = 1; byte mipLevels = 1; int usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + int viewType = VK_IMAGE_VIEW_TYPE_2D; - byte samplerFlags = 0; - - boolean levelViews = false; + // Sampler settings + boolean linearFiltering = false; + boolean clamp = false; + int reductionMode = -1; public Builder(int width, int height) { this.width = width; this.height = height; } + public Builder setName(String name) { + this.name = name; + return this; + } + public Builder setFormat(int format) { this.format = format; return this; } - public Builder setFormat(NativeImage.InternalGlFormat format) { - this.format = convertFormat(format); + public Builder setArrayLayers(int n) { + this.arrayLayers = (byte) n; return this; } public Builder setMipLevels(int n) { this.mipLevels = (byte) n; - - if (n > 1) - this.samplerFlags |= USE_MIPMAPS_BIT | MIPMAP_LINEAR_FILTERING_BIT; - return this; } @@ -463,23 +511,23 @@ public Builder addUsage(int usage) { return this; } - public Builder setLinearFiltering(boolean b) { - this.samplerFlags |= b ? LINEAR_FILTERING_BIT : 0; + public Builder setViewType(int viewType) { + this.viewType = viewType; return this; } - public Builder setClamp(boolean b) { - this.samplerFlags |= b ? CLAMP_BIT : 0; + public Builder setLinearFiltering(boolean b) { + this.linearFiltering = b; return this; } - public Builder setSamplerReductionModeMin() { - this.samplerFlags = REDUCTION_MIN_BIT | LINEAR_FILTERING_BIT; + public Builder setClamp(boolean b) { + this.clamp = b; return this; } - public Builder setLevelViews(boolean b) { - this.levelViews = b; + public Builder setSamplerReductionMode(int reductionMode) { + this.reductionMode = reductionMode; return this; } @@ -489,23 +537,17 @@ public VulkanImage createVulkanImage() { return VulkanImage.createTextureImage(this); } - private static int convertFormat(NativeImage.InternalGlFormat format) { - return switch (format) { - case RGBA -> VK_FORMAT_R8G8B8A8_UNORM; - case RED -> VK_FORMAT_R8_UNORM; - default -> throw new IllegalArgumentException(String.format("Unxepcted format: %s", format)); - }; - } - private static int formatSize(int format) { return switch (format) { case VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_SRGB, VK_FORMAT_D32_SFLOAT, VK_FORMAT_D24_UNORM_S8_UINT, - VK_FORMAT_R8G8B8A8_UINT, VK_FORMAT_R8G8B8A8_SINT -> 4; + VK_FORMAT_R8G8B8A8_UINT, VK_FORMAT_R8G8B8A8_SINT, + VK_FORMAT_R32_SFLOAT -> 4; + case VK_FORMAT_R16_SFLOAT -> 2; case VK_FORMAT_R8_UNORM -> 1; + case VK_FORMAT_R16G16B16A16_SFLOAT -> 8; -// default -> throw new IllegalArgumentException(String.format("Unxepcted format: %s", format)); - default -> 0; + default -> throw new IllegalArgumentException(String.format("Unxepcted format: %s", format)); }; } } diff --git a/src/main/java/net/vulkanmod/vulkan/util/ColorUtil.java b/src/main/java/net/vulkanmod/vulkan/util/ColorUtil.java index 7dc60c03c..0c2c0990b 100644 --- a/src/main/java/net/vulkanmod/vulkan/util/ColorUtil.java +++ b/src/main/java/net/vulkanmod/vulkan/util/ColorUtil.java @@ -47,11 +47,23 @@ public static int multiplyAlpha(int color, float m) { int newA = floatToInt(unpackA(color) * m); return (color & 0x00FFFFFF) | newA << 24; } + + public static int multiplyRGB(int color, float m) { + final int alpha = ((color >>> 24) & 0xFF); + final int red = (int) (((color >>> 16) & 0xFF) * m); + final int green = (int) (((color >>> 8) & 0xFF) * m); + final int blue = (int) ((color & 0xFF) * m); + + return (alpha << 24) | (red << 16) | (green << 8) | blue; + } + + public static int toRGBA(int color) { + return (color & 0xFF00FF00) | ((color >> 16) & 0xFF) | ((color << 16) & 0xFF0000); + } } public static class RGBA { public static int pack(float r, float g, float b, float a) { -// int color = floatToInt(r) << 24 | floatToInt(g) << 16 | floatToInt(b) << 8 | floatToInt(a); int color = floatToInt(a) << 24 | floatToInt(b) << 16 | floatToInt(g) << 8 | floatToInt(r); return color; diff --git a/src/main/java/net/vulkanmod/vulkan/util/DrawUtil.java b/src/main/java/net/vulkanmod/vulkan/util/DrawUtil.java index b5d187e3b..fd2a9ece0 100644 --- a/src/main/java/net/vulkanmod/vulkan/util/DrawUtil.java +++ b/src/main/java/net/vulkanmod/vulkan/util/DrawUtil.java @@ -1,16 +1,10 @@ package net.vulkanmod.vulkan.util; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.*; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.ShaderInstance; -import net.vulkanmod.interfaces.ShaderMixed; import net.vulkanmod.render.PipelineManager; import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.VRenderSystem; import net.vulkanmod.vulkan.shader.GraphicsPipeline; -import org.joml.Matrix4f; -import org.joml.Matrix4fStack; import org.lwjgl.opengl.GL11; import org.lwjgl.vulkan.VK11; import org.lwjgl.vulkan.VkCommandBuffer; @@ -25,7 +19,7 @@ public static void blitToScreen() { public static void fastBlit() { GraphicsPipeline blitPipeline = PipelineManager.getFastBlitPipeline(); - RenderSystem.disableCull(); + VRenderSystem.disableCull(); VRenderSystem.setPrimitiveTopologyGL(GL11.GL_TRIANGLES); Renderer renderer = Renderer.getInstance(); @@ -35,36 +29,38 @@ public static void fastBlit() { VkCommandBuffer commandBuffer = Renderer.getCommandBuffer(); VK11.vkCmdDraw(commandBuffer, 3, 1, 0, 0); - RenderSystem.enableCull(); + VRenderSystem.enableCull(); } - public static void defualtBlit() { - Matrix4f matrix4f = new Matrix4f().setOrtho(0.0F, 1.0F, 1.0F, 0.0F, 0.0F, 1.0F); - RenderSystem.setProjectionMatrix(matrix4f, VertexSorting.ORTHOGRAPHIC_Z); - Matrix4fStack posestack = RenderSystem.getModelViewStack(); - posestack.pushMatrix(); - posestack.identity(); - RenderSystem.applyModelViewMatrix(); - posestack.popMatrix(); - - ShaderInstance shaderInstance = Minecraft.getInstance().gameRenderer.blitShader; -// RenderSystem.setShader(() -> shaderInstance); - - Tesselator tesselator = RenderSystem.renderThreadTesselator(); - BufferBuilder bufferBuilder = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX); - bufferBuilder.addVertex(-1.0f, -1.0f, 0.0f).setUv(0.0F, 1.0F); - bufferBuilder.addVertex(1.0f, -1.0f, 0.0f).setUv(1.0F, 1.0F); - bufferBuilder.addVertex(1.0f, 1.0f, 0.0f).setUv(1.0F, 0.0F); - bufferBuilder.addVertex(-1.0f, 1.0f, 0.0f).setUv(0.0F, 0.0F); - var meshData = bufferBuilder.buildOrThrow(); - - MeshData.DrawState parameters = meshData.drawState(); - - Renderer renderer = Renderer.getInstance(); - - GraphicsPipeline pipeline = ((ShaderMixed)(shaderInstance)).getPipeline(); - renderer.bindGraphicsPipeline(pipeline); - renderer.uploadAndBindUBOs(pipeline); - Renderer.getDrawer().draw(meshData.vertexBuffer(), parameters.mode(), parameters.format(), parameters.vertexCount()); - } + // TODO +// public static void defualtBlit() { +// Matrix4f matrix4f = new Matrix4f().setOrtho(0.0F, 1.0F, 1.0F, 0.0F, 0.0F, 1.0F); +// RenderSystem.setProjectionMatrix(matrix4f, ProjectionType.ORTHOGRAPHIC); +// Matrix4fStack posestack = RenderSystem.getModelViewStack(); +// posestack.pushMatrix(); +// posestack.identity(); +// VRenderSystem.applyModelViewMatrix(); +// RenderSystem.(); +// posestack.popMatrix(); +// +// ShaderProgram shaderInstance = CoreShaders.BLIT_SCREEN; +//// RenderSystem.setShader(() -> shaderInstance); +// +// Tesselator tesselator = RenderSystem.renderThreadTesselator(); +// BufferBuilder bufferBuilder = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX); +// bufferBuilder.addVertex(-1.0f, -1.0f, 0.0f).setUv(0.0F, 1.0F); +// bufferBuilder.addVertex(1.0f, -1.0f, 0.0f).setUv(1.0F, 1.0F); +// bufferBuilder.addVertex(1.0f, 1.0f, 0.0f).setUv(1.0F, 0.0F); +// bufferBuilder.addVertex(-1.0f, 1.0f, 0.0f).setUv(0.0F, 0.0F); +// var meshData = bufferBuilder.buildOrThrow(); +// +// MeshData.DrawState parameters = meshData.drawState(); +// +// Renderer renderer = Renderer.getInstance(); +// +// GraphicsPipeline pipeline = ((ShaderMixed)(shaderInstance)).getPipeline(); +// renderer.bindGraphicsPipeline(pipeline); +// renderer.uploadAndBindUBOs(pipeline); +// Renderer.getDrawer().draw(meshData.vertexBuffer(), parameters.mode(), parameters.format(), parameters.vertexCount()); +// } } diff --git a/src/main/java/net/vulkanmod/vulkan/util/ScreenshotUtil.java b/src/main/java/net/vulkanmod/vulkan/util/ScreenshotUtil.java new file mode 100644 index 000000000..bae0ef938 --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/util/ScreenshotUtil.java @@ -0,0 +1,87 @@ +package net.vulkanmod.vulkan.util; + +import com.mojang.blaze3d.buffers.GpuBuffer; +import com.mojang.blaze3d.pipeline.RenderTarget; +import com.mojang.blaze3d.platform.NativeImage; +import com.mojang.blaze3d.systems.CommandEncoder; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.textures.GpuTexture; +import com.mojang.blaze3d.textures.TextureFormat; +import net.minecraft.util.ARGB; +import net.vulkanmod.render.engine.VkGpuTexture; +import net.vulkanmod.vulkan.Renderer; +import org.lwjgl.vulkan.VK10; + +import java.util.function.Consumer; + +public abstract class ScreenshotUtil { + + public static void takeScreenshot(RenderTarget renderTarget, int mipLevel, Consumer consumer) { + int width = renderTarget.width; + int height = renderTarget.height; + GpuTexture gpuTexture = renderTarget.getColorTexture(); + if (gpuTexture == null) { + throw new IllegalStateException("Tried to capture screenshot of an incomplete framebuffer"); + } else { + // Need to submit and wait cmds if screenshot was requested + // before the end of the frame + Renderer.getInstance().flushCmds(); + + int pixelSize = TextureFormat.RGBA8.pixelSize(); + GpuBuffer gpuBuffer = RenderSystem.getDevice() + .createBuffer(() -> "Screenshot buffer", 9, width * height * pixelSize); + CommandEncoder commandEncoder = RenderSystem.getDevice().createCommandEncoder(); + RenderSystem.getDevice().createCommandEncoder().copyTextureToBuffer(gpuTexture, gpuBuffer, 0, () -> { + try (GpuBuffer.MappedView readView = commandEncoder.mapBuffer(gpuBuffer, true, false)) { + NativeImage nativeImage = new NativeImage(width, height, false); + + var colorAttachment = ((VkGpuTexture) Renderer.getInstance() + .getMainPass() + .getColorAttachment()); + boolean isBgraFormat = (colorAttachment.getVulkanImage().format == VK10.VK_FORMAT_B8G8R8A8_UNORM); + + int size = mipLevel * mipLevel; + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + + if (mipLevel == 1) { + int color = readView.data().getInt((x + y * width) * pixelSize); + + if (isBgraFormat) { + color = ColorUtil.BGRAtoRGBA(color); + } + + nativeImage.setPixelABGR(x, y, color | 0xFF000000); + } else { + int red = 0; + int green = 0; + int blue = 0; + + for (int x1 = 0; x1 < mipLevel; x1++) { + for (int y1 = 0; y1 < mipLevel; y1++) { + int color = readView.data().getInt(((x + x1) + (y + y1) * width) * pixelSize); + + if (isBgraFormat) { + color = ColorUtil.BGRAtoRGBA(color); + } + + red += ARGB.red(color); + green += ARGB.green(color); + blue += ARGB.blue(color); + } + } + + nativeImage.setPixelABGR(x, y, ARGB.color(255, red / size, green / size, blue / size)); + } + } + } + + consumer.accept(nativeImage); + } + + gpuBuffer.close(); + }, 0); + } + } +} diff --git a/src/main/java/net/vulkanmod/vulkan/util/VUtil.java b/src/main/java/net/vulkanmod/vulkan/util/VUtil.java index 46ffadeb3..ab359b71a 100644 --- a/src/main/java/net/vulkanmod/vulkan/util/VUtil.java +++ b/src/main/java/net/vulkanmod/vulkan/util/VUtil.java @@ -1,5 +1,6 @@ package net.vulkanmod.vulkan.util; +import net.vulkanmod.vulkan.memory.buffer.Buffer; import org.lwjgl.PointerBuffer; import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryUtil; @@ -7,12 +8,13 @@ import java.lang.reflect.Field; import java.nio.ByteBuffer; -import java.nio.FloatBuffer; import java.util.Collection; import static org.lwjgl.system.MemoryStack.stackGet; public class VUtil { + public static final boolean CHECKS = true; + public static final int UINT32_MAX = 0xFFFFFFFF; public static final long UINT64_MAX = 0xFFFFFFFFFFFFFFFFL; @@ -43,74 +45,46 @@ public static PointerBuffer asPointerBuffer(Collection collection) { return buffer.rewind(); } - public static void memcpy(ByteBuffer buffer, short[] indices) { - - for(short index : indices) { - buffer.putShort(index); - } - - buffer.rewind(); - } - - public static void memcpy(ByteBuffer buffer, short[] indices, long offset) { - buffer.position((int) offset); - - for(short index : indices) { - buffer.putShort(index); - } - - buffer.rewind(); - } - - public static void memcpy(ByteBuffer src, ByteBuffer dst) { - MemoryUtil.memCopy(src, dst); - src.limit(src.capacity()).rewind(); - } - public static void memcpy(ByteBuffer src, long dstPtr) { MemoryUtil.memCopy(MemoryUtil.memAddress0(src), dstPtr, src.capacity()); } - public static void memcpy(ByteBuffer src, ByteBuffer dst, long offset) { - dst.position((int)offset); - - MemoryUtil.memCopy(src, dst); - src.limit(src.capacity()).rewind(); - } + public static void memcpy(ByteBuffer src, Buffer dst, long size) { + if (CHECKS) { + if (size > dst.getBufferSize() - dst.getUsedBytes()) { + throw new IllegalArgumentException("Upload size is greater than available dst buffer size"); + } + } - public static void memcpy(ByteBuffer src, ByteBuffer dst, int size, long offset) { - dst.position((int)offset); - src.limit(size); + final long srcPtr = MemoryUtil.memAddress(src); + final long dstPtr = dst.getDataPtr() + dst.getUsedBytes(); - MemoryUtil.memCopy(src, dst); - src.limit(src.capacity()).rewind(); + MemoryUtil.memCopy(srcPtr, dstPtr, size); } - public static void memcpyImage(ByteBuffer dst, ByteBuffer src, int width, int height, int channels, int unpackSkipRows, int unpackSkipPixels, int unpackRowLenght) { - int offset = (unpackSkipRows * unpackRowLenght + unpackSkipPixels) * channels; - for (int i = 0; i < height; ++i) { - src.limit(offset + width * channels); - src.position(offset); - dst.put(src); - offset += unpackRowLenght * channels; + public static void memcpy(Buffer src, ByteBuffer dst, long size) { + if (CHECKS) { + if (size > dst.remaining()) { + throw new IllegalArgumentException("Upload size is greater than available dst buffer size"); + } } - } - public static void memcpy(ByteBuffer buffer, FloatBuffer floatBuffer) { - while(floatBuffer.hasRemaining()) { - float f = floatBuffer.get(); - buffer.putFloat(f); - } - floatBuffer.position(0); + final long srcPtr = src.getDataPtr(); + final long dstPtr = MemoryUtil.memAddress(dst); + + MemoryUtil.memCopy(srcPtr, dstPtr, size); } - public static void memcpy(ByteBuffer buffer, FloatBuffer floatBuffer, long offset) { - buffer.position((int) offset); - while(floatBuffer.hasRemaining()) { - float f = floatBuffer.get(); - buffer.putFloat(f); + public static void memcpy(ByteBuffer src, Buffer dst, long size, long srcOffset, long dstOffset) { + if (CHECKS) { + if (size > dst.getBufferSize() - dstOffset) { + throw new IllegalArgumentException("Upload size is greater than available dst buffer size"); + } } - floatBuffer.position(0); + + final long dstPtr = dst.getDataPtr() + dstOffset; + final long srcPtr = MemoryUtil.memAddress(src) + srcOffset; + MemoryUtil.memCopy(srcPtr, dstPtr, size); } public static int align(int x, int align) { diff --git a/src/main/resources/assets/vulkanmod/lang/en_us.json b/src/main/resources/assets/vulkanmod/lang/en_us.json index 28f7ba3db..ec9addfed 100644 --- a/src/main/resources/assets/vulkanmod/lang/en_us.json +++ b/src/main/resources/assets/vulkanmod/lang/en_us.json @@ -8,6 +8,7 @@ "vulkanmod.options.buttons.apply": "Apply", "vulkanmod.options.buttons.kofi": "Support me", + "vulkanmod.options.buttons.update_available": "Update available!", "vulkanmod.options.advCulling": "Advanced Chunk Culling", "vulkanmod.options.advCulling.aggressive": "Aggressive", @@ -28,13 +29,23 @@ "vulkanmod.options.frameQueue": "Render queue size", "vulkanmod.options.frameQueue.tooltip": "Higher values might help stabilize frametime but will increase input lag.", + "vulkanmod.options.backfaceCulling": "Backface Culling", + "vulkanmod.options.backfaceCulling.tooltip": "Culls not visible block faces on the CPU improving GPU performance. To prevent increased CPU overhead enable Indirect Draw.", + "vulkanmod.options.indirectDraw": "Indirect Draw", - "vulkanmod.options.indirectDraw.tooltip": "Reduces CPU overhead but increases GPU overhead. Enabling it might help in CPU limited systems.", + "vulkanmod.options.indirectDraw.tooltip": "Reduces CPU overhead but might increases GPU overhead.", "vulkanmod.options.refreshRate": "Refresh Rate", "vulkanmod.options.uniqueOpaqueLayer": "Unique opaque layer", "vulkanmod.options.uniqueOpaqueLayer.tooltip": "Use a unique render layer for opaque terrain to improve performance.", - "vulkanmod.options.windowedFullscreen": "Windowed Fullscreen" + "vulkanmod.options.windowMode": "Window Mode", + "vulkanmod.options.windowMode.windowed": "Windowed", + "vulkanmod.options.windowMode.windowedFullscreen": "Windowed Fullscreen", + + "vulkanmod.options.builderThreads": "Chunk Builder Threads", + "vulkanmod.options.builderThreads.auto": "Auto", + + "vulkanmod.options.textureAnimations": "Texture Animations" } \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_lightning/rendertype_lightning.fsh b/src/main/resources/assets/vulkanmod/shaders/basic/clouds/clouds.fsh similarity index 50% rename from src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_lightning/rendertype_lightning.fsh rename to src/main/resources/assets/vulkanmod/shaders/basic/clouds/clouds.fsh index 611cd42ce..4db811887 100644 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_lightning/rendertype_lightning.fsh +++ b/src/main/resources/assets/vulkanmod/shaders/basic/clouds/clouds.fsh @@ -1,10 +1,10 @@ #version 450 + #include "fog.glsl" -layout(binding = 1) uniform UBO{ +layout(binding = 1) uniform UBO { vec4 ColorModulator; - float FogStart; - float FogEnd; + float FogCloudsEnd; }; layout(location = 0) in vec4 vertexColor; @@ -13,5 +13,7 @@ layout(location = 1) in float vertexDistance; layout(location = 0) out vec4 fragColor; void main() { - fragColor = vertexColor * ColorModulator * linear_fog_fade(vertexDistance, FogStart, FogEnd); -} \ No newline at end of file + vec4 color = vertexColor; + color.a *= 1.0f - linear_fog_value(vertexDistance, 0, FogCloudsEnd); + fragColor = vec4(color.rgb, color.a); +} diff --git a/src/main/resources/assets/vulkanmod/shaders/basic/clouds/clouds.json b/src/main/resources/assets/vulkanmod/shaders/basic/clouds/clouds.json new file mode 100644 index 000000000..a70792662 --- /dev/null +++ b/src/main/resources/assets/vulkanmod/shaders/basic/clouds/clouds.json @@ -0,0 +1,15 @@ +{ + "vertex": "clouds", + "fragment": "clouds", + "samplers": [], + "UBOs": [ + { "type": "vertex", "binding": 0, "fields": [ + { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ModelOffset", "type": "float", "count": 3, "values": [ 0.0, 0.0, 0.0 ] } + ] }, + { "type": "all", "binding": 1, "fields": [ + { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, + { "name": "FogCloudsEnd", "type": "float", "count": 1, "values": [ 1.0 ] } + ] } + ] +} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_lightning/rendertype_lightning.vsh b/src/main/resources/assets/vulkanmod/shaders/basic/clouds/clouds.vsh similarity index 56% rename from src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_lightning/rendertype_lightning.vsh rename to src/main/resources/assets/vulkanmod/shaders/basic/clouds/clouds.vsh index c9312302f..09fa14443 100644 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_lightning/rendertype_lightning.vsh +++ b/src/main/resources/assets/vulkanmod/shaders/basic/clouds/clouds.vsh @@ -1,20 +1,25 @@ #version 450 -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; - layout(binding = 0) uniform UniformBufferObject { mat4 MVP; + vec3 ModelOffset; }; +layout(binding = 1) uniform UBO { + vec4 ColorModulator; + float FogCloudsEnd; +}; + +layout(location = 0) in vec3 Position; +layout(location = 1) in vec4 Color; + layout(location = 0) out vec4 vertexColor; layout(location = 1) out float vertexDistance; void main() { gl_Position = MVP * vec4(Position, 1.0); + vec3 viewPos = Position + ModelOffset; + vertexDistance = length(viewPos.xyz); - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = Color; -} \ No newline at end of file + vertexColor = Color * ColorModulator; +} diff --git a/src/main/resources/assets/vulkanmod/shaders/basic/terrain/terrain.fsh b/src/main/resources/assets/vulkanmod/shaders/basic/terrain/terrain.fsh index 84146fa24..827c5e8f6 100644 --- a/src/main/resources/assets/vulkanmod/shaders/basic/terrain/terrain.fsh +++ b/src/main/resources/assets/vulkanmod/shaders/basic/terrain/terrain.fsh @@ -7,14 +7,19 @@ layout(binding = 2) uniform sampler2D Sampler0; layout(binding = 1) uniform UBO { vec4 FogColor; - float FogStart; - float FogEnd; + float FogEnvironmentalStart; + float FogEnvironmentalEnd; + float FogRenderDistanceStart; + float FogRenderDistanceEnd; + float FogSkyEnd; + float FogCloudsEnd; float AlphaCutout; }; -layout(location = 0) in float vertexDistance; -layout(location = 1) in vec4 vertexColor; -layout(location = 2) in vec2 texCoord0; +layout(location = 0) in vec4 vertexColor; +layout(location = 1) in vec2 texCoord0; +layout(location = 2) in float sphericalVertexDistance; +layout(location = 3) in float cylindricalVertexDistance; layout(location = 0) out vec4 fragColor; @@ -23,5 +28,5 @@ void main() { if (color.a < AlphaCutout) { discard; } - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); + fragColor = apply_fog(color, sphericalVertexDistance, cylindricalVertexDistance, FogEnvironmentalStart, FogEnvironmentalEnd, FogRenderDistanceStart, FogRenderDistanceEnd, FogColor); } diff --git a/src/main/resources/assets/vulkanmod/shaders/basic/terrain/terrain.json b/src/main/resources/assets/vulkanmod/shaders/basic/terrain/terrain.json index bf010c54b..993650ce9 100644 --- a/src/main/resources/assets/vulkanmod/shaders/basic/terrain/terrain.json +++ b/src/main/resources/assets/vulkanmod/shaders/basic/terrain/terrain.json @@ -1,38 +1,26 @@ { - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_solid", - "fragment": "rendertype_solid", - "attributes": [ - "Position", - "Color", - "UV0" - ], + "vertex": "terrain", + "fragment": "terrain", "samplers": [ { "name": "Sampler0" }, { "name": "Sampler2" } ], - "uniforms": [ - { "name": "ChunkOffset", "type": "float", "count": 3, "values": [ 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], "UBOs": [ { "type": "vertex", "binding": 0, "fields": [ { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } ] }, { "type": "fragment", "binding": 1, "fields": [ { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, + { "name": "FogEnvironmentalStart", "type": "float", "count": 1, "values": [ 0.0 ] }, + { "name": "FogEnvironmentalEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, + { "name": "FogRenderDistanceStart", "type": "float", "count": 1, "values": [ 1.0 ] }, + { "name": "FogRenderDistanceEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, + { "name": "FogSkyEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, + { "name": "FogCloudsEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, { "name": "AlphaCutout", "type": "float", "count": 1, "values": [ 1.0 ] } ] } ], "PushConstants": [ - { "name": "ChunkOffset", "type": "float", "count": 3, "values": [ 0.0, 0.0, 0.0 ] } + { "name": "ModelOffset", "type": "float", "count": 3, "values": [ 0.0, 0.0, 0.0 ] } ] } diff --git a/src/main/resources/assets/vulkanmod/shaders/basic/terrain/terrain.vsh b/src/main/resources/assets/vulkanmod/shaders/basic/terrain/terrain.vsh index 87a3531d5..ee6a6bc57 100644 --- a/src/main/resources/assets/vulkanmod/shaders/basic/terrain/terrain.vsh +++ b/src/main/resources/assets/vulkanmod/shaders/basic/terrain/terrain.vsh @@ -8,50 +8,54 @@ layout (binding = 0) uniform UniformBufferObject { }; layout (push_constant) uniform pushConstant { - vec3 ChunkOffset; + vec3 ModelOffset; }; layout (binding = 3) uniform sampler2D Sampler2; -layout (location = 0) out float vertexDistance; -layout (location = 1) out vec4 vertexColor; -layout (location = 2) out vec2 texCoord0; +layout (location = 0) out vec4 vertexColor; +layout (location = 1) out vec2 texCoord0; +layout (location = 2) out float sphericalVertexDistance; +layout (location = 3) out float cylindricalVertexDistance; -//Compressed Vertex -layout (location = 0) in ivec4 Position; -layout (location = 1) in vec4 Color; -layout (location = 2) in uvec2 UV0; +#define COMPRESSED_VERTEX + +#ifdef COMPRESSED_VERTEX + layout (location = 0) in ivec4 Position; + layout (location = 1) in uvec2 UV0; + layout (location = 2) in uint PackedColor; +#else + layout (location = 0) in vec3 Position; + layout (location = 1) in vec4 Color; + layout (location = 2) in vec2 UV0; + layout (location = 3) in ivec2 UV2; + layout (location = 4) in vec3 Normal; +#endif const float UV_INV = 1.0 / 32768.0; -//const vec3 POSITION_INV = vec3(1.0 / 1024.0); const vec3 POSITION_INV = vec3(1.0 / 2048.0); const vec3 POSITION_OFFSET = vec3(4.0); -void main() { +vec3 getVertexPosition() { const vec3 baseOffset = bitfieldExtract(ivec3(gl_InstanceIndex) >> ivec3(0, 16, 8), 0, 8); - const vec4 pos = vec4(fma(Position.xyz, POSITION_INV, ChunkOffset + baseOffset), 1.0); - gl_Position = MVP * pos; - vertexDistance = fog_distance(pos.xyz, 0); - vertexColor = Color * sample_lightmap2(Sampler2, Position.a); - texCoord0 = UV0 * UV_INV; + #ifdef COMPRESSED_VERTEX + return fma(Position.xyz, POSITION_INV, ModelOffset + baseOffset); + #else + return Position.xyz + baseOffset; + #endif } -////Default Vertex -//layout(location = 0) in vec3 Position; -//layout(location = 1) in vec4 Color; -//layout(location = 2) in vec2 UV0; -//layout(location = 3) in ivec2 UV2; -//layout(location = 4) in vec3 Normal; -// -//void main() { -// const vec3 baseOffset = bitfieldExtract(ivec3(gl_InstanceIndex) >> ivec3(0, 16, 8), 0, 8); -// const vec4 pos = vec4(Position.xyz + baseOffset, 1.0); -// gl_Position = MVP * pos; -// -// vertexDistance = length((ModelViewMat * pos).xyz); -// vertexColor = Color * minecraft_sample_lightmap(Sampler2, UV2); -// texCoord0 = UV0; -// // normal = MVP * vec4(Normal, 0.0); -//} \ No newline at end of file +void main() { + const vec3 pos = getVertexPosition(); + gl_Position = MVP * vec4(pos, 1.0); + + sphericalVertexDistance = fog_spherical_distance(pos); + cylindricalVertexDistance = fog_cylindrical_distance(pos); + + const vec4 Color = unpackUnorm4x8(PackedColor); + vertexColor = Color * sample_lightmap2(Sampler2, Position.a); + + texCoord0 = UV0 * UV_INV; +} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/basic/terrain/terrain_Z.fsh b/src/main/resources/assets/vulkanmod/shaders/basic/terrain/terrain_Z.fsh deleted file mode 100644 index b3d4faf58..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/basic/terrain/terrain_Z.fsh +++ /dev/null @@ -1,24 +0,0 @@ -#version 450 -layout(early_fragment_tests) in; -#include "light.glsl" -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO { - vec4 FogColor; - float FogStart; - float FogEnd; -}; - - -layout(location = 0) in float vertexDistance; -layout(location = 1) in vec4 vertexColor; -layout(location = 2) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor; - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} diff --git a/src/main/resources/assets/vulkanmod/shaders/basic/terrain_earlyZ/terrain_earlyZ.fsh b/src/main/resources/assets/vulkanmod/shaders/basic/terrain_earlyZ/terrain_earlyZ.fsh new file mode 100644 index 000000000..7be38bce7 --- /dev/null +++ b/src/main/resources/assets/vulkanmod/shaders/basic/terrain_earlyZ/terrain_earlyZ.fsh @@ -0,0 +1,30 @@ +#version 450 + +layout(early_fragment_tests) in; + +#include "light.glsl" +#include "fog.glsl" + +layout(binding = 2) uniform sampler2D Sampler0; + +layout(binding = 1) uniform UBO { + vec4 FogColor; + float FogEnvironmentalStart; + float FogEnvironmentalEnd; + float FogRenderDistanceStart; + float FogRenderDistanceEnd; + float FogSkyEnd; + float FogCloudsEnd; +}; + +layout(location = 0) in vec4 vertexColor; +layout(location = 1) in vec2 texCoord0; +layout(location = 2) in float sphericalVertexDistance; +layout(location = 3) in float cylindricalVertexDistance; + +layout(location = 0) out vec4 fragColor; + +void main() { + vec4 color = texture(Sampler0, texCoord0) * vertexColor; + fragColor = apply_fog(color, sphericalVertexDistance, cylindricalVertexDistance, FogEnvironmentalStart, FogEnvironmentalEnd, FogRenderDistanceStart, FogRenderDistanceEnd, FogColor); +} diff --git a/src/main/resources/assets/vulkanmod/shaders/basic/terrain_earlyZ/terrain_earlyZ.json b/src/main/resources/assets/vulkanmod/shaders/basic/terrain_earlyZ/terrain_earlyZ.json new file mode 100644 index 000000000..139dd2e2d --- /dev/null +++ b/src/main/resources/assets/vulkanmod/shaders/basic/terrain_earlyZ/terrain_earlyZ.json @@ -0,0 +1,26 @@ +{ + "vertex": "terrain", + "fragment": "terrain_earlyZ", + "samplers": [ + { "name": "Sampler0" }, + { "name": "Sampler2" } + ], + "UBOs": [ + { "type": "vertex", "binding": 0, "fields": [ + { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } + ] }, + { "type": "fragment", "binding": 1, "fields": [ + { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, + { "name": "FogEnvironmentalStart", "type": "float", "count": 1, "values": [ 0.0 ] }, + { "name": "FogEnvironmentalEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, + { "name": "FogRenderDistanceStart", "type": "float", "count": 1, "values": [ 1.0 ] }, + { "name": "FogRenderDistanceEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, + { "name": "FogSkyEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, + { "name": "FogCloudsEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, + { "name": "AlphaCutout", "type": "float", "count": 1, "values": [ 1.0 ] } + ] } + ], + "PushConstants": [ + { "name": "ModelOffset", "type": "float", "count": 3, "values": [ 0.0, 0.0, 0.0 ] } + ] +} diff --git a/src/main/resources/assets/vulkanmod/shaders/core/rendertype_item_entity_translucent_cull/rendertype_item_entity_translucent_cull.vsh b/src/main/resources/assets/vulkanmod/shaders/core/rendertype_item_entity_translucent_cull/rendertype_item_entity_translucent_cull.vsh new file mode 100644 index 000000000..a7db8154d --- /dev/null +++ b/src/main/resources/assets/vulkanmod/shaders/core/rendertype_item_entity_translucent_cull/rendertype_item_entity_translucent_cull.vsh @@ -0,0 +1,93 @@ +#version 330 + +#include "light.glsl" + +layout(std140) uniform Lighting { +vec3 Light0_Direction; +vec3 Light1_Direction; +}; + +layout(std140) uniform Fog { + vec4 FogColor; + float FogEnvironmentalStart; + float FogEnvironmentalEnd; + float FogRenderDistanceStart; + float FogRenderDistanceEnd; + float FogSkyEnd; + float FogCloudsEnd; +}; + +float linear_fog_value(float vertexDistance, float fogStart, float fogEnd) { + if (vertexDistance <= fogStart) { + return 0.0; + } else if (vertexDistance >= fogEnd) { + return 1.0; + } + + return (vertexDistance - fogStart) / (fogEnd - fogStart); +} + +float total_fog_value(float sphericalVertexDistance, float cylindricalVertexDistance, float environmentalStart, float environmantalEnd, float renderDistanceStart, float renderDistanceEnd) { + return max(linear_fog_value(sphericalVertexDistance, environmentalStart, environmantalEnd), linear_fog_value(cylindricalVertexDistance, renderDistanceStart, renderDistanceEnd)); +} + +vec4 apply_fog(vec4 inColor, float sphericalVertexDistance, float cylindricalVertexDistance, float environmentalStart, float environmantalEnd, float renderDistanceStart, float renderDistanceEnd, vec4 fogColor) { + float fogValue = total_fog_value(sphericalVertexDistance, cylindricalVertexDistance, environmentalStart, environmantalEnd, renderDistanceStart, renderDistanceEnd); + return vec4(mix(inColor.rgb, fogColor.rgb, fogValue * fogColor.a), inColor.a); +} + +float fog_spherical_distance(vec3 pos) { + return length(pos); +} + +float fog_cylindrical_distance(vec3 pos) { + float distXZ = length(pos.xz); + float distY = abs(pos.y); + return max(distXZ, distY); +} + +layout(std140) uniform DynamicTransforms { + mat4 ModelViewMat; + vec4 ColorModulator; + vec3 ModelOffset; + mat4 TextureMat; + float LineWidth; +}; + +layout(std140) uniform Projection { + mat4 ProjMat; +}; + +vec4 projection_from_position(vec4 position) { + vec4 projection = position * 0.5; + projection.xy = vec2(projection.x + projection.w, projection.y + projection.w); + projection.zw = position.zw; + return projection; +} + +in vec3 Position; +in vec4 Color; +in vec2 UV0; +in ivec2 UV1; +in ivec2 UV2; +in vec3 Normal; + +uniform sampler2D Sampler2; + +out float sphericalVertexDistance; +out float cylindricalVertexDistance; +out vec4 vertexColor; +out vec2 texCoord0; +out vec2 texCoord1; +out vec2 texCoord2; + +void main() { + gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0); + + sphericalVertexDistance = fog_spherical_distance(Position); + cylindricalVertexDistance = fog_cylindrical_distance(Position); + vertexColor = minecraft_mix_light(Light0_Direction, Light1_Direction, Normal, Color) * texelFetch(Sampler2, UV2 / 16, 0); + texCoord0 = UV0; + texCoord1 = UV1; + texCoord2 = UV2; +} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/core/screenquad/screenquad.vsh b/src/main/resources/assets/vulkanmod/shaders/core/screenquad/screenquad.vsh new file mode 100644 index 000000000..1c317cd74 --- /dev/null +++ b/src/main/resources/assets/vulkanmod/shaders/core/screenquad/screenquad.vsh @@ -0,0 +1,11 @@ +#version 330 + +out vec2 texCoord; + +void main() { + vec2 uv = vec2((gl_VertexID << 1) & 2, -(gl_VertexID & 2) + 1); + vec4 pos = vec4(uv * vec2(2, -2) + vec2(-1, +1), 0, 1); + + gl_Position = pos; + texCoord = uv; +} diff --git a/src/main/resources/assets/vulkanmod/shaders/include/fog.glsl b/src/main/resources/assets/vulkanmod/shaders/include/fog.glsl index 2322fb8e7..35fe1ad0f 100644 --- a/src/main/resources/assets/vulkanmod/shaders/include/fog.glsl +++ b/src/main/resources/assets/vulkanmod/shaders/include/fog.glsl @@ -21,3 +21,32 @@ float fog_distance(vec3 pos, int shape) { return max(distXZ, distY); } } + +float linear_fog_value(float vertexDistance, float fogStart, float fogEnd) { + if (vertexDistance <= fogStart) { + return 0.0; + } else if (vertexDistance >= fogEnd) { + return 1.0; + } + + return (vertexDistance - fogStart) / (fogEnd - fogStart); +} + +float total_fog_value(float sphericalVertexDistance, float cylindricalVertexDistance, float environmentalStart, float environmantalEnd, float renderDistanceStart, float renderDistanceEnd) { + return max(linear_fog_value(sphericalVertexDistance, environmentalStart, environmantalEnd), linear_fog_value(cylindricalVertexDistance, renderDistanceStart, renderDistanceEnd)); +} + +vec4 apply_fog(vec4 inColor, float sphericalVertexDistance, float cylindricalVertexDistance, float environmentalStart, float environmantalEnd, float renderDistanceStart, float renderDistanceEnd, vec4 fogColor) { + float fogValue = total_fog_value(sphericalVertexDistance, cylindricalVertexDistance, environmentalStart, environmantalEnd, renderDistanceStart, renderDistanceEnd); + return vec4(mix(inColor.rgb, fogColor.rgb, fogValue * fogColor.a), inColor.a); +} + +float fog_spherical_distance(vec3 pos) { + return length(pos); +} + +float fog_cylindrical_distance(vec3 pos) { + float distXZ = length(pos.xz); + float distY = abs(pos.y); + return max(distXZ, distY); +} diff --git a/src/main/resources/assets/vulkanmod/shaders/include/light.glsl b/src/main/resources/assets/vulkanmod/shaders/include/light.glsl index 3f95fb01a..0db8ac7b3 100644 --- a/src/main/resources/assets/vulkanmod/shaders/include/light.glsl +++ b/src/main/resources/assets/vulkanmod/shaders/include/light.glsl @@ -3,15 +3,6 @@ const float MINECRAFT_LIGHT_POWER = (0.6); const float MINECRAFT_AMBIENT_LIGHT = (0.4); -vec4 minecraft_mix_light(vec3 lightDir0, vec3 lightDir1, vec3 normal, vec4 color) { - lightDir0 = normalize(lightDir0); - lightDir1 = normalize(lightDir1); - float light0 = max(0.0, dot(lightDir0, normal)); - float light1 = max(0.0, dot(lightDir1, normal)); - float lightAccum = min(1.0, fma((light0 + light1), MINECRAFT_LIGHT_POWER, MINECRAFT_AMBIENT_LIGHT)); - return vec4(color.rgb * lightAccum, color.a); -} - vec4 minecraft_sample_lightmap(sampler2D lightMap, ivec2 uv) { return texelFetch(lightMap, bitfieldExtract(uv, 4, 8), 0); //return texture(lightMap, clamp(uv / 256.0, vec2(0.5 / 16.0), vec2(15.5 / 16.0))); @@ -26,3 +17,18 @@ vec4 sample_lightmap2(sampler2D lightMap, uint uv) { // const ivec2 lm = ivec2(uv >> 12, (uv >> 4) & 0xF); return texelFetch(lightMap, lm, 0); } + +vec2 minecraft_compute_light(vec3 lightDir0, vec3 lightDir1, vec3 normal) { + return vec2(dot(lightDir0, normal), dot(lightDir1, normal)); +} + +vec4 minecraft_mix_light_separate(vec2 light, vec4 color) { + vec2 lightValue = max(vec2(0.0), light); + float lightAccum = min(1.0, fma((lightValue.x + lightValue.y), MINECRAFT_LIGHT_POWER, MINECRAFT_AMBIENT_LIGHT)); + return vec4(color.rgb * lightAccum, color.a); +} + +vec4 minecraft_mix_light(vec3 lightDir0, vec3 lightDir1, vec3 normal, vec4 color) { + vec2 light = minecraft_compute_light(lightDir0, lightDir1, normal); + return minecraft_mix_light_separate(light, color); +} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/blit_screen/blit_screen.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/blit_screen/blit_screen.fsh deleted file mode 100644 index be1711e59..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/blit_screen/blit_screen.fsh +++ /dev/null @@ -1,14 +0,0 @@ -#version 450 - -layout(binding = 1) uniform sampler2D DiffuseSampler; - -layout(location = 0) in vec2 texCoord; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(DiffuseSampler, texCoord); - - // blit final output of compositor into displayed back buffer - fragColor = color; -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/blit_screen/blit_screen.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/blit_screen/blit_screen.json deleted file mode 100644 index bd9707c0e..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/blit_screen/blit_screen.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "blit_screen", - "fragment": "blit_screen", - "attributes": [ - "Position", - "UV", - "Color" - ], - "samplers": [], - "uniforms": [], - "UBOs": [] -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/blit_screen/blit_screen.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/blit_screen/blit_screen.vsh deleted file mode 100644 index e3dd01d3c..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/blit_screen/blit_screen.vsh +++ /dev/null @@ -1,12 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec2 UV; - -layout(location = 0) out vec2 texCoord; - -void main() { - gl_Position = vec4(Position, 1.0); - - texCoord = UV; -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/particle/particle.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/particle/particle.fsh deleted file mode 100644 index 7659168a5..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/particle/particle.fsh +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; -layout(location = 2) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; - if (color.a < 0.1) { - discard; - } - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/particle/particle.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/particle/particle.json deleted file mode 100644 index 6dddf404d..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/particle/particle.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "particle", - "fragment": "particle", - "attributes": [ - "Position", - "UV0", - "Color", - "UV2" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/particle/particle.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/particle/particle.vsh deleted file mode 100644 index 03430a48c..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/particle/particle.vsh +++ /dev/null @@ -1,26 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec2 UV0; -layout(location = 2) in vec4 Color; -layout(location = 3) in ivec2 UV2; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(binding = 3) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; -layout(location = 2) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - texCoord0 = UV0; - vertexColor = Color * texelFetch(Sampler2, UV2 / 16, 0); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position/position.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position/position.fsh deleted file mode 100644 index 3f5a88f37..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position/position.fsh +++ /dev/null @@ -1,17 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - fragColor = linear_fog(ColorModulator, vertexDistance, FogStart, FogEnd, FogColor); -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position/position.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position/position.json deleted file mode 100644 index ea9c19207..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position/position.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "position", - "fragment": "position", - "attributes": [], - "samplers": [], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position/position.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position/position.vsh deleted file mode 100644 index 3c348837f..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position/position.vsh +++ /dev/null @@ -1,17 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(location = 0) in vec3 Position; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(location = 0) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color/position_color.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color/position_color.fsh deleted file mode 100644 index fce9fa7c6..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color/position_color.fsh +++ /dev/null @@ -1,17 +0,0 @@ -#version 450 - -layout(location = 0) in vec4 vertexColor; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; -}; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = vertexColor; - if (color.a == 0.0) { - discard; - } - fragColor = color * ColorModulator; -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color/position_color.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color/position_color.json deleted file mode 100644 index fd537cf88..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color/position_color.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "position_color", - "fragment": "position_color", - "attributes": [ - "Color" - ], - "samplers": [], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color/position_color.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color/position_color.vsh deleted file mode 100644 index ebb1fafb9..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color/position_color.vsh +++ /dev/null @@ -1,16 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(location = 0) out vec4 vertexColor; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexColor = Color; -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_lightmap/position_color_lightmap.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_lightmap/position_color_lightmap.fsh deleted file mode 100644 index a94ccfc2e..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_lightmap/position_color_lightmap.fsh +++ /dev/null @@ -1,17 +0,0 @@ -#version 450 - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord2; - -layout(binding = 1) uniform UBO { - vec4 ColorModulator; -}; - -layout(binding = 2) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler2, texCoord2) * vertexColor; - fragColor = color * ColorModulator; -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_lightmap/position_color_lightmap.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_lightmap/position_color_lightmap.json deleted file mode 100644 index ad3eac50c..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_lightmap/position_color_lightmap.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "position_color_lightmap", - "fragment": "position_color_lightmap", - "attributes": [ - "Position", - "Color", - "UV2" - ], - "samplers": [ - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_lightmap/position_color_lightmap.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_lightmap/position_color_lightmap.vsh deleted file mode 100644 index 78f3e6d99..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_lightmap/position_color_lightmap.vsh +++ /dev/null @@ -1,19 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV2; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord2; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexColor = Color; - texCoord2 = UV2; -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_normal/position_color_normal.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_normal/position_color_normal.fsh deleted file mode 100644 index cf7099c9f..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_normal/position_color_normal.fsh +++ /dev/null @@ -1,49 +0,0 @@ -//#version 150 -// -//#moj_import -// -//uniform vec4 ColorModulator; -//uniform float FogStart; -//uniform float FogEnd; -//uniform vec4 FogColor; -// -//in float vertexDistance; -//in vec4 vertexColor; -//in vec4 normal; -// -//out vec4 fragColor; -// -//void main() { -// vec4 color = vertexColor * ColorModulator; -// if (color.a < 0.1) { -// discard; -// } -// fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -//} - -#version 450 - -#include - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - float FogStart; - float FogEnd; - vec4 FogColor; -}; - -layout(location = 0) in float vertexDistance; -layout(location = 1) in vec4 vertexColor; -layout(location = 2) in vec4 normal; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = vertexColor * ColorModulator; - if (color.a < 0.1) { - discard; - } - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_normal/position_color_normal.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_normal/position_color_normal.json deleted file mode 100644 index afe94f3c7..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_normal/position_color_normal.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "position_color_normal", - "fragment": "position_color_normal", - "attributes": [ - "Position", - "Color", - "Normal" - ], - "samplers": [], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_normal/position_color_normal.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_normal/position_color_normal.vsh deleted file mode 100644 index 456109004..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_normal/position_color_normal.vsh +++ /dev/null @@ -1,23 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(location = 0) out float vertexDistance; -layout(location = 1) out vec4 vertexColor; -layout(location = 2) out vec4 normal; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = Color; - normal = MVP * vec4(Normal, 0.0); -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_tex/position_color_tex.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_tex/position_color_tex.fsh deleted file mode 100644 index e1a3c7191..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_tex/position_color_tex.fsh +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor; - if (color.a < 0.1) { - discard; - } - fragColor = color * ColorModulator; -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_tex/position_color_tex.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_tex/position_color_tex.json deleted file mode 100644 index 4d92a81a6..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_tex/position_color_tex.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "position_color_tex", - "fragment": "position_color_tex", - "attributes": [ - "Position", - "Color", - "UV0" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_tex/position_color_tex.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_tex/position_color_tex.vsh deleted file mode 100644 index dd71051aa..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_tex/position_color_tex.vsh +++ /dev/null @@ -1,19 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexColor = Color; - texCoord0 = UV0; -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_tex_lightmap/position_color_tex_lightmap.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_tex_lightmap/position_color_tex_lightmap.fsh deleted file mode 100644 index e1a3c7191..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_tex_lightmap/position_color_tex_lightmap.fsh +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor; - if (color.a < 0.1) { - discard; - } - fragColor = color * ColorModulator; -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_tex_lightmap/position_color_tex_lightmap.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_tex_lightmap/position_color_tex_lightmap.json deleted file mode 100644 index f6b71e715..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_tex_lightmap/position_color_tex_lightmap.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "position_color_tex_lightmap", - "fragment": "position_color_tex_lightmap", - "attributes": [ - "Position", - "Color", - "UV0" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_tex_lightmap/position_color_tex_lightmap.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_tex_lightmap/position_color_tex_lightmap.vsh deleted file mode 100644 index 4c4d7f86e..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_color_tex_lightmap/position_color_tex_lightmap.vsh +++ /dev/null @@ -1,19 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexColor = Color; - texCoord0 = UV0; -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex/position_tex.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex/position_tex.fsh deleted file mode 100644 index d8a9e6c87..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex/position_tex.fsh +++ /dev/null @@ -1,19 +0,0 @@ -#version 450 - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; -}; - -layout(location = 0) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0); - if (color.a == 0.0) { - discard; - } - fragColor = color * ColorModulator; -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex/position_tex.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex/position_tex.json deleted file mode 100644 index 9f91a8dd3..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex/position_tex.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "position_tex", - "fragment": "position_tex", - "attributes": [ - "Position", - "UV0" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex/position_tex.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex/position_tex.vsh deleted file mode 100644 index 4abe8e465..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex/position_tex.vsh +++ /dev/null @@ -1,16 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec2 UV0; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(location = 0) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - texCoord0 = UV0; -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex_color/position_tex_color.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex_color/position_tex_color.fsh deleted file mode 100644 index e1a3c7191..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex_color/position_tex_color.fsh +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor; - if (color.a < 0.1) { - discard; - } - fragColor = color * ColorModulator; -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex_color/position_tex_color.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex_color/position_tex_color.json deleted file mode 100644 index e65c24526..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex_color/position_tex_color.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "position_tex_color", - "fragment": "position_tex_color", - "attributes": [ - "Position", - "UV0", - "Color" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex_color/position_tex_color.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex_color/position_tex_color.vsh deleted file mode 100644 index dd6470006..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex_color/position_tex_color.vsh +++ /dev/null @@ -1,19 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 Position; -layout(location = 2) in vec4 Color; -layout(location = 1) in vec2 UV0; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexColor = Color; - texCoord0 = UV0; -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex_color_normal/position_tex_color_normal.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex_color_normal/position_tex_color_normal.fsh deleted file mode 100644 index 0fcceefff..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex_color_normal/position_tex_color_normal.fsh +++ /dev/null @@ -1,27 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; -layout(location = 2) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; - if (color.a < 0.1) { - discard; - } - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} - - diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex_color_normal/position_tex_color_normal.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex_color_normal/position_tex_color_normal.json deleted file mode 100644 index 067700ceb..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex_color_normal/position_tex_color_normal.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "position_tex_color_normal", - "fragment": "position_tex_color_normal", - "attributes": [ - "Position", - "UV0", - "Color" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex_color_normal/position_tex_color_normal.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex_color_normal/position_tex_color_normal.vsh deleted file mode 100644 index e022017c3..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/position_tex_color_normal/position_tex_color_normal.vsh +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec2 UV0; -layout(location = 2) in vec4 Color; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; -layout(location = 2) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - texCoord0 = UV0; - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = Color; -} - - diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_cutout_no_cull/rendertype_armor_cutout_no_cull.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_cutout_no_cull/rendertype_armor_cutout_no_cull.fsh deleted file mode 100644 index 7659168a5..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_cutout_no_cull/rendertype_armor_cutout_no_cull.fsh +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; -layout(location = 2) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; - if (color.a < 0.1) { - discard; - } - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_cutout_no_cull/rendertype_armor_cutout_no_cull.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_cutout_no_cull/rendertype_armor_cutout_no_cull.json deleted file mode 100644 index aaf972afd..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_cutout_no_cull/rendertype_armor_cutout_no_cull.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_armor_cutout_no_cull", - "fragment": "rendertype_armor_cutout_no_cull", - "attributes": [ - "Position", - "Color", - "UV0", - "UV2", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_cutout_no_cull/rendertype_armor_cutout_no_cull.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_cutout_no_cull/rendertype_armor_cutout_no_cull.vsh deleted file mode 100644 index ea9fb38c1..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_cutout_no_cull/rendertype_armor_cutout_no_cull.vsh +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 - -#include "light.glsl" -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 4) in ivec2 UV2; -layout(location = 5) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - vec3 Light0_Direction; - vec3 Light1_Direction; -}; - -layout(binding = 3) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; -layout(location = 2) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = minecraft_mix_light(Light0_Direction, Light1_Direction, Normal, Color) * texelFetch(Sampler2, UV2 / 16, 0); - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_entity_glint/rendertype_armor_entity_glint.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_entity_glint/rendertype_armor_entity_glint.fsh deleted file mode 100644 index 8ffd06755..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_entity_glint/rendertype_armor_entity_glint.fsh +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - float FogStart; - float FogEnd; - float GlintAlpha; -}; - -layout(location = 0) in float vertexDistance; -layout(location = 1) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * ColorModulator; - if (color.a < 0.1) { - discard; - } - float fade = linear_fog_fade(vertexDistance, FogStart, FogEnd) * GlintAlpha; - fragColor = vec4(color.rgb * fade, color.a); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_entity_glint/rendertype_armor_entity_glint.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_entity_glint/rendertype_armor_entity_glint.json deleted file mode 100644 index 9ab1295ed..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_entity_glint/rendertype_armor_entity_glint.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_armor_entity_glint", - "fragment": "rendertype_armor_entity_glint", - "attributes": [ - "Position", - "UV0" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "TextureMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "TextureMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "GlintAlpha", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_entity_glint/rendertype_armor_entity_glint.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_entity_glint/rendertype_armor_entity_glint.vsh deleted file mode 100644 index 71aa44c51..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_entity_glint/rendertype_armor_entity_glint.vsh +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec2 UV0; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - mat4 TextureMat; -}; - -layout(location = 0) out float vertexDistance; -layout(location = 1) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - texCoord0 = (TextureMat * vec4(UV0, 0.0, 1.0)).xy; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_glint/rendertype_armor_glint.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_glint/rendertype_armor_glint.fsh deleted file mode 100644 index 8ffd06755..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_glint/rendertype_armor_glint.fsh +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - float FogStart; - float FogEnd; - float GlintAlpha; -}; - -layout(location = 0) in float vertexDistance; -layout(location = 1) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * ColorModulator; - if (color.a < 0.1) { - discard; - } - float fade = linear_fog_fade(vertexDistance, FogStart, FogEnd) * GlintAlpha; - fragColor = vec4(color.rgb * fade, color.a); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_glint/rendertype_armor_glint.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_glint/rendertype_armor_glint.json deleted file mode 100644 index 33c472d39..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_glint/rendertype_armor_glint.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_armor_glint", - "fragment": "rendertype_armor_glint", - "attributes": [ - "Position", - "UV0" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "TextureMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "TextureMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "GlintAlpha", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_glint/rendertype_armor_glint.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_glint/rendertype_armor_glint.vsh deleted file mode 100644 index 71aa44c51..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_armor_glint/rendertype_armor_glint.vsh +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec2 UV0; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - mat4 TextureMat; -}; - -layout(location = 0) out float vertexDistance; -layout(location = 1) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - texCoord0 = (TextureMat * vec4(UV0, 0.0, 1.0)).xy; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_beacon_beam/rendertype_beacon_beam.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_beacon_beam/rendertype_beacon_beam.fsh deleted file mode 100644 index 3e0d10ea6..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_beacon_beam/rendertype_beacon_beam.fsh +++ /dev/null @@ -1,27 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 0) uniform UniformBufferObject { - mat4 ProjMat; -}; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0); - color *= vertexColor * ColorModulator; - float fragmentDistance = -ProjMat[3].z / ((gl_FragCoord.z) * -2.0 + 1.0 - ProjMat[2].z); - fragColor = linear_fog(color, fragmentDistance, FogStart, FogEnd, FogColor); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_beacon_beam/rendertype_beacon_beam.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_beacon_beam/rendertype_beacon_beam.json deleted file mode 100644 index 846056264..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_beacon_beam/rendertype_beacon_beam.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_beacon_beam", - "fragment": "rendertype_beacon_beam", - "attributes": [ - "Position", - "Color", - "UV0" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "all", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_beacon_beam/rendertype_beacon_beam.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_beacon_beam/rendertype_beacon_beam.vsh deleted file mode 100644 index 817669d61..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_beacon_beam/rendertype_beacon_beam.vsh +++ /dev/null @@ -1,19 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexColor = Color; - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_breeze_wind/rendertype_breeze_wind.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_breeze_wind/rendertype_breeze_wind.fsh deleted file mode 100644 index 52cbfe5e5..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_breeze_wind/rendertype_breeze_wind.fsh +++ /dev/null @@ -1,24 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in float vertexDistance; -layout(location = 1) in vec4 vertexColor; -layout(location = 3) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; - if (color.a < 0.1) { - discard; - } - fragColor = color * linear_fog_fade(vertexDistance, FogStart, FogEnd); -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_breeze_wind/rendertype_breeze_wind.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_breeze_wind/rendertype_breeze_wind.json deleted file mode 100644 index 17a3bd328..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_breeze_wind/rendertype_breeze_wind.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_breeze_wind", - "fragment": "rendertype_breeze_wind", - "attributes": [ - "Position", - "Color", - "UV0", - "UV2" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "TextureMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogShape", "type": "int", "count": 1, "values": [ 0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "TextureMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "FogShape", "type": "int", "count": 1, "values": [ 0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_breeze_wind/rendertype_breeze_wind.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_breeze_wind/rendertype_breeze_wind.vsh deleted file mode 100644 index 714c6e1a7..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_breeze_wind/rendertype_breeze_wind.vsh +++ /dev/null @@ -1,33 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 4) in ivec2 UV2; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - mat4 ModelViewMat; - mat4 TextureMat; - int FogShape; -}; - -layout(binding = 4) uniform sampler2D Sampler2; - -layout(location = 0) out float vertexDistance; -layout(location = 1) out vec4 vertexColor; -layout(location = 2) out vec4 lightMapColor; -layout(location = 3) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vec4 pos = ModelViewMat * (Position, 1.0); - vertexDistance = fog_distance(pos.xyz, FogShape); - lightMapColor = texelFetch(Sampler2, UV2 / 16, 0); - vertexColor = Color * lightMapColor; - - texCoord0 = (TextureMat * vec4(UV0, 0.0, 1.0)).xy; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_clouds/rendertype_clouds.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_clouds/rendertype_clouds.fsh deleted file mode 100644 index db89144f5..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_clouds/rendertype_clouds.fsh +++ /dev/null @@ -1,51 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; -layout(location = 2) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; - if (color.a < 0.1) { - discard; - } - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} - -//#version 150 -// -//#moj_import -// -//uniform sampler2D Sampler0; -// -//uniform vec4 ColorModulator; -//uniform float FogStart; -//uniform float FogEnd; -//uniform vec4 FogColor; -// -//in vec2 texCoord0; -//in float vertexDistance; -//in vec4 vertexColor; -// -//out vec4 fragColor; -// -//void main() { -// vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; -// if (color.a < 0.1) { -// discard; -// } -// fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -//} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_clouds/rendertype_clouds.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_clouds/rendertype_clouds.json deleted file mode 100644 index 7798d39af..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_clouds/rendertype_clouds.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_clouds", - "fragment": "rendertype_clouds", - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogShape", "type": "int", "count": 1, "values": [ 0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "FogShape", "type": "int", "count": 1, "values": [ 0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_clouds/rendertype_clouds.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_clouds/rendertype_clouds.vsh deleted file mode 100644 index 289748aef..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_clouds/rendertype_clouds.vsh +++ /dev/null @@ -1,54 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec2 UV0; -layout(location = 2) in vec4 Color; -layout(location = 3) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - mat4 ModelViewMat; - int FogShape; -}; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; -layout(location = 2) out float vertexDistance; -layout(location = 3) out vec3 normal; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - texCoord0 = UV0; - vec4 pos = ModelViewMat * vec4(Position, 1.0); - vertexDistance = fog_distance(pos.xyz, FogShape); - vertexColor = Color; -} - -//#version 150 -// -//#moj_import -// -//in vec3 Position; -//in vec2 UV0; -//in vec4 Color; -//in vec3 Normal; -// -//uniform mat4 ModelViewMat; -//uniform mat4 ProjMat; -//uniform int FogShape; -// -//out vec2 texCoord0; -//out float vertexDistance; -//out vec4 vertexColor; -// -//void main() { -// vec4 pos = ModelViewMat * vec4(Position, 1.0); -// gl_Position = ProjMat * pos; -// -// texCoord0 = UV0; -// vertexDistance = fog_distance(pos.xyz, FogShape); -// vertexColor = Color; -//} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_crumbling/rendertype_crumbling.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_crumbling/rendertype_crumbling.fsh deleted file mode 100644 index 68a45f590..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_crumbling/rendertype_crumbling.fsh +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor; - if (color.a < 0.1) { - discard; - } - fragColor = color * ColorModulator; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_crumbling/rendertype_crumbling.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_crumbling/rendertype_crumbling.json deleted file mode 100644 index 52c1c7608..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_crumbling/rendertype_crumbling.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_crumbling", - "fragment": "rendertype_crumbling", - "attributes": [ - "Position", - "Color", - "UV0", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_crumbling/rendertype_crumbling.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_crumbling/rendertype_crumbling.vsh deleted file mode 100644 index d55f8be78..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_crumbling/rendertype_crumbling.vsh +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 4) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexColor = Color; - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_cutout/rendertype_cutout.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_cutout/rendertype_cutout.fsh deleted file mode 100644 index a0259eb00..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_cutout/rendertype_cutout.fsh +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in float vertexDistance; -layout(location = 1) in vec4 vertexColor; -layout(location = 2) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; - if (color.a < 0.1) { - discard; - } - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_cutout/rendertype_cutout.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_cutout/rendertype_cutout.json deleted file mode 100644 index 225b0c073..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_cutout/rendertype_cutout.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_cutout", - "fragment": "rendertype_cutout", - "attributes": [ - "Position", - "Color", - "UV0", - "UV2", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_cutout/rendertype_cutout.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_cutout/rendertype_cutout.vsh deleted file mode 100644 index 901a6df43..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_cutout/rendertype_cutout.vsh +++ /dev/null @@ -1,28 +0,0 @@ -#version 450 - -#include "light.glsl" -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 3) in ivec2 UV2; -layout(location = 4) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(binding = 3) uniform sampler2D Sampler2; - -layout(location = 0) out float vertexDistance; -layout(location = 1) out vec4 vertexColor; -layout(location = 2) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = Color * minecraft_sample_lightmap(Sampler2, UV2); - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_cutout_mipped/rendertype_cutout_mipped.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_cutout_mipped/rendertype_cutout_mipped.fsh deleted file mode 100644 index fd4834eda..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_cutout_mipped/rendertype_cutout_mipped.fsh +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in float vertexDistance; -layout(location = 1) in vec4 vertexColor; -layout(location = 2) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; - if (color.a < 0.5) { - discard; - } - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_cutout_mipped/rendertype_cutout_mipped.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_cutout_mipped/rendertype_cutout_mipped.json deleted file mode 100644 index 3cc4ad811..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_cutout_mipped/rendertype_cutout_mipped.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_cutout_mipped", - "fragment": "rendertype_cutout_mipped", - "attributes": [ - "Position", - "Color", - "UV0", - "UV2", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_cutout_mipped/rendertype_cutout_mipped.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_cutout_mipped/rendertype_cutout_mipped.vsh deleted file mode 100644 index 901a6df43..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_cutout_mipped/rendertype_cutout_mipped.vsh +++ /dev/null @@ -1,28 +0,0 @@ -#version 450 - -#include "light.glsl" -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 3) in ivec2 UV2; -layout(location = 4) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(binding = 3) uniform sampler2D Sampler2; - -layout(location = 0) out float vertexDistance; -layout(location = 1) out vec4 vertexColor; -layout(location = 2) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = Color * minecraft_sample_lightmap(Sampler2, UV2); - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_end_portal/rendertype_end_portal.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_end_portal/rendertype_end_portal.fsh deleted file mode 100644 index d41c5f745..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_end_portal/rendertype_end_portal.fsh +++ /dev/null @@ -1,69 +0,0 @@ -#version 450 - -mat2 mat2_rotate_z(float radians) { - return mat2( - cos(radians), -sin(radians), - sin(radians), cos(radians) - ); -} - -layout(location = 0) in vec4 texProj0; - -layout(binding = 1) uniform UniformBufferObject { - float GameTime; - int EndPortalLayers; -}; - -layout(binding = 2) uniform sampler2D Sampler0; -layout(binding = 3) uniform sampler2D Sampler1; - -const vec3[] COLORS = vec3[]( - vec3(0.022087, 0.098399, 0.110818), - vec3(0.011892, 0.095924, 0.089485), - vec3(0.027636, 0.101689, 0.100326), - vec3(0.046564, 0.109883, 0.114838), - vec3(0.064901, 0.117696, 0.097189), - vec3(0.063761, 0.086895, 0.123646), - vec3(0.084817, 0.111994, 0.166380), - vec3(0.097489, 0.154120, 0.091064), - vec3(0.106152, 0.131144, 0.195191), - vec3(0.097721, 0.110188, 0.187229), - vec3(0.133516, 0.138278, 0.148582), - vec3(0.070006, 0.243332, 0.235792), - vec3(0.196766, 0.142899, 0.214696), - vec3(0.047281, 0.315338, 0.321970), - vec3(0.204675, 0.390010, 0.302066), - vec3(0.080955, 0.314821, 0.661491) -); - -const mat4 SCALE_TRANSLATE = mat4( - 0.5, 0.0, 0.0, 0.25, - 0.0, 0.5, 0.0, 0.25, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0 -); - -mat4 end_portal_layer(float layer) { - mat4 translate = mat4( - 1.0, 0.0, 0.0, 17.0 / layer, - 0.0, 1.0, 0.0, (2.0 + layer / 1.5) * (GameTime * 1.5), - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0 - ); - - mat2 rotate = mat2_rotate_z(radians((layer * layer * 4321.0 + layer * 9.0) * 2.0)); - - mat2 scale = mat2((4.5 - layer / 4.0) * 2.0); - - return mat4(scale * rotate) * translate * SCALE_TRANSLATE; -} - -layout(location = 0) out vec4 fragColor; - -void main() { - vec3 color = textureProj(Sampler0, texProj0).rgb * COLORS[0]; - for (int i = 0; i < EndPortalLayers; i++) { - color += textureProj(Sampler1, texProj0 * end_portal_layer(float(i + 1))).rgb * COLORS[i]; - } - fragColor = vec4(color, 1.0); -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_end_portal/rendertype_end_portal.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_end_portal/rendertype_end_portal.json deleted file mode 100644 index 8854d96e4..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_end_portal/rendertype_end_portal.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_end_portal", - "fragment": "rendertype_end_portal", - "attributes": [], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler1" } - ], - "uniforms": [ - { "name": "GameTime", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "EndPortalLayers", "type": "int", "count": 1, "values": [ 15 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "GameTime", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "EndPortalLayers", "type": "int", "count": 1, "values": [ 15 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_end_portal/rendertype_end_portal.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_end_portal/rendertype_end_portal.vsh deleted file mode 100644 index f85a742f1..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_end_portal/rendertype_end_portal.vsh +++ /dev/null @@ -1,23 +0,0 @@ -#version 450 - -//projection.glsl -vec4 projection_from_position(vec4 position) { - vec4 projection = position * 0.5; - projection.xy = vec2(projection.x + projection.w, projection.y + projection.w); - projection.zw = position.zw; - return projection; -} - -layout(location = 0) in vec3 Position; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(location = 0) out vec4 texProj0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - texProj0 = projection_from_position(gl_Position); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_energy_swirl/rendertype_energy_swirl.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_energy_swirl/rendertype_energy_swirl.fsh deleted file mode 100644 index 3f347be38..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_energy_swirl/rendertype_energy_swirl.fsh +++ /dev/null @@ -1,24 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in float vertexDistance; -layout(location = 1) in vec4 vertexColor; -layout(location = 2) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; - if (color.a < 0.1) { - discard; - } - fragColor = color * linear_fog_fade(vertexDistance, FogStart, FogEnd); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_energy_swirl/rendertype_energy_swirl.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_energy_swirl/rendertype_energy_swirl.json deleted file mode 100644 index a47d5e123..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_energy_swirl/rendertype_energy_swirl.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_energy_swirl", - "fragment": "rendertype_energy_swirl", - "attributes": [ - "Position", - "Color", - "UV0" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "TextureMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "TextureMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_energy_swirl/rendertype_energy_swirl.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_energy_swirl/rendertype_energy_swirl.vsh deleted file mode 100644 index f005d2760..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_energy_swirl/rendertype_energy_swirl.vsh +++ /dev/null @@ -1,24 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - mat4 TextureMat; -}; - -layout(location = 0) out float vertexDistance; -layout(location = 1) out vec4 vertexColor; -layout(location = 2) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = Color; - texCoord0 = (TextureMat * vec4(UV0, 0.0, 1.0)).xy; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_alpha/rendertype_entity_alpha.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_alpha/rendertype_entity_alpha.fsh deleted file mode 100644 index 5da52f811..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_alpha/rendertype_entity_alpha.fsh +++ /dev/null @@ -1,16 +0,0 @@ -#version 450 - -layout(binding = 1) uniform sampler2D Sampler0; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0); - if (color.a < vertexColor.a) { - discard; - } - fragColor = color; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_alpha/rendertype_entity_alpha.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_alpha/rendertype_entity_alpha.json deleted file mode 100644 index 4caff8079..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_alpha/rendertype_entity_alpha.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_entity_alpha", - "fragment": "rendertype_entity_alpha", - "attributes": [ - "Position", - "Color", - "UV0", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] } - - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_alpha/rendertype_entity_alpha.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_alpha/rendertype_entity_alpha.vsh deleted file mode 100644 index 200022c8e..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_alpha/rendertype_entity_alpha.vsh +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 5) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; - - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexColor = Color; - texCoord0 = UV0; -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout/rendertype_entity_cutout.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout/rendertype_entity_cutout.fsh deleted file mode 100644 index 29fd0268f..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout/rendertype_entity_cutout.fsh +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec4 lightMapColor; -layout(location = 2) in vec4 overlayColor; -layout(location = 3) in vec2 texCoord0; -layout(location = 4) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0); - if (color.a < 0.1) { - discard; - } - color *= vertexColor * ColorModulator; - color.rgb = mix(overlayColor.rgb, color.rgb, overlayColor.a); - color *= lightMapColor; - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout/rendertype_entity_cutout.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout/rendertype_entity_cutout.json deleted file mode 100644 index 51ae16d55..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout/rendertype_entity_cutout.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_entity_cutout", - "fragment": "rendertype_entity_cutout", - "attributes": [ - "Position", - "Color", - "UV0", - "UV1", - "UV2", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler1" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout/rendertype_entity_cutout.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout/rendertype_entity_cutout.vsh deleted file mode 100644 index 46038952c..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout/rendertype_entity_cutout.vsh +++ /dev/null @@ -1,36 +0,0 @@ -#version 450 - -#include "light.glsl" -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 3) in ivec2 UV1; -layout(location = 4) in ivec2 UV2; -layout(location = 5) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - vec3 Light0_Direction; - vec3 Light1_Direction; -}; - -layout(binding = 3) uniform sampler2D Sampler1; -layout(binding = 4) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec4 lightMapColor; -layout(location = 2) out vec4 overlayColor; -layout(location = 3) out vec2 texCoord0; -layout(location = 4) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = minecraft_mix_light(Light0_Direction, Light1_Direction, Normal, Color); - lightMapColor = texelFetch(Sampler2, UV2 / 16, 0); - overlayColor = texelFetch(Sampler1, UV1, 0); - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout_no_cull/rendertype_entity_cutout_no_cull.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout_no_cull/rendertype_entity_cutout_no_cull.fsh deleted file mode 100644 index fe257648a..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout_no_cull/rendertype_entity_cutout_no_cull.fsh +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec4 lightMapColor; -layout(location = 2) in vec4 overlayColor; -layout(location = 3) in vec2 texCoord0; -layout(location = 4) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0); - if (color.a < 0.1) { - discard; - } - color *= vertexColor * ColorModulator; - color.rgb = mix(overlayColor.rgb, color.rgb, overlayColor.a); - color *= lightMapColor; - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout_no_cull/rendertype_entity_cutout_no_cull.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout_no_cull/rendertype_entity_cutout_no_cull.json deleted file mode 100644 index d04943b44..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout_no_cull/rendertype_entity_cutout_no_cull.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_entity_cutout_no_cull", - "fragment": "rendertype_entity_cutout_no_cull", - "attributes": [ - "Position", - "Color", - "UV0", - "UV1", - "UV2", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler1" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout_no_cull/rendertype_entity_cutout_no_cull.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout_no_cull/rendertype_entity_cutout_no_cull.vsh deleted file mode 100644 index 46038952c..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout_no_cull/rendertype_entity_cutout_no_cull.vsh +++ /dev/null @@ -1,36 +0,0 @@ -#version 450 - -#include "light.glsl" -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 3) in ivec2 UV1; -layout(location = 4) in ivec2 UV2; -layout(location = 5) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - vec3 Light0_Direction; - vec3 Light1_Direction; -}; - -layout(binding = 3) uniform sampler2D Sampler1; -layout(binding = 4) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec4 lightMapColor; -layout(location = 2) out vec4 overlayColor; -layout(location = 3) out vec2 texCoord0; -layout(location = 4) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = minecraft_mix_light(Light0_Direction, Light1_Direction, Normal, Color); - lightMapColor = texelFetch(Sampler2, UV2 / 16, 0); - overlayColor = texelFetch(Sampler1, UV1, 0); - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout_no_cull_z_offset/rendertype_entity_cutout_no_cull_z_offset.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout_no_cull_z_offset/rendertype_entity_cutout_no_cull_z_offset.fsh deleted file mode 100644 index fe257648a..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout_no_cull_z_offset/rendertype_entity_cutout_no_cull_z_offset.fsh +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec4 lightMapColor; -layout(location = 2) in vec4 overlayColor; -layout(location = 3) in vec2 texCoord0; -layout(location = 4) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0); - if (color.a < 0.1) { - discard; - } - color *= vertexColor * ColorModulator; - color.rgb = mix(overlayColor.rgb, color.rgb, overlayColor.a); - color *= lightMapColor; - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout_no_cull_z_offset/rendertype_entity_cutout_no_cull_z_offset.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout_no_cull_z_offset/rendertype_entity_cutout_no_cull_z_offset.json deleted file mode 100644 index 45caf5fb9..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout_no_cull_z_offset/rendertype_entity_cutout_no_cull_z_offset.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_entity_cutout_no_cull_z_offset", - "fragment": "rendertype_entity_cutout_no_cull_z_offset", - "attributes": [ - "Position", - "Color", - "UV0", - "UV1", - "UV2", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler1" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout_no_cull_z_offset/rendertype_entity_cutout_no_cull_z_offset.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout_no_cull_z_offset/rendertype_entity_cutout_no_cull_z_offset.vsh deleted file mode 100644 index 76e60cbae..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_cutout_no_cull_z_offset/rendertype_entity_cutout_no_cull_z_offset.vsh +++ /dev/null @@ -1,36 +0,0 @@ -#version 450 - -#include "light.glsl" -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 3) in ivec2 UV1; -layout(location = 4) in ivec2 UV2; -layout(location = 5) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - vec3 Light0_Direction; - vec3 Light1_Direction; -}; - -layout(binding = 3) uniform sampler2D Sampler1; -layout(binding = 4) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec4 lightMapColor; -layout(location = 2) out vec4 overlayColor; -layout(location = 3) out vec2 texCoord0; -layout(location = 4) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = minecraft_mix_light(Light0_Direction, Light1_Direction, Normal, Color); - lightMapColor = texelFetch(Sampler2, UV2 / 16, 0); - overlayColor = texelFetch(Sampler1, UV1, 0); - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_decal/rendertype_entity_decal.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_decal/rendertype_entity_decal.fsh deleted file mode 100644 index 23563e8a6..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_decal/rendertype_entity_decal.fsh +++ /dev/null @@ -1,28 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec4 overlayColor; -layout(location = 2) in vec2 texCoord0; -layout(location = 3) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0); - if (color.a < 0.1) { - discard; - } - color.rgb = mix(overlayColor.rgb, color.rgb, overlayColor.a); - color *= vertexColor * ColorModulator; - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_decal/rendertype_entity_decal.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_decal/rendertype_entity_decal.json deleted file mode 100644 index 7ff513675..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_decal/rendertype_entity_decal.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_entity_decal", - "fragment": "rendertype_entity_decal", - "attributes": [ - "Position", - "Color", - "UV0", - "UV1", - "UV2", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler1" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_decal/rendertype_entity_decal.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_decal/rendertype_entity_decal.vsh deleted file mode 100644 index e63fafd90..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_decal/rendertype_entity_decal.vsh +++ /dev/null @@ -1,34 +0,0 @@ -#version 450 - -#include "light.glsl" -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 3) in ivec2 UV1; -layout(location = 4) in ivec2 UV2; -layout(location = 5) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - vec3 Light0_Direction; - vec3 Light1_Direction; -}; - -layout(binding = 3) uniform sampler2D Sampler1; -layout(binding = 4) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec4 overlayColor; -layout(location = 2) out vec2 texCoord0; -layout(location = 3) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = minecraft_mix_light(Light0_Direction, Light1_Direction, Normal, Color) * texelFetch(Sampler2, UV2 / 16, 0); - overlayColor = texelFetch(Sampler1, UV1, 0); - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_glint/rendertype_entity_glint.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_glint/rendertype_entity_glint.fsh deleted file mode 100644 index 8ffd06755..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_glint/rendertype_entity_glint.fsh +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - float FogStart; - float FogEnd; - float GlintAlpha; -}; - -layout(location = 0) in float vertexDistance; -layout(location = 1) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * ColorModulator; - if (color.a < 0.1) { - discard; - } - float fade = linear_fog_fade(vertexDistance, FogStart, FogEnd) * GlintAlpha; - fragColor = vec4(color.rgb * fade, color.a); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_glint/rendertype_entity_glint.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_glint/rendertype_entity_glint.json deleted file mode 100644 index 669060bd4..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_glint/rendertype_entity_glint.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_entity_glint", - "fragment": "rendertype_entity_glint", - "attributes": [ - "Position", - "UV0" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "TextureMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "TextureMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "GlintAlpha", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_glint/rendertype_entity_glint.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_glint/rendertype_entity_glint.vsh deleted file mode 100644 index 71aa44c51..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_glint/rendertype_entity_glint.vsh +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec2 UV0; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - mat4 TextureMat; -}; - -layout(location = 0) out float vertexDistance; -layout(location = 1) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - texCoord0 = (TextureMat * vec4(UV0, 0.0, 1.0)).xy; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_glint_direct/rendertype_entity_glint_direct.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_glint_direct/rendertype_entity_glint_direct.fsh deleted file mode 100644 index 8ffd06755..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_glint_direct/rendertype_entity_glint_direct.fsh +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - float FogStart; - float FogEnd; - float GlintAlpha; -}; - -layout(location = 0) in float vertexDistance; -layout(location = 1) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * ColorModulator; - if (color.a < 0.1) { - discard; - } - float fade = linear_fog_fade(vertexDistance, FogStart, FogEnd) * GlintAlpha; - fragColor = vec4(color.rgb * fade, color.a); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_glint_direct/rendertype_entity_glint_direct.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_glint_direct/rendertype_entity_glint_direct.json deleted file mode 100644 index b7f6179a0..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_glint_direct/rendertype_entity_glint_direct.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_entity_glint_direct", - "fragment": "rendertype_entity_glint_direct", - "attributes": [ - "Position", - "UV0" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "TextureMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "TextureMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "GlintAlpha", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_glint_direct/rendertype_entity_glint_direct.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_glint_direct/rendertype_entity_glint_direct.vsh deleted file mode 100644 index 71aa44c51..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_glint_direct/rendertype_entity_glint_direct.vsh +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec2 UV0; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - mat4 TextureMat; -}; - -layout(location = 0) out float vertexDistance; -layout(location = 1) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - texCoord0 = (TextureMat * vec4(UV0, 0.0, 1.0)).xy; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_no_outline/rendertype_entity_no_outline.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_no_outline/rendertype_entity_no_outline.fsh deleted file mode 100644 index d44254ed4..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_no_outline/rendertype_entity_no_outline.fsh +++ /dev/null @@ -1,22 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; -layout(location = 2) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_no_outline/rendertype_entity_no_outline.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_no_outline/rendertype_entity_no_outline.json deleted file mode 100644 index 4a9b8f495..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_no_outline/rendertype_entity_no_outline.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_entity_no_outline", - "fragment": "rendertype_entity_no_outline", - "attributes": [ - "Position", - "Color", - "UV0", - "UV2", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_no_outline/rendertype_entity_no_outline.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_no_outline/rendertype_entity_no_outline.vsh deleted file mode 100644 index ea9fb38c1..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_no_outline/rendertype_entity_no_outline.vsh +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 - -#include "light.glsl" -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 4) in ivec2 UV2; -layout(location = 5) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - vec3 Light0_Direction; - vec3 Light1_Direction; -}; - -layout(binding = 3) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; -layout(location = 2) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = minecraft_mix_light(Light0_Direction, Light1_Direction, Normal, Color) * texelFetch(Sampler2, UV2 / 16, 0); - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_shadow/rendertype_entity_shadow.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_shadow/rendertype_entity_shadow.fsh deleted file mode 100644 index 4ee8e3d7d..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_shadow/rendertype_entity_shadow.fsh +++ /dev/null @@ -1,18 +0,0 @@ -#version 450 - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, clamp(texCoord0, 0.0, 1.0)); - color *= vertexColor * ColorModulator; - fragColor = color; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_shadow/rendertype_entity_shadow.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_shadow/rendertype_entity_shadow.json deleted file mode 100644 index 96628895f..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_shadow/rendertype_entity_shadow.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_entity_shadow", - "fragment": "rendertype_entity_shadow", - "attributes": [ - "Position", - "Color", - "UV0" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_shadow/rendertype_entity_shadow.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_shadow/rendertype_entity_shadow.vsh deleted file mode 100644 index 817669d61..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_shadow/rendertype_entity_shadow.vsh +++ /dev/null @@ -1,19 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexColor = Color; - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_smooth_cutout/rendertype_entity_smooth_cutout.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_smooth_cutout/rendertype_entity_smooth_cutout.fsh deleted file mode 100644 index fe257648a..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_smooth_cutout/rendertype_entity_smooth_cutout.fsh +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec4 lightMapColor; -layout(location = 2) in vec4 overlayColor; -layout(location = 3) in vec2 texCoord0; -layout(location = 4) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0); - if (color.a < 0.1) { - discard; - } - color *= vertexColor * ColorModulator; - color.rgb = mix(overlayColor.rgb, color.rgb, overlayColor.a); - color *= lightMapColor; - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_smooth_cutout/rendertype_entity_smooth_cutout.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_smooth_cutout/rendertype_entity_smooth_cutout.json deleted file mode 100644 index c3f9d7219..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_smooth_cutout/rendertype_entity_smooth_cutout.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_entity_smooth_cutout", - "fragment": "rendertype_entity_smooth_cutout", - "attributes": [ - "Position", - "Color", - "UV0", - "UV1", - "UV2", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler1" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_smooth_cutout/rendertype_entity_smooth_cutout.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_smooth_cutout/rendertype_entity_smooth_cutout.vsh deleted file mode 100644 index 46038952c..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_smooth_cutout/rendertype_entity_smooth_cutout.vsh +++ /dev/null @@ -1,36 +0,0 @@ -#version 450 - -#include "light.glsl" -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 3) in ivec2 UV1; -layout(location = 4) in ivec2 UV2; -layout(location = 5) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - vec3 Light0_Direction; - vec3 Light1_Direction; -}; - -layout(binding = 3) uniform sampler2D Sampler1; -layout(binding = 4) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec4 lightMapColor; -layout(location = 2) out vec4 overlayColor; -layout(location = 3) out vec2 texCoord0; -layout(location = 4) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = minecraft_mix_light(Light0_Direction, Light1_Direction, Normal, Color); - lightMapColor = texelFetch(Sampler2, UV2 / 16, 0); - overlayColor = texelFetch(Sampler1, UV1, 0); - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_solid/rendertype_entity_solid.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_solid/rendertype_entity_solid.fsh deleted file mode 100644 index 0046a9483..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_solid/rendertype_entity_solid.fsh +++ /dev/null @@ -1,26 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec4 lightMapColor; -layout(location = 2) in vec4 overlayColor; -layout(location = 3) in vec2 texCoord0; -layout(location = 4) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; - color.rgb = mix(overlayColor.rgb, color.rgb, overlayColor.a); - color *= lightMapColor; - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_solid/rendertype_entity_solid.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_solid/rendertype_entity_solid.json deleted file mode 100644 index e3d0c8b9d..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_solid/rendertype_entity_solid.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_entity_solid", - "fragment": "rendertype_entity_solid", - "attributes": [ - "Position", - "Color", - "UV0", - "UV1", - "UV2", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler1" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_solid/rendertype_entity_solid.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_solid/rendertype_entity_solid.vsh deleted file mode 100644 index 46038952c..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_solid/rendertype_entity_solid.vsh +++ /dev/null @@ -1,36 +0,0 @@ -#version 450 - -#include "light.glsl" -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 3) in ivec2 UV1; -layout(location = 4) in ivec2 UV2; -layout(location = 5) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - vec3 Light0_Direction; - vec3 Light1_Direction; -}; - -layout(binding = 3) uniform sampler2D Sampler1; -layout(binding = 4) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec4 lightMapColor; -layout(location = 2) out vec4 overlayColor; -layout(location = 3) out vec2 texCoord0; -layout(location = 4) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = minecraft_mix_light(Light0_Direction, Light1_Direction, Normal, Color); - lightMapColor = texelFetch(Sampler2, UV2 / 16, 0); - overlayColor = texelFetch(Sampler1, UV1, 0); - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent/rendertype_entity_translucent.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent/rendertype_entity_translucent.fsh deleted file mode 100644 index 29fd0268f..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent/rendertype_entity_translucent.fsh +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec4 lightMapColor; -layout(location = 2) in vec4 overlayColor; -layout(location = 3) in vec2 texCoord0; -layout(location = 4) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0); - if (color.a < 0.1) { - discard; - } - color *= vertexColor * ColorModulator; - color.rgb = mix(overlayColor.rgb, color.rgb, overlayColor.a); - color *= lightMapColor; - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent/rendertype_entity_translucent.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent/rendertype_entity_translucent.json deleted file mode 100644 index a3f707107..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent/rendertype_entity_translucent.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_entity_translucent", - "fragment": "rendertype_entity_translucent", - "attributes": [ - "Position", - "Color", - "UV0", - "UV1", - "UV2", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler1" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent/rendertype_entity_translucent.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent/rendertype_entity_translucent.vsh deleted file mode 100644 index 46038952c..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent/rendertype_entity_translucent.vsh +++ /dev/null @@ -1,36 +0,0 @@ -#version 450 - -#include "light.glsl" -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 3) in ivec2 UV1; -layout(location = 4) in ivec2 UV2; -layout(location = 5) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - vec3 Light0_Direction; - vec3 Light1_Direction; -}; - -layout(binding = 3) uniform sampler2D Sampler1; -layout(binding = 4) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec4 lightMapColor; -layout(location = 2) out vec4 overlayColor; -layout(location = 3) out vec2 texCoord0; -layout(location = 4) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = minecraft_mix_light(Light0_Direction, Light1_Direction, Normal, Color); - lightMapColor = texelFetch(Sampler2, UV2 / 16, 0); - overlayColor = texelFetch(Sampler1, UV1, 0); - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent_cull/rendertype_entity_translucent_cull.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent_cull/rendertype_entity_translucent_cull.fsh deleted file mode 100644 index c101705b9..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent_cull/rendertype_entity_translucent_cull.fsh +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; -layout(location = 2) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; - if (color.a < 0.1) { - discard; - } - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent_cull/rendertype_entity_translucent_cull.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent_cull/rendertype_entity_translucent_cull.json deleted file mode 100644 index 3f5cf9af4..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent_cull/rendertype_entity_translucent_cull.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_entity_translucent_cull", - "fragment": "rendertype_entity_translucent_cull", - "attributes": [ - "Position", - "Color", - "UV0", - "UV1", - "UV2", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent_cull/rendertype_entity_translucent_cull.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent_cull/rendertype_entity_translucent_cull.vsh deleted file mode 100644 index e2850014e..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent_cull/rendertype_entity_translucent_cull.vsh +++ /dev/null @@ -1,31 +0,0 @@ -#version 450 - -#include "light.glsl" -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 3) in ivec2 UV1; -layout(location = 4) in ivec2 UV2; -layout(location = 5) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - vec3 Light0_Direction; - vec3 Light1_Direction; -}; - -layout(binding = 3) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; -layout(location = 2) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = minecraft_mix_light(Light0_Direction, Light1_Direction, Normal, Color) * texelFetch(Sampler2, UV2 / 16, 0); - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent_emissive/rendertype_entity_translucent_emissive.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent_emissive/rendertype_entity_translucent_emissive.fsh deleted file mode 100644 index f7ad11db5..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent_emissive/rendertype_entity_translucent_emissive.fsh +++ /dev/null @@ -1,27 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec4 overlayColor; -layout(location = 2) in vec2 texCoord0; -layout(location = 3) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0); - if (color.a < 0.1) { - discard; - } - color *= vertexColor * ColorModulator; - color.rgb = mix(overlayColor.rgb, color.rgb, overlayColor.a); - fragColor = color * linear_fog_fade(vertexDistance, FogStart, FogEnd); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent_emissive/rendertype_entity_translucent_emissive.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent_emissive/rendertype_entity_translucent_emissive.json deleted file mode 100644 index c69e75508..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent_emissive/rendertype_entity_translucent_emissive.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_entity_translucent_emissive", - "fragment": "rendertype_entity_translucent_emissive", - "attributes": [ - "Position", - "Color", - "UV0", - "UV1", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler1" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent_emissive/rendertype_entity_translucent_emissive.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent_emissive/rendertype_entity_translucent_emissive.vsh deleted file mode 100644 index 5dd29078b..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_entity_translucent_emissive/rendertype_entity_translucent_emissive.vsh +++ /dev/null @@ -1,33 +0,0 @@ -#version 450 - -#include "light.glsl" -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 3) in ivec2 UV1; -layout(location = 5) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - vec3 Light0_Direction; - vec3 Light1_Direction; -}; - -layout(binding = 3) uniform sampler2D Sampler1; -layout(binding = 4) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec4 overlayColor; -layout(location = 2) out vec2 texCoord0; -layout(location = 3) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = minecraft_mix_light(Light0_Direction, Light1_Direction, Normal, Color); - overlayColor = texelFetch(Sampler1, UV1, 0); - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_eyes/rendertype_eyes.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_eyes/rendertype_eyes.fsh deleted file mode 100644 index 73da034a1..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_eyes/rendertype_eyes.fsh +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; -layout(location = 2) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor; - fragColor = color * ColorModulator * linear_fog_fade(vertexDistance, FogStart, FogEnd); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_eyes/rendertype_eyes.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_eyes/rendertype_eyes.json deleted file mode 100644 index 57462d602..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_eyes/rendertype_eyes.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_eyes", - "fragment": "rendertype_eyes", - "attributes": [ - "Position", - "Color", - "UV0" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_eyes/rendertype_eyes.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_eyes/rendertype_eyes.vsh deleted file mode 100644 index 74920ad34..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_eyes/rendertype_eyes.vsh +++ /dev/null @@ -1,23 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; -layout(location = 2) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = Color; - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint/rendertype_glint.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint/rendertype_glint.fsh deleted file mode 100644 index 8ffd06755..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint/rendertype_glint.fsh +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - float FogStart; - float FogEnd; - float GlintAlpha; -}; - -layout(location = 0) in float vertexDistance; -layout(location = 1) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * ColorModulator; - if (color.a < 0.1) { - discard; - } - float fade = linear_fog_fade(vertexDistance, FogStart, FogEnd) * GlintAlpha; - fragColor = vec4(color.rgb * fade, color.a); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint/rendertype_glint.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint/rendertype_glint.json deleted file mode 100644 index 83e0056a2..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint/rendertype_glint.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_glint", - "fragment": "rendertype_glint", - "attributes": [ - "Position", - "UV0" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "TextureMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "TextureMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "GlintAlpha", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint/rendertype_glint.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint/rendertype_glint.vsh deleted file mode 100644 index 71aa44c51..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint/rendertype_glint.vsh +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec2 UV0; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - mat4 TextureMat; -}; - -layout(location = 0) out float vertexDistance; -layout(location = 1) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - texCoord0 = (TextureMat * vec4(UV0, 0.0, 1.0)).xy; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint_direct/rendertype_glint_direct.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint_direct/rendertype_glint_direct.fsh deleted file mode 100644 index 8ffd06755..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint_direct/rendertype_glint_direct.fsh +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - float FogStart; - float FogEnd; - float GlintAlpha; -}; - -layout(location = 0) in float vertexDistance; -layout(location = 1) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * ColorModulator; - if (color.a < 0.1) { - discard; - } - float fade = linear_fog_fade(vertexDistance, FogStart, FogEnd) * GlintAlpha; - fragColor = vec4(color.rgb * fade, color.a); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint_direct/rendertype_glint_direct.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint_direct/rendertype_glint_direct.json deleted file mode 100644 index d016ddf12..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint_direct/rendertype_glint_direct.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_glint_direct", - "fragment": "rendertype_glint_direct", - "attributes": [ - "Position", - "UV0" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "TextureMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "TextureMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "GlintAlpha", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint_direct/rendertype_glint_direct.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint_direct/rendertype_glint_direct.vsh deleted file mode 100644 index 71aa44c51..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint_direct/rendertype_glint_direct.vsh +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec2 UV0; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - mat4 TextureMat; -}; - -layout(location = 0) out float vertexDistance; -layout(location = 1) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - texCoord0 = (TextureMat * vec4(UV0, 0.0, 1.0)).xy; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint_translucent/rendertype_glint_translucent.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint_translucent/rendertype_glint_translucent.fsh deleted file mode 100644 index 8ffd06755..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint_translucent/rendertype_glint_translucent.fsh +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - float FogStart; - float FogEnd; - float GlintAlpha; -}; - -layout(location = 0) in float vertexDistance; -layout(location = 1) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * ColorModulator; - if (color.a < 0.1) { - discard; - } - float fade = linear_fog_fade(vertexDistance, FogStart, FogEnd) * GlintAlpha; - fragColor = vec4(color.rgb * fade, color.a); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint_translucent/rendertype_glint_translucent.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint_translucent/rendertype_glint_translucent.json deleted file mode 100644 index 4fbd62b86..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint_translucent/rendertype_glint_translucent.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_glint_translucent", - "fragment": "rendertype_glint_translucent", - "attributes": [ - "Position", - "UV0" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "TextureMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "TextureMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "GlintAlpha", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint_translucent/rendertype_glint_translucent.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint_translucent/rendertype_glint_translucent.vsh deleted file mode 100644 index 71aa44c51..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_glint_translucent/rendertype_glint_translucent.vsh +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec2 UV0; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - mat4 TextureMat; -}; - -layout(location = 0) out float vertexDistance; -layout(location = 1) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - texCoord0 = (TextureMat * vec4(UV0, 0.0, 1.0)).xy; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_item_entity_translucent_cull/rendertype_item_entity_translucent_cull.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_item_entity_translucent_cull/rendertype_item_entity_translucent_cull.fsh deleted file mode 100644 index c101705b9..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_item_entity_translucent_cull/rendertype_item_entity_translucent_cull.fsh +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; -layout(location = 2) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; - if (color.a < 0.1) { - discard; - } - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_item_entity_translucent_cull/rendertype_item_entity_translucent_cull.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_item_entity_translucent_cull/rendertype_item_entity_translucent_cull.json deleted file mode 100644 index 8bfd37985..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_item_entity_translucent_cull/rendertype_item_entity_translucent_cull.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_item_entity_translucent_cull", - "fragment": "rendertype_item_entity_translucent_cull", - "attributes": [ - "Position", - "Color", - "UV0", - "UV2", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_item_entity_translucent_cull/rendertype_item_entity_translucent_cull.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_item_entity_translucent_cull/rendertype_item_entity_translucent_cull.vsh deleted file mode 100644 index ea9fb38c1..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_item_entity_translucent_cull/rendertype_item_entity_translucent_cull.vsh +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 - -#include "light.glsl" -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 4) in ivec2 UV2; -layout(location = 5) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - vec3 Light0_Direction; - vec3 Light1_Direction; -}; - -layout(binding = 3) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; -layout(location = 2) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = minecraft_mix_light(Light0_Direction, Light1_Direction, Normal, Color) * texelFetch(Sampler2, UV2 / 16, 0); - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_leash/rendertype_leash.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_leash/rendertype_leash.fsh deleted file mode 100644 index 2981a5776..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_leash/rendertype_leash.fsh +++ /dev/null @@ -1,17 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 1) uniform UBO{ - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - fragColor = linear_fog(vertexColor, vertexDistance, FogStart, FogEnd, FogColor); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_leash/rendertype_leash.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_leash/rendertype_leash.json deleted file mode 100644 index 373975076..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_leash/rendertype_leash.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_leash", - "fragment": "rendertype_leash", - "attributes": [ - "Position", - "Color", - "UV2" - ], - "samplers": [ - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_leash/rendertype_leash.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_leash/rendertype_leash.vsh deleted file mode 100644 index 267e94591..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_leash/rendertype_leash.vsh +++ /dev/null @@ -1,24 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in ivec2 UV2; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; - vec4 ColorModulator; -}; - -layout(binding = 2) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = Color * ColorModulator * texelFetch(Sampler2, UV2 / 16, 0); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_lightning/rendertype_lightning.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_lightning/rendertype_lightning.json deleted file mode 100644 index 59a6d6ad0..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_lightning/rendertype_lightning.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_lightning", - "fragment": "rendertype_lightning", - "attributes": [ - "Color" - ], - "samplers": [], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_lines/rendertype_lines.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_lines/rendertype_lines.fsh deleted file mode 100644 index 9d3812f74..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_lines/rendertype_lines.fsh +++ /dev/null @@ -1,19 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = vertexColor * ColorModulator; - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_lines/rendertype_lines.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_lines/rendertype_lines.json deleted file mode 100644 index b719262ee..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_lines/rendertype_lines.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_lines", - "fragment": "rendertype_lines", - "attributes": [ - "Position", - "Color", - "Normal" - ], - "samplers": [], - "uniforms": [ - { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "LineWidth", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "ScreenSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "ScreenSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] }, - { "name": "LineWidth", "type": "float", "count": 1, "values": [ 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_lines/rendertype_lines.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_lines/rendertype_lines.vsh deleted file mode 100644 index 60a1d4b8c..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_lines/rendertype_lines.vsh +++ /dev/null @@ -1,47 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 ModelViewMat; - mat4 ProjMat; - vec2 ScreenSize; - float LineWidth; -}; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out float vertexDistance; - -const float VIEW_SHRINK = 1.0 - (1.0 / 256.0); -const mat4 VIEW_SCALE = mat4( - VIEW_SHRINK, 0.0, 0.0, 0.0, - 0.0, VIEW_SHRINK, 0.0, 0.0, - 0.0, 0.0, VIEW_SHRINK, 0.0, - 0.0, 0.0, 0.0, 1.0 -); - -void main() { - vec4 linePosStart = ProjMat * VIEW_SCALE * ModelViewMat * vec4(Position, 1.0); - vec4 linePosEnd = ProjMat * VIEW_SCALE * ModelViewMat * vec4(Position + Normal, 1.0); - - vec3 ndc1 = linePosStart.xyz / linePosStart.w; - vec3 ndc2 = linePosEnd.xyz / linePosEnd.w; - - vec2 lineScreenDirection = normalize((ndc2.xy - ndc1.xy) * ScreenSize); - vec2 lineOffset = vec2(-lineScreenDirection.y, lineScreenDirection.x) * LineWidth / ScreenSize; - - if (lineOffset.x < 0.0) { - lineOffset *= -1.0; - } - - if (mod(gl_VertexIndex, 2) == 0) { - gl_Position = vec4((ndc1 + vec3(lineOffset, 0.0)) * linePosStart.w, linePosStart.w); - } else { - gl_Position = vec4((ndc1 - vec3(lineOffset, 0.0)) * linePosStart.w, linePosStart.w); - } - - vertexDistance = length((vec4(Position, 1.0)).xyz); - vertexColor = Color; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_outline/rendertype_outline.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_outline/rendertype_outline.fsh deleted file mode 100644 index 7127479f2..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_outline/rendertype_outline.fsh +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0); - if (color.a == 0.0) { - discard; - } - fragColor = vec4(ColorModulator.rgb * vertexColor.rgb, ColorModulator.a); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_outline/rendertype_outline.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_outline/rendertype_outline.json deleted file mode 100644 index dbb6a88db..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_outline/rendertype_outline.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_outline", - "fragment": "rendertype_outline", - "attributes": [ - "Position", - "Color", - "UV0" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_outline/rendertype_outline.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_outline/rendertype_outline.vsh deleted file mode 100644 index a2486fa8d..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_outline/rendertype_outline.vsh +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec2 UV0; -layout(location = 2) in vec4 Color; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexColor = Color; - texCoord0 = UV0; -} - diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_solid/rendertype_solid.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_solid/rendertype_solid.fsh deleted file mode 100644 index 84b4bfba2..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_solid/rendertype_solid.fsh +++ /dev/null @@ -1,22 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in float vertexDistance; -layout(location = 1) in vec4 vertexColor; -layout(location = 2) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_solid/rendertype_solid.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_solid/rendertype_solid.json deleted file mode 100644 index 7126b7b92..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_solid/rendertype_solid.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_solid", - "fragment": "rendertype_solid", - "attributes": [ - "Position", - "Color", - "UV0", - "UV2", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_solid/rendertype_solid.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_solid/rendertype_solid.vsh deleted file mode 100644 index 901a6df43..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_solid/rendertype_solid.vsh +++ /dev/null @@ -1,28 +0,0 @@ -#version 450 - -#include "light.glsl" -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 3) in ivec2 UV2; -layout(location = 4) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(binding = 3) uniform sampler2D Sampler2; - -layout(location = 0) out float vertexDistance; -layout(location = 1) out vec4 vertexColor; -layout(location = 2) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = Color * minecraft_sample_lightmap(Sampler2, UV2); - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text/rendertype_text.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text/rendertype_text.fsh deleted file mode 100644 index c101705b9..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text/rendertype_text.fsh +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; -layout(location = 2) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; - if (color.a < 0.1) { - discard; - } - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text/rendertype_text.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text/rendertype_text.json deleted file mode 100644 index e72c6b337..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text/rendertype_text.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_text", - "fragment": "rendertype_text", - "attributes": [ - "Position", - "Color", - "UV0", - "UV2" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text/rendertype_text.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text/rendertype_text.vsh deleted file mode 100644 index 647a3f1d7..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text/rendertype_text.vsh +++ /dev/null @@ -1,26 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 3) in ivec2 UV2; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(binding = 3) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; -layout(location = 2) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = Color * texelFetch(Sampler2, UV2 / 16, 0); - texCoord0 = UV0; -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_background/rendertype_text_background.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_background/rendertype_text_background.fsh deleted file mode 100644 index f4c3c01f6..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_background/rendertype_text_background.fsh +++ /dev/null @@ -1,22 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 2) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = vertexColor * ColorModulator; - if (color.a < 0.1) { - discard; - } - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_background/rendertype_text_background.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_background/rendertype_text_background.json deleted file mode 100644 index 786c39176..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_background/rendertype_text_background.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_text_background", - "fragment": "rendertype_text_background", - "attributes": [ - "Position", - "Color", - "UV2" - ], - "samplers": [ - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogShape", "type": "int", "count": 1, "values": [ 0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_background/rendertype_text_background.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_background/rendertype_text_background.vsh deleted file mode 100644 index ae6f0c93e..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_background/rendertype_text_background.vsh +++ /dev/null @@ -1,23 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in ivec2 UV2; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(binding = 2) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 2) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = Color * texelFetch(Sampler2, UV2 / 16, 0); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_background_see_through/rendertype_text_background_see_through.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_background_see_through/rendertype_text_background_see_through.fsh deleted file mode 100644 index 3d175e2cc..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_background_see_through/rendertype_text_background_see_through.fsh +++ /dev/null @@ -1,17 +0,0 @@ -#version 450 - -layout(location = 0) in vec4 vertexColor; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; -}; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = vertexColor; - if (color.a < 0.1) { - discard; - } - fragColor = color * ColorModulator; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_background_see_through/rendertype_text_background_see_through.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_background_see_through/rendertype_text_background_see_through.json deleted file mode 100644 index b70d3129a..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_background_see_through/rendertype_text_background_see_through.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_text_background_see_through", - "fragment": "rendertype_text_background_see_through", - "attributes": [ - "Position", - "Color" - ], - "samplers": [], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_background_see_through/rendertype_text_background_see_through.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_background_see_through/rendertype_text_background_see_through.vsh deleted file mode 100644 index 5b5ad04e3..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_background_see_through/rendertype_text_background_see_through.vsh +++ /dev/null @@ -1,16 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(location = 0) out vec4 vertexColor; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexColor = Color; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_intensity/rendertype_text_intensity.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_intensity/rendertype_text_intensity.fsh deleted file mode 100644 index 957404e3f..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_intensity/rendertype_text_intensity.fsh +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; -layout(location = 2) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0).rrrr * vertexColor * ColorModulator; - if (color.a < 0.1) { - discard; - } - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_intensity/rendertype_text_intensity.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_intensity/rendertype_text_intensity.json deleted file mode 100644 index a2bc21221..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_intensity/rendertype_text_intensity.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_text_intensity", - "fragment": "rendertype_text_intensity", - "attributes": [ - "Position", - "Color", - "UV0", - "UV2" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_intensity/rendertype_text_intensity.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_intensity/rendertype_text_intensity.vsh deleted file mode 100644 index cd7a1176d..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_intensity/rendertype_text_intensity.vsh +++ /dev/null @@ -1,26 +0,0 @@ -#version 450 - -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 3) in ivec2 UV2; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(binding = 3) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; -layout(location = 2) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = Color * texelFetch(Sampler2, UV2 / 16, 0); - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_intensity_see_through/rendertype_text_intensity_see_through.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_intensity_see_through/rendertype_text_intensity_see_through.fsh deleted file mode 100644 index 931e23127..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_intensity_see_through/rendertype_text_intensity_see_through.fsh +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO { - vec4 ColorModulator; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0).rrrr * vertexColor; - if (color.a < 0.1) { - discard; - } - fragColor = color * ColorModulator; -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_intensity_see_through/rendertype_text_intensity_see_through.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_intensity_see_through/rendertype_text_intensity_see_through.json deleted file mode 100644 index 7c83ff3f2..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_intensity_see_through/rendertype_text_intensity_see_through.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_text_intensity_see_through", - "fragment": "rendertype_text_intensity_see_through", - "attributes": [ - "Position", - "Color", - "UV0" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_intensity_see_through/rendertype_text_intensity_see_through.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_intensity_see_through/rendertype_text_intensity_see_through.vsh deleted file mode 100644 index 817669d61..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_intensity_see_through/rendertype_text_intensity_see_through.vsh +++ /dev/null @@ -1,19 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexColor = Color; - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_see_through/rendertype_text_see_through.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_see_through/rendertype_text_see_through.fsh deleted file mode 100644 index 9083d7665..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_see_through/rendertype_text_see_through.fsh +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor; - if (color.a < 0.1) { - discard; - } - fragColor = color * ColorModulator; -} - diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_see_through/rendertype_text_see_through.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_see_through/rendertype_text_see_through.json deleted file mode 100644 index 42009dce5..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_see_through/rendertype_text_see_through.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_text_see_through", - "fragment": "rendertype_text_see_through", - "attributes": [ - "Position", - "Color", - "UV0" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_see_through/rendertype_text_see_through.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_see_through/rendertype_text_see_through.vsh deleted file mode 100644 index b203fb509..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_text_see_through/rendertype_text_see_through.vsh +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexColor = Color; - texCoord0 = UV0; -} - diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent/rendertype_translucent.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent/rendertype_translucent.fsh deleted file mode 100644 index d44254ed4..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent/rendertype_translucent.fsh +++ /dev/null @@ -1,22 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; -layout(location = 2) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent/rendertype_translucent.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent/rendertype_translucent.json deleted file mode 100644 index e466427aa..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent/rendertype_translucent.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_translucent", - "fragment": "rendertype_translucent", - "attributes": [ - "Position", - "Color", - "UV0", - "UV2", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent/rendertype_translucent.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent/rendertype_translucent.vsh deleted file mode 100644 index 626cad61d..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent/rendertype_translucent.vsh +++ /dev/null @@ -1,28 +0,0 @@ -#version 450 - -#include "light.glsl" -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 3) in ivec2 UV2; -layout(location = 4) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(binding = 3) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; -layout(location = 2) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = Color * minecraft_sample_lightmap(Sampler2, UV2); - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent_moving_block/rendertype_translucent_moving_block.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent_moving_block/rendertype_translucent_moving_block.fsh deleted file mode 100644 index 88f51fae7..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent_moving_block/rendertype_translucent_moving_block.fsh +++ /dev/null @@ -1,17 +0,0 @@ -#version 450 - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor; - fragColor = color * ColorModulator; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent_moving_block/rendertype_translucent_moving_block.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent_moving_block/rendertype_translucent_moving_block.json deleted file mode 100644 index 00a20cbba..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent_moving_block/rendertype_translucent_moving_block.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_translucent_moving_block", - "fragment": "rendertype_translucent_moving_block", - "attributes": [ - "Position", - "Color", - "UV0", - "UV2", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent_moving_block/rendertype_translucent_moving_block.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent_moving_block/rendertype_translucent_moving_block.vsh deleted file mode 100644 index 350d59bae..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent_moving_block/rendertype_translucent_moving_block.vsh +++ /dev/null @@ -1,23 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 3) in ivec2 UV2; -layout(location = 4) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(binding = 3) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexColor = Color * texelFetch(Sampler2, UV2 / 16, 0); - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent_no_crumbling/rendertype_translucent_no_crumbling.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent_no_crumbling/rendertype_translucent_no_crumbling.fsh deleted file mode 100644 index 88f51fae7..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent_no_crumbling/rendertype_translucent_no_crumbling.fsh +++ /dev/null @@ -1,17 +0,0 @@ -#version 450 - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor; - fragColor = color * ColorModulator; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent_no_crumbling/rendertype_translucent_no_crumbling.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent_no_crumbling/rendertype_translucent_no_crumbling.json deleted file mode 100644 index 072428c98..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent_no_crumbling/rendertype_translucent_no_crumbling.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_translucent_no_crumbling", - "fragment": "rendertype_translucent_no_crumbling", - "attributes": [ - "Position", - "Color", - "UV0", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent_no_crumbling/rendertype_translucent_no_crumbling.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent_no_crumbling/rendertype_translucent_no_crumbling.vsh deleted file mode 100644 index f9c22186b..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_translucent_no_crumbling/rendertype_translucent_no_crumbling.vsh +++ /dev/null @@ -1,22 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 4) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(binding = 3) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexColor = Color; - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_tripwire/rendertype_tripwire.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_tripwire/rendertype_tripwire.fsh deleted file mode 100644 index 7659168a5..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_tripwire/rendertype_tripwire.fsh +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 -#include "fog.glsl" - -layout(binding = 2) uniform sampler2D Sampler0; - -layout(binding = 1) uniform UBO{ - vec4 ColorModulator; - vec4 FogColor; - float FogStart; - float FogEnd; -}; - -layout(location = 0) in vec4 vertexColor; -layout(location = 1) in vec2 texCoord0; -layout(location = 2) in float vertexDistance; - -layout(location = 0) out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; - if (color.a < 0.1) { - discard; - } - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_tripwire/rendertype_tripwire.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_tripwire/rendertype_tripwire.json deleted file mode 100644 index d6044d977..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_tripwire/rendertype_tripwire.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_tripwire", - "fragment": "rendertype_tripwire", - "attributes": [ - "Position", - "Color", - "UV0", - "UV2", - "Normal" - ], - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_tripwire/rendertype_tripwire.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_tripwire/rendertype_tripwire.vsh deleted file mode 100644 index 626cad61d..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_tripwire/rendertype_tripwire.vsh +++ /dev/null @@ -1,28 +0,0 @@ -#version 450 - -#include "light.glsl" -#include "fog.glsl" - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec4 Color; -layout(location = 2) in vec2 UV0; -layout(location = 3) in ivec2 UV2; -layout(location = 4) in vec3 Normal; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -layout(binding = 3) uniform sampler2D Sampler2; - -layout(location = 0) out vec4 vertexColor; -layout(location = 1) out vec2 texCoord0; -layout(location = 2) out float vertexDistance; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); - - vertexDistance = fog_distance(Position.xyz, 0); - vertexColor = Color * minecraft_sample_lightmap(Sampler2, UV2); - texCoord0 = UV0; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_water_mask/rendertype_water_mask.fsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_water_mask/rendertype_water_mask.fsh deleted file mode 100644 index 252f19600..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_water_mask/rendertype_water_mask.fsh +++ /dev/null @@ -1,11 +0,0 @@ -#version 450 - -layout(binding = 1) uniform UniformBufferObject { - vec4 ColorModulator; -}; - -layout(location = 0) out vec4 fragColor; - -void main() { - fragColor = ColorModulator; -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_water_mask/rendertype_water_mask.json b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_water_mask/rendertype_water_mask.json deleted file mode 100644 index 52f69c0bb..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_water_mask/rendertype_water_mask.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_water_mask", - "fragment": "rendertype_water_mask", - "attributes": [], - "samplers": [], - "uniforms": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ], - "UBOs": [ - { "type": "vertex", "binding": 0, "fields": [ - { "name": "MVP", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } - ] }, - { "type": "fragment", "binding": 1, "fields": [ - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } - ] } - ] -} diff --git a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_water_mask/rendertype_water_mask.vsh b/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_water_mask/rendertype_water_mask.vsh deleted file mode 100644 index c663f48de..000000000 --- a/src/main/resources/assets/vulkanmod/shaders/minecraft/core/rendertype_water_mask/rendertype_water_mask.vsh +++ /dev/null @@ -1,11 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 Position; - -layout(binding = 0) uniform UniformBufferObject { - mat4 MVP; -}; - -void main() { - gl_Position = MVP * vec4(Position, 1.0); -} \ No newline at end of file diff --git a/src/main/resources/assets/vulkanmod/shaders/post/blit/blit.vsh b/src/main/resources/assets/vulkanmod/shaders/post/blit/blit.vsh new file mode 100644 index 000000000..1f6cf6e70 --- /dev/null +++ b/src/main/resources/assets/vulkanmod/shaders/post/blit/blit.vsh @@ -0,0 +1,15 @@ +#version 150 + +in vec4 Position; + +uniform mat4 ProjMat; +uniform vec2 OutSize; + +out vec2 texCoord; + +void main(){ + vec4 outPos = ProjMat * vec4(Position.xy * OutSize, 0.0, 1.0); + gl_Position = vec4(outPos.xy, 0.2, 1.0); + + texCoord = vec2(Position.x, 1.0 - Position.y); +} diff --git a/src/main/resources/assets/vulkanmod/shaders/post/blit/blur.vsh b/src/main/resources/assets/vulkanmod/shaders/post/blit/blur.vsh new file mode 100644 index 000000000..65982295c --- /dev/null +++ b/src/main/resources/assets/vulkanmod/shaders/post/blit/blur.vsh @@ -0,0 +1,21 @@ +#version 150 + +in vec4 Position; + +uniform mat4 ProjMat; +uniform vec2 InSize; +uniform vec2 OutSize; +uniform vec2 BlurDir; + +out vec2 texCoord; +out vec2 sampleStep; + +void main() { + vec4 outPos = ProjMat * vec4(Position.xy * OutSize, 0.0, 1.0); + gl_Position = vec4(outPos.xy, 0.2, 1.0); + + vec2 oneTexel = 1.0 / InSize; + sampleStep = oneTexel * BlurDir; + + texCoord = vec2(Position.x, 1.0 - Position.y); +} diff --git a/src/main/resources/assets/vulkanmod/Vlogo.png b/src/main/resources/assets/vulkanmod/vlogo.png similarity index 100% rename from src/main/resources/assets/vulkanmod/Vlogo.png rename to src/main/resources/assets/vulkanmod/vlogo.png diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 37218f426..5d5d0fdd0 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ "sources": "https://github.com/xCollateral/VulkanMod" }, - "icon": "assets/vulkanmod/Vlogo.png", + "icon": "assets/vulkanmod/vlogo.png", "environment": "client", "entrypoints": { @@ -28,7 +28,9 @@ "depends": { "fabricloader": ">=0.14.14", - "minecraft": ">=1.21", - "java": ">=17" + "minecraft": ["1.21.9", "1.21.10"] + }, + "custom": { + "fabric-renderer-api-v1:contains_renderer": true } } diff --git a/src/main/resources/vulkanmod.accesswidener b/src/main/resources/vulkanmod.accesswidener index 459ba601d..85ea0ce73 100644 --- a/src/main/resources/vulkanmod.accesswidener +++ b/src/main/resources/vulkanmod.accesswidener @@ -6,6 +6,15 @@ accessible class net/minecraft/client/gui/Gui$HeartType accessible class net/minecraft/client/renderer/OutlineBufferSource$EntityOutlineGenerator +accessible class net/minecraft/client/renderer/texture/SpriteContents$Ticker +accessible class net/minecraft/client/renderer/texture/SpriteContents$FrameInfo +accessible class net/minecraft/client/renderer/texture/SpriteContents$AnimatedTexture +accessible field net/minecraft/client/renderer/texture/SpriteContents$AnimatedTexture frames Ljava/util/List; +accessible field net/minecraft/client/renderer/texture/SpriteContents$FrameInfo time I + #1.20 -accessible field com/mojang/blaze3d/systems/RenderSystem vertexSorting Lcom/mojang/blaze3d/vertex/VertexSorting; accessible field net/minecraft/client/renderer/RenderStateShard name Ljava/lang/String; + +accessible class net/minecraft/client/renderer/ShaderManager$ShaderSourceKey +accessible method net/minecraft/client/renderer/ShaderManager$ShaderSourceKey (Lnet/minecraft/resources/ResourceLocation;Lcom/mojang/blaze3d/shaders/ShaderType;)V +accessible class net/minecraft/client/renderer/ShaderManager$CompilationCache \ No newline at end of file diff --git a/src/main/resources/vulkanmod.mixins.json b/src/main/resources/vulkanmod.mixins.json index 674e07398..8c6d50389 100644 --- a/src/main/resources/vulkanmod.mixins.json +++ b/src/main/resources/vulkanmod.mixins.json @@ -15,64 +15,81 @@ "chunk.DirectionMixin", "chunk.FrustumMixin", "chunk.LevelRendererMixin", - "chunk.RenderBuffersM", + "chunk.SectionBufferBuilderPoolM", "chunk.SectionRenderDispatcherM", "chunk.ViewAreaM", "chunk.VisibilitySetMixin", - "compatibility.EffectInstanceM", - "compatibility.ProgramM", - "compatibility.UniformM", "compatibility.gl.GL11M", + "compatibility.gl.GL14M", "compatibility.gl.GL15M", "compatibility.gl.GL30M", "debug.crash_report.SystemReportM", - "debug.DebugScreenOverlayM", - "debug.GlDebugInfoM", + "debug.DebugEntryMemoryM", + "debug.DebugEntrySystemSpecsM", + "debug.DebugScreenEntriesM", "debug.KeyboardHandlerM", + "fix.MainMixin", + "matrix.Matrix4fM", + "matrix.PoseAccessor", + "profiling.ClientMetricsSamplersProviderMixin", "profiling.GuiMixin", "profiling.KeyboardHandlerM", "profiling.LevelRendererMixin", + "profiling.TimerQueryM", - "render.BufferUploaderM", + "render.CompositeStateAccessor", + "render.CompositeRenderTypeM", + "render.FogRendererMixin", "render.GameRendererMixin", - "render.GlProgramManagerMixin", + "render.GuiRendererMixin", "render.GlStateManagerM", - "render.LevelRendererMixin", "render.MinecraftMixin", + "render.PictureInPictureRendererM", "render.RenderSystemMixin", "render.RenderTypeM", - "render.ShaderInstanceM", + "render.biome.BiomeManagerM", + "render.block.BakedQuadM", + "render.clouds.LevelRendererM", + "render.color.BlockColorsM", "render.entity.EntityRendererM", "render.entity.LevelRendererM", "render.entity.model.ModelPartCubeM", "render.entity.model.ModelPartM", - "render.particle.SingleQuadParticleM", + "render.frame.MinecraftMixin", + "render.frame.RenderSystemMixin", + "render.frapi.BatchingRenderCommandQueueM", + "render.frapi.BlockModelRendererM", + "render.frapi.BlockRenderDispatcherAccessor", + "render.frapi.BlockRenderManagerM", + "render.frapi.ItemFeatureRendererM", + "render.frapi.ItemRendererAccessor", + "render.frapi.ItemRenderStateLayerRenderStateM", + "render.frapi.ItemRenderStateM", + "render.frapi.OrderedRenderCommandQueueImplM", + "render.particle.QuadParticleGroupM", + "render.particle.QuadParticleRenderStateM", + "render.shader.RenderPipelineM", + "render.shader.ShaderManagerM", "render.target.MainTargetMixin", "render.target.RenderTargetMixin", "render.vertex.BufferBuilderM", - "render.vertex.FaceBakeryM", "render.vertex.IndexTypeMixin", - "render.vertex.VertexBufferM", - "render.vertex.VertexConsumerM", "render.vertex.VertexFormatMixin", "screen.ScreenM", "screen.OptionsScreenM", "texture.mip.MipmapGeneratorM", - "texture.image.MNativeImage", "texture.image.NativeImageAccessor", - "texture.MAbstractTexture", - "texture.MSpriteContents", - "texture.MTextureManager", - "texture.MTextureUtil", - - "util.ScreenshotRecorderM", + "texture.update.MLightTexture", + "texture.update.MSpriteContents", + "texture.update.MTextureManager", + "util.ScreenshotMixin", "vertex.EntityOutlineGeneratorM", "vertex.SpriteCoordinateExpanderM", @@ -85,11 +102,8 @@ "texture.mip.MipmapGeneratorM", - "compatibility.PostChainM", "compatibility.PostPassM", - "render.block.BakedQuadM", - "voxel.VoxelShapeMixin" ], "injectors": {