From 812428d0d3f226b1f1dff3fe360e65f7322f044d Mon Sep 17 00:00:00 2001 From: amo Date: Sun, 14 Jul 2024 14:35:50 +0100 Subject: [PATCH 01/47] github please stop screaming at me --- CODE_OF_CONDUCT.md | 128 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..18c91471 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. From be762ac4d0761b592b6090bf8969c35330a5537f Mon Sep 17 00:00:00 2001 From: amo Date: Sun, 14 Jul 2024 14:40:36 +0100 Subject: [PATCH 02/47] STOP IT --- CONTRIBUTING.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..f87d0a40 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,45 @@ +# Contributing Guidelines + +## Introduction +Welcome to the Veil project! We're thrilled that you're interested in contributing. Veil is a rendering library for Minecraft, with the goal of including more game-engine style features in the future. This project is created out of a love for coding and the desire to build something fun and useful. While we primarily develop Veil for our own use, we are more than happy for others to use it in their projects. However, please understand that Veil is not designed to be an "enterprise-level" library, and we will always prioritize our own goals and use cases. + +## How to Contribute + +### Reporting Issues +If you encounter any bugs or have suggestions for improvements, please open an issue. When reporting an issue, please provide as much detail as possible, including steps to reproduce the problem, your environment, and any relevant logs or screenshots. + +### Pull Requests (PRs) +We welcome pull requests from the community! However, please note that we review and accept PRs at our discretion, based on how they fit with our vision and needs for Veil. Here are some guidelines to help your PR get accepted: + +1. **Discuss First**: Before spending time on a major change, it's a good idea to open an issue to discuss your proposed changes. This helps ensure that your efforts align with the project's direction and goals. + +2. **Fork the Repository**: Create a fork of the Veil repository and work on your changes in your fork. + +3. **Create a Branch**: Use a descriptive branch name for your changes, such as `feature/new-cool-feature` or `bugfix/fix-crash`. + +4. **Write Clear Commit Messages**: Use clear and concise commit messages that explain the purpose of your changes. + +5. **Follow Coding Standards**: Maintain the coding style and conventions used in the project. Consistent code helps with readability and maintenance. + +6. **Test Your Changes**: Ensure that your changes do not break existing functionality. If possible, add tests for your new features or bug fixes. + +7. **Submit Your PR**: Once your changes are ready, submit a pull request to the `main` branch of the Veil repository. Include a description of your changes and any relevant context or documentation. + +### Code of Conduct +Please note that we expect all contributors to adhere to our [Code of Conduct](CODE_OF_CONDUCT.md). Respectful and constructive interactions are crucial for maintaining a positive and collaborative community. + +## What to Expect +As maintainers, we review contributions based on our discretion and priorities. Here are a few things to keep in mind: + +- **Internal Priorities**: Our own use cases and goals for Veil will always take precedence. While we appreciate community contributions, they must align with our internal needs. +- **Response Time**: We will do our best to review your issues and PRs in a timely manner, but please be patient as this is a passion project for us. +- **Feedback**: If we have feedback or requests for changes, we will communicate them through the issue or PR comments. +- **Acceptance**: Not all contributions will be accepted. We appreciate all efforts, but we reserve the right to decline contributions that do not align with our project's vision or standards. + +## Thank You! +Thank you for your interest in contributing to Veil! Your contributions, whether large or small, help make this project better for everyone. We appreciate your support and understanding of our approach to managing this passion project. + +Happy coding! + +--- +If you have any questions, feel free to reach out to us through the issues section on GitHub or in the FoundryMC Discord. We're here to help and appreciate your efforts to improve Veil! From 377f9d2544be55bd6200c546633f1a4375beca0f Mon Sep 17 00:00:00 2001 From: amo Date: Sun, 14 Jul 2024 14:42:26 +0100 Subject: [PATCH 03/47] issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 36 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 20 +++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..2620bccb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,36 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Description** +Please provide a clear and concise description of the bug. + +**To Reproduce** +Steps to reproduce the behavior: +1. +2. +3. + +**Expected Behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**System Information** +Please provide the following information: +- **Veil Version**: [e.g., 1.0.0] +- **Minecraft Version**: [e.g., 1.16.5] +- **Loader & Loader Version**: [e.g., Fabric 0.11.3] +- **Operating System**: [e.g., Windows 10, macOS 11.2] +- **CPU**: [e.g., Intel i7-9700K] +- **GPU**: [e.g., NVIDIA RTX 2070] +- **RAM**: [e.g., 16GB] + +**Additional Context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..bbcbbe7d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. From 1e1f8ddd542bf5ecb92660f05ce07ae9976f18e3 Mon Sep 17 00:00:00 2001 From: amo Date: Sun, 14 Jul 2024 14:58:36 +0100 Subject: [PATCH 04/47] Update README.md --- README.md | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 338883a3..49e8e4b1 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,44 @@ -# Veil +# Veil: Advanced Rendering for Minecraft 🖼️✨ -[![https://maven.blamejared.com/foundry/veil/Veil-common-1.20.1/](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fmaven.blamejared.com%2Ffoundry%2Fveil%2FVeil-common-1.20.1%2Fmaven-metadata.xml&label=Veil%201.20)](https://maven.blamejared.com/foundry/veil/Veil-common-1.20.1/) -[![https://maven.blamejared.com/foundry/veil/Veil-common-1.20.4/](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fmaven.blamejared.com%2Ffoundry%2Fveil%2FVeil-common-1.20.4%2Fmaven-metadata.xml&label=Veil%201.20.4)](https://maven.blamejared.com/foundry/veil/Veil-common-1.20.4/) +[![Veil 1.20](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fmaven.blamejared.com%2Ffoundry%2Fveil%2FVeil-common-1.20.1%2Fmaven-metadata.xml&label=Veil%201.20)](https://maven.blamejared.com/foundry/veil/Veil-common-1.20.1/) +[![Veil 1.20.4](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fmaven.blamejared.com%2Ffoundry%2Fveil%2FVeil-common-1.20.4%2Fmaven-metadata.xml&label=Veil%201.20.4)](https://maven.blamejared.com/foundry/veil/Veil-common-1.20.4/) -This is the Veil project. It is a collection of tools and utilities that are designed to make it easier for mod developers to do advanced rendering in their mods. See the [Example Mod here](https://github.com/FoundryMC/veil-example-mod). +Veil is a sophisticated collection of tools and utilities designed to facilitate advanced rendering for Minecraft mod developers. Our goal is to enable more modern game-engine level content in Java Minecraft, pushing the boundaries of what is possible in modding. -### [Veil Developer Wiki](https://github.com/FoundryMC/Veil/wiki) +## Features + +- **Animations**: A timeline-keyframe system supporting position, rotation, and scale. +- **Colors**: Manage colors and use them with Themes. +- **Easings**: Apply easing functions for more natural motion. +- **Framebuffer**: JSON-driven custom framebuffers. +- **In-World Tooltips**: Fully customizable, network-synced 3D tooltips. +- **OpenCL**: Harness the power of OpenCL for rendering and other computational tasks. +- **Post Processing**: A custom post-processing pipeline with easy texture binding. +- **Shaders**: Full support for all OpenGL shader types, with HLSL and Spir-V support potentially coming in the future. +- **Shader Modification**: Inject and modify existing shaders to suit your needs. + +## Getting Started + +Explore our [Example Mod](https://github.com/FoundryMC/veil-example-mod) to see Veil in action and learn how to integrate it into your projects. + +For comprehensive documentation and guides, visit our [Veil Developer Wiki](https://github.com/FoundryMC/Veil/wiki). + +## Contribution Guidelines + +We welcome contributions from the community! Before contributing, please read our [Contributing Guidelines](CONTRIBUTING.md) to understand our processes and ensure your contributions align with the project goals. + +## Code of Conduct + +Please note that we expect all contributors to adhere to our [Code of Conduct](CODE_OF_CONDUCT.md). Respectful and constructive interactions are crucial for maintaining a positive and collaborative community. + +## License + +Veil is licensed under the [LGPL License](LICENSE). Feel free to use, modify, and distribute the code as per the terms of the license. + +## Goals + +Our primary goal with Veil is to enable the creation of more modern, game engine-level content within Java Minecraft. We strive to provide mod developers with the tools they need to push the boundaries of what is possible in Minecraft modding, bringing new and exciting experiences to players. + +## Contact + +If you have any questions, feel free to reach out to us through the issues section on GitHub. We're here to help and appreciate your efforts to improve Veil! From ade732385e39b52d32eae1d2646ef58bc44de7ad Mon Sep 17 00:00:00 2001 From: Xyndra <71836523+Xyndra@users.noreply.github.com> Date: Sun, 14 Jul 2024 21:22:37 +0200 Subject: [PATCH 05/47] Render JavaDoc using GitHub Actions (#22) * Create publish-javadoc.yml * Javadoc no failOnError * Update publish-javadoc.yml * Update publish-javadoc.yml * Update publish-javadoc.yml * Update publish-javadoc.yml * Update publish-javadoc.yml * Update publish-javadoc.yml --- .github/workflows/publish-javadoc.yml | 37 +++++++++++++++++++++++++++ build.gradle | 5 ++++ 2 files changed, 42 insertions(+) create mode 100644 .github/workflows/publish-javadoc.yml diff --git a/.github/workflows/publish-javadoc.yml b/.github/workflows/publish-javadoc.yml new file mode 100644 index 00000000..2bdbeedf --- /dev/null +++ b/.github/workflows/publish-javadoc.yml @@ -0,0 +1,37 @@ +name: Deploy Javadoc + +on: + push: + branches: + - 1.20 + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: write # if you have a protection rule on your repository, you'll need to give write permission to the workflow. + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Debug - List directory contents + run: | + pwd + ls -R + + - name: Deploy JavaDoc 🚀 + uses: MathieuSoysal/Javadoc-publisher.yml@v2.5.0 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + javadoc-branch: javadoc + java-version: 17 + javadoc-source-folder: common/build/docs/javadoc + project: gradle + + + - name: Debug - List directory contents + run: | + pwd + ls -R + if: always() diff --git a/build.gradle b/build.gradle index 6f8e1a0a..8b8a5fb3 100644 --- a/build.gradle +++ b/build.gradle @@ -12,6 +12,11 @@ subprojects { java.toolchain.languageVersion = JavaLanguageVersion.of(17) java.withSourcesJar() + + javadoc { + failOnError = false + } + jar { from(rootProject.file("LICENSE")) { rename { "${it}_${mod_name}" } From 899d07f66ba8716dd84a794681b0d17089d69f20 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Sun, 14 Jul 2024 13:35:39 -0600 Subject: [PATCH 06/47] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 49e8e4b1..d9f70d3c 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![Veil 1.20](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fmaven.blamejared.com%2Ffoundry%2Fveil%2FVeil-common-1.20.1%2Fmaven-metadata.xml&label=Veil%201.20)](https://maven.blamejared.com/foundry/veil/Veil-common-1.20.1/) [![Veil 1.20.4](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fmaven.blamejared.com%2Ffoundry%2Fveil%2FVeil-common-1.20.4%2Fmaven-metadata.xml&label=Veil%201.20.4)](https://maven.blamejared.com/foundry/veil/Veil-common-1.20.4/) +[![Javadoc](https://img.shields.io/badge/javadoc-latest-blue)](https://foundrymc.github.io/Veil/) Veil is a sophisticated collection of tools and utilities designed to facilitate advanced rendering for Minecraft mod developers. Our goal is to enable more modern game-engine level content in Java Minecraft, pushing the boundaries of what is possible in modding. From db19d3bfcef36e764e7a0fff91f29655f8054799 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Tue, 16 Jul 2024 16:22:55 -0600 Subject: [PATCH 07/47] Added imgui context switching --- common/src/main/java/foundry/veil/Veil.java | 21 +++++++- .../api/client/editor/EditorFontManager.java | 25 +++++---- .../veil/api/client/editor/EditorManager.java | 2 +- .../veil/api/client/imgui/VeilImGui.java | 4 ++ .../api/client/render/VeilRenderSystem.java | 4 +- .../client/imgui/InactiveVeilImGuiImpl.java | 8 +++ .../veil/impl/client/imgui/VeilImGuiImpl.java | 53 +++++++++++++++++-- .../impl/client/imgui/VeilImGuiImplGlfw.java | 47 ++++++++++++++++ .../client/imgui/KeyboardHandlerMixin.java | 18 +++++-- .../mixin/client/imgui/MouseHandlerMixin.java | 40 ++++++++++---- 10 files changed, 190 insertions(+), 32 deletions(-) create mode 100644 common/src/main/java/foundry/veil/impl/client/imgui/VeilImGuiImplGlfw.java diff --git a/common/src/main/java/foundry/veil/Veil.java b/common/src/main/java/foundry/veil/Veil.java index e766e879..fc3e719e 100644 --- a/common/src/main/java/foundry/veil/Veil.java +++ b/common/src/main/java/foundry/veil/Veil.java @@ -1,6 +1,8 @@ package foundry.veil; +import foundry.veil.api.client.imgui.VeilImGui; import foundry.veil.api.molang.VeilMolang; +import foundry.veil.impl.client.imgui.VeilImGuiImpl; import foundry.veil.platform.VeilPlatform; import gg.moonflower.molangcompiler.api.MolangCompiler; import net.minecraft.resources.ResourceLocation; @@ -24,7 +26,7 @@ public class Veil { static { DEBUG = System.getProperty("veil.debug") != null; - IMGUI = System.getProperty("veil.disableImgui") == null && !PLATFORM.isModLoaded("axiom"); + IMGUI = System.getProperty("veil.disableImgui") == null; VERBOSE_SHADER_ERRORS = System.getProperty("veil.verboseShaderErrors") != null; } @@ -40,6 +42,23 @@ public static void init() { VeilMolang.set(MolangCompiler.create(MolangCompiler.DEFAULT_FLAGS, Veil.class.getClassLoader())); } + /** + *

Enables writing ImGui to the screen. This useful for debugging during the normal render loop.

+ *

Be sure to call {@link #endImGui()} when done.

+ */ + public static VeilImGui beginImGui() { + VeilImGui imGui = VeilImGuiImpl.get(); + imGui.begin(); + return imGui; + } + + /** + * Disables ImGui writing. This should be called after done using ImGui during the main render loop. + */ + public static void endImGui() { + VeilImGuiImpl.get().end(); + } + public static ResourceLocation veilPath(String path) { return new ResourceLocation(MODID, path); } diff --git a/common/src/main/java/foundry/veil/api/client/editor/EditorFontManager.java b/common/src/main/java/foundry/veil/api/client/editor/EditorFontManager.java index 28ac0175..119fbbc0 100644 --- a/common/src/main/java/foundry/veil/api/client/editor/EditorFontManager.java +++ b/common/src/main/java/foundry/veil/api/client/editor/EditorFontManager.java @@ -113,17 +113,22 @@ public ImFont getFont(ResourceLocation name, boolean bold, boolean italic) { } public void rebuildFonts() { - ImFontAtlas atlas = ImGui.getIO().getFonts(); - atlas.clear(); - this.defaultFont = atlas.addFontDefault(); - - this.fonts.clear(); - for (Map.Entry entry : this.fontBuilders.entrySet()) { - Veil.LOGGER.info("Built {}", entry.getKey()); - this.fonts.put(entry.getKey(), entry.getValue().build(FONT_SIZE)); + try { + Veil.beginImGui(); + ImFontAtlas atlas = ImGui.getIO().getFonts(); + atlas.clear(); + this.defaultFont = atlas.addFontDefault(); + + this.fonts.clear(); + for (Map.Entry entry : this.fontBuilders.entrySet()) { + Veil.LOGGER.info("Built {}", entry.getKey()); + this.fonts.put(entry.getKey(), entry.getValue().build(FONT_SIZE)); + } + ImGui.getIO().setFontDefault(this.getFont(EditorManager.DEFAULT_FONT, false, false)); + VeilImGuiImpl.get().updateFonts(); + } finally { + Veil.endImGui(); } - ImGui.getIO().setFontDefault(this.getFont(EditorManager.DEFAULT_FONT, false, false)); - VeilImGuiImpl.get().updateFonts(); } private record FontPack(ImFont regular, ImFont italic, ImFont bold, ImFont boldItalic) implements NativeResource { diff --git a/common/src/main/java/foundry/veil/api/client/editor/EditorManager.java b/common/src/main/java/foundry/veil/api/client/editor/EditorManager.java index ca3754b6..9009828e 100644 --- a/common/src/main/java/foundry/veil/api/client/editor/EditorManager.java +++ b/common/src/main/java/foundry/veil/api/client/editor/EditorManager.java @@ -60,7 +60,7 @@ public void render() { if (ImGui.beginMainMenuBar()) { ImFont font = ImGui.getFont(); - float dingleWidth = font.calcTextSizeAX(ImGui.getFontSize(), Float.MAX_VALUE, 0, "Veil ") + 4; + float dingleWidth = font.calcTextSizeAX(ImGui.getFontSize(), Float.MAX_VALUE, 0, " Veil ") + 4; float dingleHeight = ImGui.getTextLineHeightWithSpacing() + 2; ImGui.getWindowDrawList().addRectFilled(0f, 0f, dingleWidth, dingleHeight, ImGui.getColorU32(ImGuiCol.FrameBgHovered)); ImGui.text("Veil "); diff --git a/common/src/main/java/foundry/veil/api/client/imgui/VeilImGui.java b/common/src/main/java/foundry/veil/api/client/imgui/VeilImGui.java index 60a1048a..35601339 100644 --- a/common/src/main/java/foundry/veil/api/client/imgui/VeilImGui.java +++ b/common/src/main/java/foundry/veil/api/client/imgui/VeilImGui.java @@ -16,6 +16,10 @@ public interface VeilImGui extends NativeResource { void begin(); + void beginFrame(); + + void endFrame(); + void end(); void onGrabMouse(); diff --git a/common/src/main/java/foundry/veil/api/client/render/VeilRenderSystem.java b/common/src/main/java/foundry/veil/api/client/render/VeilRenderSystem.java index aa135153..c8390804 100644 --- a/common/src/main/java/foundry/veil/api/client/render/VeilRenderSystem.java +++ b/common/src/main/java/foundry/veil/api/client/render/VeilRenderSystem.java @@ -640,12 +640,12 @@ public static Vector3fc getLight1Position() { @ApiStatus.Internal public static void beginFrame() { - VeilImGuiImpl.get().begin(); + VeilImGuiImpl.get().beginFrame(); } @ApiStatus.Internal public static void endFrame() { - VeilImGuiImpl.get().end(); + VeilImGuiImpl.get().endFrame(); renderer.getFramebufferManager().clear(); UNIFORM_BLOCK_STATE.clear(); } diff --git a/common/src/main/java/foundry/veil/impl/client/imgui/InactiveVeilImGuiImpl.java b/common/src/main/java/foundry/veil/impl/client/imgui/InactiveVeilImGuiImpl.java index 93485e98..008c28e8 100644 --- a/common/src/main/java/foundry/veil/impl/client/imgui/InactiveVeilImGuiImpl.java +++ b/common/src/main/java/foundry/veil/impl/client/imgui/InactiveVeilImGuiImpl.java @@ -15,6 +15,14 @@ public class InactiveVeilImGuiImpl implements VeilImGui { public void begin() { } + @Override + public void beginFrame() { + } + + @Override + public void endFrame() { + } + @Override public void end() { } diff --git a/common/src/main/java/foundry/veil/impl/client/imgui/VeilImGuiImpl.java b/common/src/main/java/foundry/veil/impl/client/imgui/VeilImGuiImpl.java index 088750ed..24fe3f42 100644 --- a/common/src/main/java/foundry/veil/impl/client/imgui/VeilImGuiImpl.java +++ b/common/src/main/java/foundry/veil/impl/client/imgui/VeilImGuiImpl.java @@ -30,24 +30,50 @@ public class VeilImGuiImpl implements VeilImGui { private final ImGuiImplGlfw implGlfw; private final ImGuiImplGl3 implGl3; + private final ImGuiContext oldImGuiContext; + private final ImPlotContext oldImPlotContext; private final ImGuiContext imGuiContext; private final ImPlotContext imPlotContext; private boolean active; + private int beginLayer; private VeilImGuiImpl(long window) { - this.implGlfw = new ImGuiImplGlfw(); + this.implGlfw = new VeilImGuiImplGlfw(); this.implGl3 = new ImGuiImplGl3(); - this.imGuiContext = ImGui.createContext(); - this.imPlotContext = ImPlot.createContext(); + this.oldImGuiContext = new ImGuiContext(ImGui.getCurrentContext().ptr); + this.oldImPlotContext = new ImPlotContext(ImPlot.getCurrentContext().ptr); + + this.imGuiContext = new ImGuiContext(ImGui.createContext().ptr); + this.imPlotContext = new ImPlotContext(ImPlot.createContext().ptr); this.implGlfw.init(window, true); this.implGl3.init("#version 410 core"); VeilImGuiStylesheet.initStyles(); + + ImGui.setCurrentContext(this.oldImGuiContext); + ImPlot.setCurrentContext(this.oldImPlotContext); } @Override public void begin() { + this.beginLayer++; + + if (ImGui.getCurrentContext().ptr == this.imGuiContext.ptr) { + return; + } + + this.oldImGuiContext.ptr = ImGui.getCurrentContext().ptr; + this.oldImPlotContext.ptr = ImPlot.getCurrentContext().ptr; + + ImGui.setCurrentContext(this.imGuiContext); + ImPlot.setCurrentContext(this.imPlotContext); + } + + @Override + public void beginFrame() { + this.begin(); + if (this.active) { Veil.LOGGER.error("ImGui failed to render previous frame, disposing"); ImGui.endFrame(); @@ -57,14 +83,19 @@ public void begin() { ImGui.newFrame(); VeilRenderSystem.renderer().getEditorManager().render(); + + this.end(); } @Override - public void end() { + public void endFrame() { if (!this.active) { Veil.LOGGER.error("ImGui state de-synced"); + this.end(); return; } + this.begin(); + this.active = false; VeilRenderSystem.renderer().getEditorManager().renderLast(); ImGui.render(); @@ -76,6 +107,20 @@ public void end() { ImGui.renderPlatformWindowsDefault(); glfwMakeContextCurrent(backupWindowPtr); } + + if (this.beginLayer > 1) { + Veil.LOGGER.error("Mismatched begin/end during frame"); + this.beginLayer = 1; + } + this.end(); + } + + @Override + public void end() { + if (--this.beginLayer == 0) { + ImGui.setCurrentContext(this.oldImGuiContext); + ImPlot.setCurrentContext(this.oldImPlotContext); + } } @Override diff --git a/common/src/main/java/foundry/veil/impl/client/imgui/VeilImGuiImplGlfw.java b/common/src/main/java/foundry/veil/impl/client/imgui/VeilImGuiImplGlfw.java new file mode 100644 index 00000000..61d34acd --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/client/imgui/VeilImGuiImplGlfw.java @@ -0,0 +1,47 @@ +package foundry.veil.impl.client.imgui; + +import foundry.veil.Veil; +import imgui.glfw.ImGuiImplGlfw; + +public class VeilImGuiImplGlfw extends ImGuiImplGlfw { + + @Override + public void scrollCallback(long windowId, double xOffset, double yOffset) { + try { + Veil.beginImGui(); + super.scrollCallback(windowId, xOffset, yOffset); + } finally { + Veil.endImGui(); + } + } + + @Override + public void keyCallback(long windowId, int key, int scancode, int action, int mods) { + try { + Veil.beginImGui(); + super.keyCallback(windowId, key, scancode, action, mods); + } finally { + Veil.endImGui(); + } + } + + @Override + public void windowFocusCallback(long windowId, boolean focused) { + try { + Veil.beginImGui(); + super.windowFocusCallback(windowId, focused); + } finally { + Veil.endImGui(); + } + } + + @Override + public void charCallback(long windowId, int c) { + try { + Veil.beginImGui(); + super.charCallback(windowId, c); + } finally { + Veil.endImGui(); + } + } +} diff --git a/common/src/main/java/foundry/veil/mixin/client/imgui/KeyboardHandlerMixin.java b/common/src/main/java/foundry/veil/mixin/client/imgui/KeyboardHandlerMixin.java index e02b9fac..784045aa 100644 --- a/common/src/main/java/foundry/veil/mixin/client/imgui/KeyboardHandlerMixin.java +++ b/common/src/main/java/foundry/veil/mixin/client/imgui/KeyboardHandlerMixin.java @@ -1,6 +1,6 @@ package foundry.veil.mixin.client.imgui; -import foundry.veil.impl.client.imgui.VeilImGuiImpl; +import foundry.veil.Veil; import net.minecraft.client.KeyboardHandler; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -12,15 +12,23 @@ public class KeyboardHandlerMixin { @Inject(method = "keyPress", at = @At("HEAD"), cancellable = true) public void keyCallback(long window, int key, int scancode, int action, int mods, CallbackInfo ci) { - if (VeilImGuiImpl.get().keyCallback(window, key, scancode, action, mods)) { - ci.cancel(); + try { + if (Veil.beginImGui().keyCallback(window, key, scancode, action, mods)) { + ci.cancel(); + } + } finally { + Veil.endImGui(); } } @Inject(method = "charTyped", at = @At("HEAD"), cancellable = true) public void charCallback(long window, int codepoint, int mods, CallbackInfo ci) { - if (VeilImGuiImpl.get().charCallback(window, codepoint)) { - ci.cancel(); + try { + if (Veil.beginImGui().charCallback(window, codepoint)) { + ci.cancel(); + } + } finally { + Veil.endImGui(); } } } diff --git a/common/src/main/java/foundry/veil/mixin/client/imgui/MouseHandlerMixin.java b/common/src/main/java/foundry/veil/mixin/client/imgui/MouseHandlerMixin.java index e02dccee..1b81e436 100644 --- a/common/src/main/java/foundry/veil/mixin/client/imgui/MouseHandlerMixin.java +++ b/common/src/main/java/foundry/veil/mixin/client/imgui/MouseHandlerMixin.java @@ -1,5 +1,7 @@ package foundry.veil.mixin.client.imgui; +import foundry.veil.Veil; +import foundry.veil.api.client.imgui.VeilImGui; import foundry.veil.impl.client.imgui.VeilImGuiImpl; import net.minecraft.client.MouseHandler; import org.spongepowered.asm.mixin.Mixin; @@ -13,34 +15,54 @@ public class MouseHandlerMixin { @Inject(method = "onPress", at = @At("HEAD"), cancellable = true) public void mouseButtonCallback(long window, int button, int action, int mods, CallbackInfo ci) { - if (VeilImGuiImpl.get().mouseButtonCallback(window, button, action, mods)) { - ci.cancel(); + try { + if (Veil.beginImGui().mouseButtonCallback(window, button, action, mods)) { + ci.cancel(); + } + } finally { + Veil.endImGui(); } } @Inject(method = "onScroll", at = @At("HEAD"), cancellable = true) public void scrollCallback(long window, double xOffset, double yOffset, CallbackInfo ci) { - if (VeilImGuiImpl.get().scrollCallback(window, xOffset, yOffset)) { - ci.cancel(); + try { + if (Veil.beginImGui().scrollCallback(window, xOffset, yOffset)) { + ci.cancel(); + } + } finally { + Veil.endImGui(); } } @Inject(method = "grabMouse", at = @At("HEAD")) public void grabMouse(CallbackInfo ci) { - VeilImGuiImpl.get().onGrabMouse(); + try { + Veil.beginImGui().onGrabMouse(); + } finally { + Veil.endImGui(); + } } @Inject(method = "xpos", at = @At("HEAD"), cancellable = true) public void cancelMouseX(CallbackInfoReturnable cir) { - if (VeilImGuiImpl.get().shouldHideMouse()) { - cir.setReturnValue(Double.MIN_VALUE); + try { + if (Veil.beginImGui().shouldHideMouse()) { + cir.setReturnValue(Double.MIN_VALUE); + } + } finally { + Veil.endImGui(); } } @Inject(method = "ypos", at = @At("HEAD"), cancellable = true) public void cancelMouseY(CallbackInfoReturnable cir) { - if (VeilImGuiImpl.get().shouldHideMouse()) { - cir.setReturnValue(Double.MIN_VALUE); + try { + if (Veil.beginImGui().shouldHideMouse()) { + cir.setReturnValue(Double.MIN_VALUE); + } + } finally { + Veil.endImGui(); } } } From 164fe795e088208e67c35bbd22ae6ced4b73a242 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Tue, 16 Jul 2024 16:25:08 -0600 Subject: [PATCH 08/47] Fixed crash when closing game --- .../main/java/foundry/veil/impl/client/imgui/VeilImGuiImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/src/main/java/foundry/veil/impl/client/imgui/VeilImGuiImpl.java b/common/src/main/java/foundry/veil/impl/client/imgui/VeilImGuiImpl.java index 24fe3f42..26a535e7 100644 --- a/common/src/main/java/foundry/veil/impl/client/imgui/VeilImGuiImpl.java +++ b/common/src/main/java/foundry/veil/impl/client/imgui/VeilImGuiImpl.java @@ -170,10 +170,12 @@ public boolean shouldHideMouse() { @Override public void free() { + this.begin(); this.implGlfw.dispose(); this.implGl3.dispose(); ImGui.destroyContext(this.imGuiContext); ImPlot.destroyContext(this.imPlotContext); + this.end(); } public static void init(long window) { From c7aefce04c810ddc18bc06cf4ae01fc503519862 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Tue, 16 Jul 2024 16:29:21 -0600 Subject: [PATCH 09/47] Added DiffuseSampler uniform --- .../render/shader/program/TextureUniformAccess.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/common/src/main/java/foundry/veil/api/client/render/shader/program/TextureUniformAccess.java b/common/src/main/java/foundry/veil/api/client/render/shader/program/TextureUniformAccess.java index d850651c..ae91cce0 100644 --- a/common/src/main/java/foundry/veil/api/client/render/shader/program/TextureUniformAccess.java +++ b/common/src/main/java/foundry/veil/api/client/render/shader/program/TextureUniformAccess.java @@ -30,6 +30,7 @@ default void addRenderSystemTextures() { * @param framebuffer The framebuffer to bind samplers from */ default void setFramebufferSamplers(AdvancedFbo framebuffer) { + boolean setDiffuseSampler = false; for (int i = 0; i < framebuffer.getColorAttachments(); i++) { if (!framebuffer.isColorTextureAttachment(i)) { continue; @@ -40,6 +41,10 @@ default void setFramebufferSamplers(AdvancedFbo framebuffer) { if (attachment.getName() != null) { this.addSampler(attachment.getName(), attachment.getId()); } + if (!setDiffuseSampler) { + this.addSampler("DiffuseSampler", attachment.getId()); + setDiffuseSampler = true; + } } if (framebuffer.isDepthTextureAttachment()) { @@ -53,12 +58,14 @@ default void setFramebufferSamplers(AdvancedFbo framebuffer) { /** * Adds a listener for sampler updates. + * * @param listener The listener instance */ void addSamplerListener(SamplerListener listener); /** * Removes a listener from sampler updates. + * * @param listener The listener instance */ void removeSamplerListener(SamplerListener listener); @@ -110,6 +117,7 @@ interface SamplerListener { /** * Called to update the listener with the new texture units for the specified textures. + * * @param boundSamplers The textures bound */ void onUpdateSamplers(Object2IntMap boundSamplers); From a0562f7153b03644fc08e640b4d2c51fe1dadb1d Mon Sep 17 00:00:00 2001 From: Ocelot Date: Fri, 19 Jul 2024 09:57:31 -0600 Subject: [PATCH 10/47] Fixed platform loop. Fixes #17 --- .../foundry/veil/impl/client/editor/DeviceInfoViewer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/foundry/veil/impl/client/editor/DeviceInfoViewer.java b/common/src/main/java/foundry/veil/impl/client/editor/DeviceInfoViewer.java index d756aac2..b37ac4c4 100644 --- a/common/src/main/java/foundry/veil/impl/client/editor/DeviceInfoViewer.java +++ b/common/src/main/java/foundry/veil/impl/client/editor/DeviceInfoViewer.java @@ -200,8 +200,8 @@ private void renderOpenCL() { VeilOpenCL.DeviceInfo[] devices = platform.devices(); title(CL_DEVICES); for (int j = 0; j < devices.length; j++) { - VeilOpenCL.DeviceInfo device = devices[i]; - if (!ImGui.collapsingHeader(I18n.get("editor.veil.device_info.opencl.device", device.name(), device.id()), i == 0 ? ImGuiTreeNodeFlags.DefaultOpen : 0)) { + VeilOpenCL.DeviceInfo device = devices[j]; + if (!ImGui.collapsingHeader(I18n.get("editor.veil.device_info.opencl.device", device.name(), device.id()), j == 0 ? ImGuiTreeNodeFlags.DefaultOpen : 0)) { continue; } From bc4ff8ae9998ea206855d6c38b7dfe89db60418b Mon Sep 17 00:00:00 2001 From: Ocelot Date: Sun, 21 Jul 2024 19:56:54 -0600 Subject: [PATCH 11/47] Fixed final framebuffers not being hdr --- .../assets/veil/pinwheel/framebuffers/opaque_final.json | 2 +- .../assets/veil/pinwheel/framebuffers/transparent_final.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/framebuffers/opaque_final.json b/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/framebuffers/opaque_final.json index 6a281cbb..2565a018 100644 --- a/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/framebuffers/opaque_final.json +++ b/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/framebuffers/opaque_final.json @@ -2,7 +2,7 @@ "depth": true, "color_buffers": [ { - "format": "RGBA8" + "format": "RGB16F" } ] } \ No newline at end of file diff --git a/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/framebuffers/transparent_final.json b/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/framebuffers/transparent_final.json index 6a281cbb..2565a018 100644 --- a/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/framebuffers/transparent_final.json +++ b/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/framebuffers/transparent_final.json @@ -2,7 +2,7 @@ "depth": true, "color_buffers": [ { - "format": "RGBA8" + "format": "RGB16F" } ] } \ No newline at end of file From cff3b171851d27fd5b1cb76c2999051378c7bec9 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Sun, 21 Jul 2024 20:33:45 -0600 Subject: [PATCH 12/47] Fixed HDR data not being accessible by post --- .../render/deferred/VeilDeferredRenderer.java | 11 +++- .../render/post/PostProcessingManager.java | 54 +++++++++---------- .../pipeline/VeilFirstPersonRenderer.java | 11 ++-- .../veil/pinwheel/post/first_person.json | 2 +- .../pinwheel/framebuffers/opaque_final.json | 6 +-- .../framebuffers/transparent_final.json | 6 +-- fabric/build.gradle | 4 +- 7 files changed, 43 insertions(+), 51 deletions(-) diff --git a/common/src/main/java/foundry/veil/api/client/render/deferred/VeilDeferredRenderer.java b/common/src/main/java/foundry/veil/api/client/render/deferred/VeilDeferredRenderer.java index ebda2c7b..58b78f8c 100644 --- a/common/src/main/java/foundry/veil/api/client/render/deferred/VeilDeferredRenderer.java +++ b/common/src/main/java/foundry/veil/api/client/render/deferred/VeilDeferredRenderer.java @@ -2,6 +2,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import foundry.veil.Veil; +import foundry.veil.api.client.render.VeilRenderSystem; import foundry.veil.api.client.render.VeilRenderer; import foundry.veil.api.client.render.deferred.light.renderer.LightRenderer; import foundry.veil.api.client.render.framebuffer.AdvancedFbo; @@ -239,6 +240,11 @@ private void run(ProfilerFiller profiler, AdvancedFbo deferred, AdvancedFbo ligh @ApiStatus.Internal public void blit() { if (!this.isEnabled() || this.state == RendererState.DISABLED) { + // Resolve the main framebuffer to the post one for later post-processing + AdvancedFbo postFramebuffer = VeilRenderSystem.renderer().getFramebufferManager().getFramebuffer(VeilFramebuffers.POST); + if (postFramebuffer != null) { + AdvancedFbo.getMainFramebuffer().resolveToAdvancedFbo(postFramebuffer); + } return; } @@ -278,8 +284,9 @@ public void blit() { RenderSystem.disableBlend(); } - profiler.popPush("resolve"); - post.resolveToFramebuffer(Minecraft.getInstance().getMainRenderTarget()); + // Don't resolve to the main framebuffer to preserve the HDR data +// profiler.popPush("resolve"); +// post.resolveToFramebuffer(Minecraft.getInstance().getMainRenderTarget()); profiler.pop(); profiler.pop(); diff --git a/common/src/main/java/foundry/veil/api/client/render/post/PostProcessingManager.java b/common/src/main/java/foundry/veil/api/client/render/post/PostProcessingManager.java index f569b865..9cc9b24a 100644 --- a/common/src/main/java/foundry/veil/api/client/render/post/PostProcessingManager.java +++ b/common/src/main/java/foundry/veil/api/client/render/post/PostProcessingManager.java @@ -143,40 +143,34 @@ private void clearPipeline() { @ApiStatus.Internal public void runPipeline() { - if (this.activePipelines.isEmpty()) { - return; - } - - AdvancedFbo postFramebuffer = VeilRenderSystem.renderer().getFramebufferManager().getFramebuffer(VeilFramebuffers.POST); - if (postFramebuffer != null) { - AdvancedFbo.getMainFramebuffer().resolveToAdvancedFbo(postFramebuffer); - } - - VeilClientPlatform platform = VeilClient.clientPlatform(); - this.context.begin(); - this.setup(); - int activeTexture = GlStateManager._getActiveTexture(); - - this.activePipelines.sort(PIPELINE_SORTER); - for (ProfileEntry entry : this.activePipelines) { - ResourceLocation id = entry.getPipeline(); - PostPipeline pipeline = this.pipelines.get(id); - if (pipeline != null) { - platform.preVeilPostProcessing(id, pipeline, this.context); - try { - pipeline.apply(this.context); - this.clearPipeline(); - } catch (Exception e) { - Veil.LOGGER.error("Error running pipeline {}", id, e); + if (!this.activePipelines.isEmpty()) { + VeilClientPlatform platform = VeilClient.clientPlatform(); + this.context.begin(); + this.setup(); + int activeTexture = GlStateManager._getActiveTexture(); + + this.activePipelines.sort(PIPELINE_SORTER); + for (ProfileEntry entry : this.activePipelines) { + ResourceLocation id = entry.getPipeline(); + PostPipeline pipeline = this.pipelines.get(id); + if (pipeline != null) { + platform.preVeilPostProcessing(id, pipeline, this.context); + try { + pipeline.apply(this.context); + this.clearPipeline(); + } catch (Exception e) { + Veil.LOGGER.error("Error running pipeline {}", id, e); + } + platform.postVeilPostProcessing(id, pipeline, this.context); } - platform.postVeilPostProcessing(id, pipeline, this.context); } - } - RenderSystem.activeTexture(activeTexture); - this.clear(); - this.context.end(); + RenderSystem.activeTexture(activeTexture); + this.clear(); + this.context.end(); + } + AdvancedFbo postFramebuffer = VeilRenderSystem.renderer().getFramebufferManager().getFramebuffer(VeilFramebuffers.POST); if (postFramebuffer != null) { postFramebuffer.resolveToFramebuffer(Minecraft.getInstance().getMainRenderTarget()); } diff --git a/common/src/main/java/foundry/veil/impl/client/render/pipeline/VeilFirstPersonRenderer.java b/common/src/main/java/foundry/veil/impl/client/render/pipeline/VeilFirstPersonRenderer.java index caa2a5f8..62ed0368 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/pipeline/VeilFirstPersonRenderer.java +++ b/common/src/main/java/foundry/veil/impl/client/render/pipeline/VeilFirstPersonRenderer.java @@ -1,6 +1,5 @@ package foundry.veil.impl.client.render.pipeline; -import com.mojang.blaze3d.pipeline.RenderTarget; import foundry.veil.Veil; import foundry.veil.api.client.render.VeilRenderSystem; import foundry.veil.api.client.render.VeilRenderer; @@ -9,7 +8,6 @@ import foundry.veil.api.client.render.framebuffer.VeilFramebuffers; import foundry.veil.api.client.render.post.PostPipeline; import foundry.veil.api.client.render.post.PostProcessingManager; -import net.minecraft.client.Minecraft; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.ApiStatus; @@ -27,13 +25,14 @@ private VeilFirstPersonRenderer() { } public static void bind() { - RenderTarget mainRenderTarget = Minecraft.getInstance().getMainRenderTarget(); - int w = mainRenderTarget.width; - int h = mainRenderTarget.height; + AdvancedFbo postTarget = VeilRenderSystem.renderer().getFramebufferManager().getFramebuffer(VeilFramebuffers.POST); + AdvancedFbo mainRenderTarget = postTarget != null ? postTarget : AdvancedFbo.getMainFramebuffer(); + int w = mainRenderTarget.getWidth(); + int h = mainRenderTarget.getHeight(); if (firstPerson == null || firstPerson.getWidth() != w || firstPerson.getHeight() != h) { free(); firstPerson = AdvancedFbo.withSize(w, h) - .addColorTextureWrapper(mainRenderTarget.getColorTextureId(), w, h) + .addColorTextureWrapper(mainRenderTarget.getColorTextureAttachment(0).getId(), w, h) .setFormat(FramebufferAttachmentDefinition.Format.DEPTH_COMPONENT) .setDepthTextureBuffer() .build(true); diff --git a/common/src/main/resources/assets/veil/pinwheel/post/first_person.json b/common/src/main/resources/assets/veil/pinwheel/post/first_person.json index 37703ed1..89f3d48b 100644 --- a/common/src/main/resources/assets/veil/pinwheel/post/first_person.json +++ b/common/src/main/resources/assets/veil/pinwheel/post/first_person.json @@ -16,7 +16,7 @@ "type": "veil:blit", "shader": "veil:blit_depth", "in": "veil:first_person", - "out": "minecraft:main", + "out": "veil:post", "clear": false } ] diff --git a/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/framebuffers/opaque_final.json b/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/framebuffers/opaque_final.json index 2565a018..2fb4ca5f 100644 --- a/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/framebuffers/opaque_final.json +++ b/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/framebuffers/opaque_final.json @@ -1,8 +1,4 @@ { "depth": true, - "color_buffers": [ - { - "format": "RGB16F" - } - ] + "format": "RGBA16F" } \ No newline at end of file diff --git a/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/framebuffers/transparent_final.json b/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/framebuffers/transparent_final.json index 2565a018..2fb4ca5f 100644 --- a/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/framebuffers/transparent_final.json +++ b/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/framebuffers/transparent_final.json @@ -1,8 +1,4 @@ { "depth": true, - "color_buffers": [ - { - "format": "RGB16F" - } - ] + "format": "RGBA16F" } \ No newline at end of file diff --git a/fabric/build.gradle b/fabric/build.gradle index 7ef3b3b6..44f70d27 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -63,8 +63,8 @@ dependencies { modCompileOnly "maven.modrinth:sodium:mc1.20.1-0.5.3" modCompileOnly "maven.modrinth:iris:1.6.11+1.20.1" modCompileOnly "maven.modrinth:replaymod:1.20.1-2.6.15" - modRuntimeOnly "maven.modrinth:sodium:mc1.20.1-0.5.3" - modRuntimeOnly "maven.modrinth:iris:1.6.11+1.20.1" +// modRuntimeOnly "maven.modrinth:sodium:mc1.20.1-0.5.3" +// modRuntimeOnly "maven.modrinth:iris:1.6.11+1.20.1" // modRuntimeOnly "maven.modrinth:replaymod:1.20.1-2.6.15" api(include("org.antlr:antlr4-runtime:${antlr_version}")) From 82a180be5023b919ab51cb6eb85124a0f7f1a109 Mon Sep 17 00:00:00 2001 From: amo Date: Wed, 31 Jul 2024 03:06:15 +0100 Subject: [PATCH 13/47] default mc tooltip color theme --- .../java/foundry/veil/api/client/color/ColorTheme.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/common/src/main/java/foundry/veil/api/client/color/ColorTheme.java b/common/src/main/java/foundry/veil/api/client/color/ColorTheme.java index f951c418..14003473 100644 --- a/common/src/main/java/foundry/veil/api/client/color/ColorTheme.java +++ b/common/src/main/java/foundry/veil/api/client/color/ColorTheme.java @@ -2,12 +2,14 @@ import foundry.veil.api.client.color.theme.IThemeProperty; import foundry.veil.api.client.tooltip.Tooltippable; +import net.minecraft.Util; import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.function.Supplier; /** * A color theme is a collection of colors. The colors can be accessed by name. Themes are intended to be used for color schemes. @@ -19,6 +21,12 @@ */ public class ColorTheme { + public static final ColorTheme DEFAULT = new ColorTheme() {{ + addColor("background", Color.VANILLA_TOOLTIP_BACKGROUND); + addColor("topBorder", Color.VANILLA_TOOLTIP_BORDER_TOP); + addColor("bottomBorder", Color.VANILLA_TOOLTIP_BORDER_BOTTOM); + }}; + private final Map colors = new HashMap<>(); private final Map> properties = new HashMap<>(); From 3d4b471bdbda68532ba956d2e6cbd606421b8566 Mon Sep 17 00:00:00 2001 From: amo Date: Wed, 31 Jul 2024 03:06:30 +0100 Subject: [PATCH 14/47] UI helper goodies --- .../api/client/ui/util/PoseStackAnimator.java | 117 ++++++++++++++++++ .../veil/api/client/ui/util/ScissorStack.java | 79 ++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 common/src/main/java/foundry/veil/api/client/ui/util/PoseStackAnimator.java create mode 100644 common/src/main/java/foundry/veil/api/client/ui/util/ScissorStack.java diff --git a/common/src/main/java/foundry/veil/api/client/ui/util/PoseStackAnimator.java b/common/src/main/java/foundry/veil/api/client/ui/util/PoseStackAnimator.java new file mode 100644 index 00000000..529a8376 --- /dev/null +++ b/common/src/main/java/foundry/veil/api/client/ui/util/PoseStackAnimator.java @@ -0,0 +1,117 @@ +package foundry.veil.api.client.ui.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.util.Mth; + +/** + * A utility class to manage and apply animations to a {@link PoseStack}. + * Animations are defined as a sequence of {@link AnimationStage}s, each with a duration and a transformation function. + */ +public class PoseStackAnimator { + + private final PoseStack poseStack; + private final List stages = new ArrayList<>(); + private int currentStageIndex = -1; + private long stageStartTime; + + /** + * Constructs a new {@link PoseStackAnimator} for the given {@link PoseStack}. + * @param poseStack The {@link PoseStack} to animate. + */ + public PoseStackAnimator(PoseStack poseStack) { + this.poseStack = poseStack; + } + + /** + * Adds a new animation stage to the sequence. + * @param durationMillis The duration of the stage in milliseconds. + * @param transform The transformation function to apply during this stage. + * This function receives the {@link PoseStack} as an argument, allowing you to directly modify its transformations. + */ + public void addStage(long durationMillis, BiConsumer transform) { + stages.add(new AnimationStage(durationMillis, transform)); + } + + /** + * Starts the animation sequence. + */ + public void startAnimation() { + currentStageIndex = 0; + stageStartTime = System.currentTimeMillis(); + } + + /** + * Advances the animation based on the elapsed time. + * Call this method once per frame to update the animation. + */ + public void tickAnimation() { + if (isAnimating()) { + AnimationStage currentStage = stages.get(currentStageIndex); + + long elapsedStageTime = System.currentTimeMillis() - stageStartTime; + float progress = Mth.clamp((float) elapsedStageTime / currentStage.durationMillis, 0.0F, 1.0F); + + applyStageTransform(currentStage, progress); + + if (progress >= 1.0F && currentStageIndex < stages.size() - 1) { + currentStageIndex++; + stageStartTime = System.currentTimeMillis(); + } else if (progress >= 1.0F) { + resetAnimation(); + } + } + } + + /** + * Checks if the animation is currently active. + * @return True if the animation is running, false otherwise. + */ + public boolean isAnimating() { + return currentStageIndex >= 0 && currentStageIndex < stages.size(); + } + + /** + * Resets the animation, stopping it and clearing any defined stages. + */ + public void resetAnimation() { + currentStageIndex = -1; + stages.clear(); + } + + /** + * Applies the transformation for the current animation stage based on the animation progress. + * This method ensures that each stage's transformation is applied independently and doesn't affect other stages. + * @param stage The current animation stage. + * @param progress The animation progress within the current stage, ranging from 0.0 to 1.0. + */ + private void applyStageTransform(AnimationStage stage, float progress) { + poseStack.pushPose(); // Isolate this stage's transformations + + long elapsedStageTime = (long) (progress * stage.durationMillis); + stage.transform.accept(elapsedStageTime, poseStack); // Apply the stage's transform function + + poseStack.popPose(); // Restore the pose stack to its previous state + } + + /** + * Represents a single stage in the animation sequence, holding its duration and the transformation function. + */ + private static class AnimationStage { + long durationMillis; + BiConsumer transform; + + /** + * Constructs a new animation stage. + * @param durationMillis The duration of the stage in milliseconds. + * @param transform The transformation function to apply during this stage. + */ + AnimationStage(long durationMillis, BiConsumer transform) { + this.durationMillis = durationMillis; + this.transform = transform; + } + } +} \ No newline at end of file diff --git a/common/src/main/java/foundry/veil/api/client/ui/util/ScissorStack.java b/common/src/main/java/foundry/veil/api/client/ui/util/ScissorStack.java new file mode 100644 index 00000000..7cebe581 --- /dev/null +++ b/common/src/main/java/foundry/veil/api/client/ui/util/ScissorStack.java @@ -0,0 +1,79 @@ +package foundry.veil.api.client.ui.util; + +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.Minecraft; +import net.minecraft.util.Mth; + +import java.util.ArrayDeque; +import java.util.Deque; + +/** + * A utility class to manage scissor clipping regions. + * This allows for restricting rendering to specific rectangular areas. + */ +public class ScissorStack { + private final Deque regions = new ArrayDeque<>(); + + public ScissorStack() { + } + + /** + * Pushes a new scissor clipping region onto the stack. + * The region is automatically constrained by any existing regions on the stack. + * + * @param x The x-coordinate of the top-left corner of the region. + * @param y The y-coordinate of the top-left corner of the region. + * @param width The width of the region. + * @param height The height of the region. + */ + public void push(int x, int y, int width, int height) { + if (!regions.isEmpty()) { + ScissorRegion parent = regions.peek(); + int x2 = x + width; + x = Mth.clamp(x, parent.x, parent.x + parent.width); + width = Mth.clamp(x2, parent.x, parent.x + parent.width) - x; + int y2 = y + height; + y = Mth.clamp(y, parent.y, parent.y + parent.height); + height = Mth.clamp(y2, parent.y, parent.y + parent.height) - y; + } + + ScissorRegion region = new ScissorRegion(x, y, width, height); + regions.push(region); + region.apply(); + } + + /** + * Removes the top scissor clipping region from the stack. + * If there are any regions remaining, the previous region is reapplied. + */ + public void pop() { + regions.pop(); + RenderSystem.disableScissor(); + if (!regions.isEmpty()) { + regions.peek().apply(); + } + } + + /** + * Represents a single scissor clipping region. + */ + private static class ScissorRegion { + int x, y, width, height; + + public ScissorRegion(int x, int y, int width, int height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + /** + * Applies this scissor region to the rendering system. + */ + void apply() { + double scale = Minecraft.getInstance().getWindow().getGuiScale(); + int screenY = (int) ((Minecraft.getInstance().getWindow().getHeight() - (y + height)) * scale); + RenderSystem.enableScissor((int) (x * scale), screenY, (int) (width * scale), (int) (height * scale)); + } + } +} \ No newline at end of file From 14b0c9ec5009af53b671596a7ec682101e306b2a Mon Sep 17 00:00:00 2001 From: Will BL Date: Thu, 8 Aug 2024 10:56:09 +0100 Subject: [PATCH 15/47] Quasar: The Registrying (#30) * feat(quasar): add emitter shape registry This allows mod devs to create custom emitter shapes. The codec retains backwards compatibility with enum-style names, like `CUBE`. Some of the emitters in test_particles resource pack have been changed to use resource locations, while others are still using enum-style names to verify that the codec doesn't break for them. * feat(quasar): add render style registry This allows mod devs to create custom render styles. The codec retains backwards compatibility with enum-style names, like `BILLBOARD`. * refactor(quasar): make ParticleModuleTypeRegistry use proper registries The codec retains backwards compatibility with names not prefixed with `veil:`, like `vortex` or `point_attractor` * refactor(quasar): rename particle module type registries --- .../main/java/foundry/veil/VeilClient.java | 6 + .../api/quasar/data/EmitterShapeSettings.java | 4 +- .../data/ParticleModuleTypeRegistry.java | 122 +++++++++------ .../api/quasar/data/QuasarParticleData.java | 8 +- .../api/quasar/data/module/ModuleType.java | 74 --------- .../collision/CollisionSubEmitterData.java | 3 +- .../collision/DieOnCollisionModuleData.java | 3 +- .../data/module/force/DragForceData.java | 3 +- .../data/module/force/GravityForceData.java | 3 +- .../module/force/PointAttractorForceData.java | 3 +- .../data/module/force/PointForceData.java | 3 +- .../module/force/VectorFieldForceData.java | 3 +- .../data/module/force/VortexForceData.java | 3 +- .../data/module/force/WindForceData.java | 3 +- .../module/init/BlockParticleModuleData.java | 3 +- .../init/InitSizeParticleModuleData.java | 3 +- .../module/init/InitSubEmitterModuleData.java | 3 +- .../init/InitialVelocityModuleData.java | 3 +- .../data/module/init/LightModuleData.java | 3 +- .../render/ColorParticleModuleData.java | 3 +- .../render/TrailParticleModuleData.java | 3 +- .../update/TickSizeParticleModuleData.java | 3 +- .../update/TickSubEmitterModuleData.java | 3 +- .../init/InitRandomRotationModuleData.java | 3 +- .../module/update/FaceVelocityModule.java | 3 +- .../quasar/emitters/shape/EmitterShape.java | 44 ++---- .../api/quasar/particle/ParticleEmitter.java | 2 +- .../veil/api/quasar/particle/RenderData.java | 140 ----------------- .../veil/api/quasar/particle/RenderStyle.java | 146 ++++++++++++++++++ .../quasar/registry/EmitterShapeRegistry.java | 43 ++++++ .../quasar/registry/RenderStyleRegistry.java | 33 ++++ .../java/foundry/veil/api/util/CodecUtil.java | 33 ++++ .../modules/emitter/shape/basic_smoke.json | 2 +- .../modules/emitter/shape/test_shape.json | 2 +- 34 files changed, 393 insertions(+), 326 deletions(-) create mode 100644 common/src/main/java/foundry/veil/api/quasar/particle/RenderStyle.java create mode 100644 common/src/main/java/foundry/veil/api/quasar/registry/EmitterShapeRegistry.java create mode 100644 common/src/main/java/foundry/veil/api/quasar/registry/RenderStyleRegistry.java diff --git a/common/src/main/java/foundry/veil/VeilClient.java b/common/src/main/java/foundry/veil/VeilClient.java index 64897057..49243865 100644 --- a/common/src/main/java/foundry/veil/VeilClient.java +++ b/common/src/main/java/foundry/veil/VeilClient.java @@ -7,6 +7,9 @@ import foundry.veil.api.client.render.VeilRenderer; import foundry.veil.api.client.render.deferred.VeilDeferredRenderer; import foundry.veil.api.event.VeilRenderLevelStageEvent; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; +import foundry.veil.api.quasar.registry.EmitterShapeRegistry; +import foundry.veil.api.quasar.registry.RenderStyleRegistry; import foundry.veil.impl.client.editor.*; import foundry.veil.impl.client.imgui.VeilImGuiImpl; import foundry.veil.impl.resource.VeilResourceManagerImpl; @@ -70,6 +73,9 @@ public static void init() { LightTypeRegistry.bootstrap(); RenderTypeLayerRegistry.bootstrap(); VeilResourceEditorRegistry.bootstrap(); + EmitterShapeRegistry.bootstrap(); + RenderStyleRegistry.bootstrap(); + ParticleModuleTypeRegistry.bootstrap(); } @ApiStatus.Internal diff --git a/common/src/main/java/foundry/veil/api/quasar/data/EmitterShapeSettings.java b/common/src/main/java/foundry/veil/api/quasar/data/EmitterShapeSettings.java index 8776c911..a5841823 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/EmitterShapeSettings.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/EmitterShapeSettings.java @@ -13,13 +13,13 @@ import org.joml.Vector3dc; import org.joml.Vector3fc; -public record EmitterShapeSettings(EmitterShape.Shape shape, +public record EmitterShapeSettings(EmitterShape shape, Vector3fc dimensions, Vector3fc rotation, boolean fromSurface) { public static final Codec DIRECT_CODEC = RecordCodecBuilder.create(instance -> instance.group( - EmitterShape.Shape.CODEC.fieldOf("shape").forGetter(EmitterShapeSettings::shape), + EmitterShape.CODEC.fieldOf("shape").forGetter(EmitterShapeSettings::shape), CodecUtil.VECTOR3F_CODEC.fieldOf("dimensions").forGetter(EmitterShapeSettings::dimensions), CodecUtil.VECTOR3F_CODEC.fieldOf("rotation").forGetter(EmitterShapeSettings::rotation), Codec.BOOL.fieldOf("from_surface").forGetter(EmitterShapeSettings::fromSurface) diff --git a/common/src/main/java/foundry/veil/api/quasar/data/ParticleModuleTypeRegistry.java b/common/src/main/java/foundry/veil/api/quasar/data/ParticleModuleTypeRegistry.java index 4178e7d4..6670e828 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/ParticleModuleTypeRegistry.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/ParticleModuleTypeRegistry.java @@ -1,71 +1,93 @@ package foundry.veil.api.quasar.data; -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; +import foundry.veil.Veil; import foundry.veil.api.quasar.data.module.ModuleType; +import foundry.veil.api.quasar.data.module.ParticleModuleData; +import foundry.veil.api.quasar.data.module.collision.CollisionSubEmitterData; +import foundry.veil.api.quasar.data.module.collision.DieOnCollisionModuleData; +import foundry.veil.api.quasar.data.module.force.*; +import foundry.veil.api.quasar.data.module.init.*; +import foundry.veil.api.quasar.data.module.render.ColorParticleModuleData; +import foundry.veil.api.quasar.data.module.render.TrailParticleModuleData; +import foundry.veil.api.quasar.data.module.update.TickSizeParticleModuleData; +import foundry.veil.api.quasar.data.module.update.TickSubEmitterModuleData; +import foundry.veil.api.quasar.emitters.module.init.InitRandomRotationModuleData; +import foundry.veil.api.util.CodecUtil; +import foundry.veil.platform.registry.RegistrationProvider; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import org.jetbrains.annotations.ApiStatus; public class ParticleModuleTypeRegistry { + public static final ResourceKey>> INIT_MODULES_KEY = ResourceKey.createRegistryKey(Veil.veilPath("quasar/module_type/init")); + public static final ResourceKey>> UPDATE_MODULES_KEY = ResourceKey.createRegistryKey(Veil.veilPath("quasar/module_type/update")); + public static final ResourceKey>> RENDER_MODULES_KEY = ResourceKey.createRegistryKey(Veil.veilPath("quasar/module_type/render")); - private static final BiMap> INIT_MODULES = HashBiMap.create(); - private static final BiMap> UPDATE_MODULES = HashBiMap.create(); - private static final BiMap> RENDER_MODULES = HashBiMap.create(); + private static final RegistrationProvider> INIT_MODULES_PROVIDER = RegistrationProvider.get(INIT_MODULES_KEY, Veil.MODID); + private static final RegistrationProvider> UPDATE_MODULES_PROVIDER = RegistrationProvider.get(UPDATE_MODULES_KEY, Veil.MODID); + private static final RegistrationProvider> RENDER_MODULES_PROVIDER = RegistrationProvider.get(RENDER_MODULES_KEY, Veil.MODID); - static { - ModuleType.bootstrap(); - } + public static final Registry> INIT_MODULES_REGISTRY = INIT_MODULES_PROVIDER.asVanillaRegistry(); + public static final Registry> UPDATE_MODULES_REGISTRY = UPDATE_MODULES_PROVIDER.asVanillaRegistry(); + public static final Registry> RENDER_MODULES_REGISTRY = RENDER_MODULES_PROVIDER.asVanillaRegistry(); - public static final Codec> INIT_MODULE_CODEC = Codec.STRING.comapFlatMap(name -> { - ModuleType module = INIT_MODULES.get(name); - if (module == null) { - return DataResult.error(() -> "Invalid Init Module: %s".formatted(name)); - } - return DataResult.success(module); - }, INIT_MODULES.inverse()::get); + public static final Codec> INIT_MODULE_CODEC = CodecUtil.registryOrLegacyCodec(INIT_MODULES_REGISTRY); + public static final Codec> UPDATE_MODULE_CODEC = CodecUtil.registryOrLegacyCodec(UPDATE_MODULES_REGISTRY); + public static final Codec> RENDER_MODULE_CODEC = CodecUtil.registryOrLegacyCodec(RENDER_MODULES_REGISTRY); - public static final Codec> UPDATE_MODULE_CODEC = Codec.STRING.comapFlatMap(name -> { - ModuleType module = UPDATE_MODULES.get(name); - if (module == null) { - return DataResult.error(() -> "Invalid Update Module: %s".formatted(name)); - } - return DataResult.success(module); - }, UPDATE_MODULES.inverse()::get); + // INIT + public static final ModuleType INITIAL_VELOCITY = registerInitModule("initial_velocity", InitialVelocityModuleData.CODEC); + public static final ModuleType INIT_COLOR = registerInitModule("init_color", ColorParticleModuleData.CODEC); + public static final ModuleType INIT_SUB_EMITTER = registerInitModule("init_sub_emitter", InitSubEmitterModuleData.CODEC); + public static final ModuleType INIT_SIZE = registerInitModule("init_size", InitSizeParticleModuleData.CODEC); + // ModuleType INIT_RANDOM_COLOR = registerInitModule("init_random_color", InitRandomColorParticleModule.CODEC); + public static final ModuleType INIT_RANDOM_ROTATION = registerInitModule("init_random_rotation", InitRandomRotationModuleData.CODEC); + public static final ModuleType LIGHT = registerInitModule("light", LightModuleData.CODEC); + public static final ModuleType BLOCK_PARTICLE = registerInitModule("block", BlockParticleModuleData.CODEC); - public static final Codec> RENDER_MODULE_CODEC = Codec.STRING.comapFlatMap(name -> { - ModuleType module = RENDER_MODULES.get(name); - if (module == null) { - return DataResult.error(() -> "Invalid Render Module: %s".formatted(name)); - } - return DataResult.success(module); - }, RENDER_MODULES.inverse()::get); + // RENDER + public static final ModuleType TRAIL = registerRenderModule("trail", TrailParticleModuleData.CODEC); + public static final ModuleType COLOR = registerRenderModule("color", ColorParticleModuleData.CODEC); + // ModuleType COLOR_OVER_LIFETIME = registerRenderModule("color_over_lifetime", ColorOverTimeParticleModule.CODEC); + // ModuleType COLOR_OVER_VELOCITY = registerRenderModule("color_over_velocity", ColorOverVelocityParticleModule.CODEC); - public static void registerInit(String name, ModuleType type) { - INIT_MODULES.put(name, type); - } + // UPDATE + public static final ModuleType TICK_SIZE = registerUpdateModule("tick_size", TickSizeParticleModuleData.CODEC); + public static final ModuleType TICK_SUB_EMITTER = registerUpdateModule("tick_sub_emitter", TickSubEmitterModuleData.CODEC); + // UPDATE - COLLISION + public static final ModuleType DIE_ON_COLLISION = registerUpdateModule("die_on_collision", DieOnCollisionModuleData.CODEC); + public static final ModuleType SUB_EMITTER_COLLISION = registerUpdateModule("sub_emitter_collision", CollisionSubEmitterData.CODEC); + // ModuleType BOUNCE = registerUpdateModule("bounce", BounceParticleModule.CODEC); + // UPDATE - FORCES + public static final ModuleType GRAVITY = registerUpdateModule("gravity", GravityForceData.CODEC); + public static final ModuleType VORTEX = registerUpdateModule("vortex", VortexForceData.CODEC); + public static final ModuleType POINT_ATTRACTOR = registerUpdateModule("point_attractor", PointAttractorForceData.CODEC); + public static final ModuleType VECTOR_FIELD = registerUpdateModule("vector_field", VectorFieldForceData.CODEC); + public static final ModuleType DRAG = registerUpdateModule("drag", DragForceData.CODEC); + public static final ModuleType WIND = registerUpdateModule("wind", WindForceData.CODEC); + public static final ModuleType POINT = registerUpdateModule("point_force", PointForceData.CODEC); - public static void registerUpdate(String name, ModuleType type) { - UPDATE_MODULES.put(name, type); + @ApiStatus.Internal + public static void bootstrap() { } - public static void registerRender(String name, ModuleType type) { - RENDER_MODULES.put(name, type); + private static ModuleType registerUpdateModule(String name, Codec codec) { + ModuleType type = () -> codec; + UPDATE_MODULES_PROVIDER.register(name, () -> type); + return type; } - public static String getName(ModuleType type) { - String initModuleName = INIT_MODULES.inverse().get(type); - if (initModuleName != null) { - return initModuleName; - } - String updateModuleName = UPDATE_MODULES.inverse().get(type); - if (updateModuleName != null) { - return updateModuleName; - } - String renderModuleName = RENDER_MODULES.inverse().get(type); - if (renderModuleName != null) { - return renderModuleName; - } + private static ModuleType registerRenderModule(String name, Codec codec) { + ModuleType type = () -> codec; + RENDER_MODULES_PROVIDER.register(name, () -> type); + return type; + } - return type.getClass().getName(); + private static ModuleType registerInitModule(String name, Codec codec) { + ModuleType type = () -> codec; + INIT_MODULES_PROVIDER.register(name, () -> type); + return type; } } \ No newline at end of file diff --git a/common/src/main/java/foundry/veil/api/quasar/data/QuasarParticleData.java b/common/src/main/java/foundry/veil/api/quasar/data/QuasarParticleData.java index af645eda..d5a6d1dd 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/QuasarParticleData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/QuasarParticleData.java @@ -5,7 +5,9 @@ import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.particle.QuasarParticle; import foundry.veil.api.quasar.particle.RenderData; +import foundry.veil.api.quasar.particle.RenderStyle; import foundry.veil.api.quasar.particle.SpriteData; +import foundry.veil.api.quasar.registry.RenderStyleRegistry; import net.minecraft.core.Holder; import net.minecraft.resources.RegistryFileCodec; import net.minecraft.resources.ResourceLocation; @@ -47,7 +49,7 @@ public record QuasarParticleData(boolean shouldCollide, List> renderModules, @Nullable SpriteData spriteData, boolean additive, - RenderData.RenderStyle renderStyle) { + RenderStyle renderStyle) { public static final Codec DIRECT_CODEC = RecordCodecBuilder.create(instance -> instance.group( Codec.BOOL.optionalFieldOf("should_collide", true).forGetter(QuasarParticleData::shouldCollide), @@ -60,7 +62,7 @@ public record QuasarParticleData(boolean shouldCollide, ParticleModuleData.RENDER_CODEC.listOf().optionalFieldOf("render_modules", Collections.emptyList()).forGetter(QuasarParticleData::renderModules), SpriteData.CODEC.optionalFieldOf("sprite_data").forGetter(data -> Optional.ofNullable(data.spriteData())), Codec.BOOL.optionalFieldOf("additive", false).forGetter(QuasarParticleData::additive), - RenderData.RenderStyle.CODEC.optionalFieldOf("render_style", RenderData.RenderStyle.BILLBOARD).forGetter(QuasarParticleData::renderStyle) + RenderStyle.CODEC.optionalFieldOf("render_style", RenderStyleRegistry.BILLBOARD.get()).forGetter(QuasarParticleData::renderStyle) ).apply(instance, (shouldCollide, faceVelocity, velocityStretchFactor, initModules, updateModules, collisionModules, forceModules, renderModules, spriteData, additive, renderStyle) -> new QuasarParticleData(shouldCollide, faceVelocity, velocityStretchFactor, initModules, updateModules, collisionModules, forceModules, renderModules, spriteData.orElse(null), additive, renderStyle))); public static final Codec> CODEC = RegistryFileCodec.create(QuasarParticles.PARTICLE_DATA, DIRECT_CODEC); @@ -74,7 +76,7 @@ public QuasarParticleData(boolean shouldCollide, List> renderModules, @Nullable SpriteData spriteData, boolean additive, - RenderData.RenderStyle renderStyle) { + RenderStyle renderStyle) { this.shouldCollide = shouldCollide; this.faceVelocity = faceVelocity; this.velocityStretchFactor = velocityStretchFactor; diff --git a/common/src/main/java/foundry/veil/api/quasar/data/module/ModuleType.java b/common/src/main/java/foundry/veil/api/quasar/data/module/ModuleType.java index 944bdfad..4aea8d15 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/module/ModuleType.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/module/ModuleType.java @@ -1,85 +1,11 @@ package foundry.veil.api.quasar.data.module; import com.mojang.serialization.Codec; -import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; -import foundry.veil.api.quasar.data.module.collision.CollisionSubEmitterData; -import foundry.veil.api.quasar.data.module.collision.DieOnCollisionModuleData; -import foundry.veil.api.quasar.data.module.force.*; -import foundry.veil.api.quasar.data.module.init.*; -import foundry.veil.api.quasar.data.module.render.ColorParticleModuleData; -import foundry.veil.api.quasar.data.module.render.TrailParticleModuleData; -import foundry.veil.api.quasar.data.module.update.TickSizeParticleModuleData; -import foundry.veil.api.quasar.data.module.update.TickSubEmitterModuleData; -import foundry.veil.api.quasar.emitters.module.init.InitRandomRotationModuleData; -import org.jetbrains.annotations.ApiStatus; @FunctionalInterface public interface ModuleType { - - // INIT - ModuleType INITIAL_VELOCITY = registerInitModule("initial_velocity", InitialVelocityModuleData.CODEC); - ModuleType INIT_COLOR = registerInitModule("init_color", ColorParticleModuleData.CODEC); - ModuleType INIT_SUB_EMITTER = registerInitModule("init_sub_emitter", InitSubEmitterModuleData.CODEC); - ModuleType INIT_SIZE = registerInitModule("init_size", InitSizeParticleModuleData.CODEC); - // ModuleType INIT_RANDOM_COLOR = registerInitModule("init_random_color", InitRandomColorParticleModule.CODEC); - ModuleType INIT_RANDOM_ROTATION = registerInitModule("init_random_rotation", InitRandomRotationModuleData.CODEC); - ModuleType LIGHT = registerInitModule("light", LightModuleData.CODEC); - ModuleType BLOCK_PARTICLE = registerInitModule("block", BlockParticleModuleData.CODEC); - - - // RENDER - ModuleType TRAIL = registerRenderModule("trail", TrailParticleModuleData.CODEC); - ModuleType COLOR = registerRenderModule("color", ColorParticleModuleData.CODEC); -// ModuleType COLOR_OVER_LIFETIME = registerRenderModule("color_over_lifetime", ColorOverTimeParticleModule.CODEC); -// ModuleType COLOR_OVER_VELOCITY = registerRenderModule("color_over_velocity", ColorOverVelocityParticleModule.CODEC); - - // UPDATE - - ModuleType TICK_SIZE = registerUpdateModule("tick_size", TickSizeParticleModuleData.CODEC); - ModuleType TICK_SUB_EMITTER = registerUpdateModule("tick_sub_emitter", TickSubEmitterModuleData.CODEC); - - // UPDATE - COLLISION - ModuleType DIE_ON_COLLISION = registerUpdateModule("die_on_collision", DieOnCollisionModuleData.CODEC); - ModuleType SUB_EMITTER_COLLISION = registerUpdateModule("sub_emitter_collision", CollisionSubEmitterData.CODEC); -// ModuleType BOUNCE = registerUpdateModule("bounce", BounceParticleModule.CODEC); - - - // UPDATE - FORCES - ModuleType GRAVITY = registerUpdateModule("gravity", GravityForceData.CODEC); - ModuleType VORTEX = registerUpdateModule("vortex", VortexForceData.CODEC); - ModuleType POINT_ATTRACTOR = registerUpdateModule("point_attractor", PointAttractorForceData.CODEC); - ModuleType VECTOR_FIELD = registerUpdateModule("vector_field", VectorFieldForceData.CODEC); - ModuleType DRAG = registerUpdateModule("drag", DragForceData.CODEC); - ModuleType WIND = registerUpdateModule("wind", WindForceData.CODEC); - ModuleType POINT = registerUpdateModule("point_force", PointForceData.CODEC); - /** * @return The codec for this module type data */ Codec codec(); - - @ApiStatus.Internal - static void bootstrap() { - } - - @ApiStatus.Internal - static ModuleType registerUpdateModule(String name, Codec codec) { - ModuleType type = () -> codec; - ParticleModuleTypeRegistry.registerUpdate(name, type); - return type; - } - - @ApiStatus.Internal - static ModuleType registerRenderModule(String name, Codec codec) { - ModuleType type = () -> codec; - ParticleModuleTypeRegistry.registerRender(name, type); - return type; - } - - @ApiStatus.Internal - static ModuleType registerInitModule(String name, Codec codec) { - ModuleType type = () -> codec; - ParticleModuleTypeRegistry.registerInit(name, type); - return type; - } } diff --git a/common/src/main/java/foundry/veil/api/quasar/data/module/collision/CollisionSubEmitterData.java b/common/src/main/java/foundry/veil/api/quasar/data/module/collision/CollisionSubEmitterData.java index 7e96a569..f0714455 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/module/collision/CollisionSubEmitterData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/module/collision/CollisionSubEmitterData.java @@ -2,6 +2,7 @@ import com.mojang.serialization.Codec; import foundry.veil.api.client.render.VeilRenderSystem; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.emitters.module.CollisionParticleModule; @@ -30,6 +31,6 @@ public void addModules(ParticleModuleSet.Builder builder) { @Override public ModuleType getType() { - return ModuleType.SUB_EMITTER_COLLISION; + return ParticleModuleTypeRegistry.SUB_EMITTER_COLLISION; } } diff --git a/common/src/main/java/foundry/veil/api/quasar/data/module/collision/DieOnCollisionModuleData.java b/common/src/main/java/foundry/veil/api/quasar/data/module/collision/DieOnCollisionModuleData.java index cc5b1780..09213832 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/module/collision/DieOnCollisionModuleData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/module/collision/DieOnCollisionModuleData.java @@ -1,6 +1,7 @@ package foundry.veil.api.quasar.data.module.collision; import com.mojang.serialization.Codec; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.emitters.module.CollisionParticleModule; @@ -18,6 +19,6 @@ public void addModules(ParticleModuleSet.Builder builder) { @Override public ModuleType getType() { - return ModuleType.DIE_ON_COLLISION; + return ParticleModuleTypeRegistry.DIE_ON_COLLISION; } } diff --git a/common/src/main/java/foundry/veil/api/quasar/data/module/force/DragForceData.java b/common/src/main/java/foundry/veil/api/quasar/data/module/force/DragForceData.java index 4c728669..5f2702ec 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/module/force/DragForceData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/module/force/DragForceData.java @@ -1,6 +1,7 @@ package foundry.veil.api.quasar.data.module.force; import com.mojang.serialization.Codec; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.emitters.module.force.ScaleForceModule; @@ -25,6 +26,6 @@ public void addModules(ParticleModuleSet.Builder builder) { @Override public ModuleType getType() { - return ModuleType.DRAG; + return ParticleModuleTypeRegistry.DRAG; } } diff --git a/common/src/main/java/foundry/veil/api/quasar/data/module/force/GravityForceData.java b/common/src/main/java/foundry/veil/api/quasar/data/module/force/GravityForceData.java index 42785cf2..cbe9e663 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/module/force/GravityForceData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/module/force/GravityForceData.java @@ -1,6 +1,7 @@ package foundry.veil.api.quasar.data.module.force; import com.mojang.serialization.Codec; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.emitters.module.force.ConstantForceModule; @@ -21,6 +22,6 @@ public void addModules(ParticleModuleSet.Builder builder) { @Override public ModuleType getType() { - return ModuleType.GRAVITY; + return ParticleModuleTypeRegistry.GRAVITY; } } diff --git a/common/src/main/java/foundry/veil/api/quasar/data/module/force/PointAttractorForceData.java b/common/src/main/java/foundry/veil/api/quasar/data/module/force/PointAttractorForceData.java index 41b67488..08756f7a 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/module/force/PointAttractorForceData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/module/force/PointAttractorForceData.java @@ -2,6 +2,7 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.emitters.module.force.PointAttractorForceModule; @@ -52,6 +53,6 @@ public void addModules(ParticleModuleSet.Builder builder) { @Override public ModuleType getType() { - return ModuleType.POINT_ATTRACTOR; + return ParticleModuleTypeRegistry.POINT_ATTRACTOR; } } diff --git a/common/src/main/java/foundry/veil/api/quasar/data/module/force/PointForceData.java b/common/src/main/java/foundry/veil/api/quasar/data/module/force/PointForceData.java index dd675071..c3328d65 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/module/force/PointForceData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/module/force/PointForceData.java @@ -2,6 +2,7 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.emitters.module.force.PointForceModule; @@ -32,6 +33,6 @@ public void addModules(ParticleModuleSet.Builder builder) { @Override public ModuleType getType() { - return ModuleType.POINT; + return ParticleModuleTypeRegistry.POINT; } } diff --git a/common/src/main/java/foundry/veil/api/quasar/data/module/force/VectorFieldForceData.java b/common/src/main/java/foundry/veil/api/quasar/data/module/force/VectorFieldForceData.java index f5e2fe5e..15372200 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/module/force/VectorFieldForceData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/module/force/VectorFieldForceData.java @@ -2,6 +2,7 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.emitters.module.force.VectorFieldForceModule; @@ -29,6 +30,6 @@ public void addModules(ParticleModuleSet.Builder builder) { @Override public ModuleType getType() { - return ModuleType.VECTOR_FIELD; + return ParticleModuleTypeRegistry.VECTOR_FIELD; } } diff --git a/common/src/main/java/foundry/veil/api/quasar/data/module/force/VortexForceData.java b/common/src/main/java/foundry/veil/api/quasar/data/module/force/VortexForceData.java index 94d2bfaa..ea3011b3 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/module/force/VortexForceData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/module/force/VortexForceData.java @@ -2,6 +2,7 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.emitters.module.force.VortexForceModule; @@ -39,6 +40,6 @@ public void addModules(ParticleModuleSet.Builder builder) { @Override public ModuleType getType() { - return ModuleType.VORTEX; + return ParticleModuleTypeRegistry.VORTEX; } } diff --git a/common/src/main/java/foundry/veil/api/quasar/data/module/force/WindForceData.java b/common/src/main/java/foundry/veil/api/quasar/data/module/force/WindForceData.java index 58b79466..271c00ae 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/module/force/WindForceData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/module/force/WindForceData.java @@ -2,6 +2,7 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.emitters.module.force.ConstantForceModule; @@ -39,6 +40,6 @@ public void addModules(ParticleModuleSet.Builder builder) { @Override public ModuleType getType() { - return ModuleType.WIND; + return ParticleModuleTypeRegistry.WIND; } } diff --git a/common/src/main/java/foundry/veil/api/quasar/data/module/init/BlockParticleModuleData.java b/common/src/main/java/foundry/veil/api/quasar/data/module/init/BlockParticleModuleData.java index 5a8dfb5e..ee11a7f8 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/module/init/BlockParticleModuleData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/module/init/BlockParticleModuleData.java @@ -1,6 +1,7 @@ package foundry.veil.api.quasar.data.module.init; import com.mojang.serialization.Codec; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.emitters.module.InitParticleModule; @@ -33,6 +34,6 @@ public void addModules(ParticleModuleSet.Builder builder) { @Override public ModuleType getType() { - return ModuleType.BLOCK_PARTICLE; + return ParticleModuleTypeRegistry.BLOCK_PARTICLE; } } diff --git a/common/src/main/java/foundry/veil/api/quasar/data/module/init/InitSizeParticleModuleData.java b/common/src/main/java/foundry/veil/api/quasar/data/module/init/InitSizeParticleModuleData.java index f4ab1bd6..f91ec66b 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/module/init/InitSizeParticleModuleData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/module/init/InitSizeParticleModuleData.java @@ -2,6 +2,7 @@ import com.mojang.serialization.Codec; import foundry.veil.api.molang.MolangExpressionCodec; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.emitters.module.InitParticleModule; @@ -27,6 +28,6 @@ public void addModules(ParticleModuleSet.Builder builder) { @Override public ModuleType getType() { - return ModuleType.INIT_SIZE; + return ParticleModuleTypeRegistry.INIT_SIZE; } } diff --git a/common/src/main/java/foundry/veil/api/quasar/data/module/init/InitSubEmitterModuleData.java b/common/src/main/java/foundry/veil/api/quasar/data/module/init/InitSubEmitterModuleData.java index 10c65ed9..e2a051df 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/module/init/InitSubEmitterModuleData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/module/init/InitSubEmitterModuleData.java @@ -2,6 +2,7 @@ import com.mojang.serialization.Codec; import foundry.veil.api.client.render.VeilRenderSystem; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.emitters.module.InitParticleModule; @@ -30,6 +31,6 @@ public void addModules(ParticleModuleSet.Builder builder) { @Override public ModuleType getType() { - return ModuleType.INIT_SUB_EMITTER; + return ParticleModuleTypeRegistry.INIT_SUB_EMITTER; } } diff --git a/common/src/main/java/foundry/veil/api/quasar/data/module/init/InitialVelocityModuleData.java b/common/src/main/java/foundry/veil/api/quasar/data/module/init/InitialVelocityModuleData.java index 7563eaba..3ef1941f 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/module/init/InitialVelocityModuleData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/module/init/InitialVelocityModuleData.java @@ -2,6 +2,7 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.emitters.module.InitParticleModule; @@ -29,6 +30,6 @@ public void addModules(ParticleModuleSet.Builder builder) { @Override public ModuleType getType() { - return ModuleType.INITIAL_VELOCITY; + return ParticleModuleTypeRegistry.INITIAL_VELOCITY; } } diff --git a/common/src/main/java/foundry/veil/api/quasar/data/module/init/LightModuleData.java b/common/src/main/java/foundry/veil/api/quasar/data/module/init/LightModuleData.java index 33ef2411..7040aa27 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/module/init/LightModuleData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/module/init/LightModuleData.java @@ -3,6 +3,7 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import foundry.veil.api.molang.MolangExpressionCodec; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.emitters.module.render.DynamicLightModule; @@ -35,6 +36,6 @@ public void addModules(ParticleModuleSet.Builder builder) { @Override public ModuleType getType() { - return ModuleType.LIGHT; + return ParticleModuleTypeRegistry.LIGHT; } } diff --git a/common/src/main/java/foundry/veil/api/quasar/data/module/render/ColorParticleModuleData.java b/common/src/main/java/foundry/veil/api/quasar/data/module/render/ColorParticleModuleData.java index 8e7e1564..7ac4816c 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/module/render/ColorParticleModuleData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/module/render/ColorParticleModuleData.java @@ -3,6 +3,7 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import foundry.veil.api.molang.MolangExpressionCodec; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.emitters.module.InitParticleModule; @@ -30,6 +31,6 @@ public void addModules(ParticleModuleSet.Builder builder) { @Override public ModuleType getType() { - return ModuleType.INIT_COLOR; + return ParticleModuleTypeRegistry.INIT_COLOR; } } diff --git a/common/src/main/java/foundry/veil/api/quasar/data/module/render/TrailParticleModuleData.java b/common/src/main/java/foundry/veil/api/quasar/data/module/render/TrailParticleModuleData.java index a0d1578c..567d9a22 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/module/render/TrailParticleModuleData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/module/render/TrailParticleModuleData.java @@ -1,6 +1,7 @@ package foundry.veil.api.quasar.data.module.render; import com.mojang.serialization.Codec; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.emitters.module.RenderParticleModule; @@ -33,6 +34,6 @@ public void addModules(ParticleModuleSet.Builder builder) { @Override public ModuleType getType() { - return ModuleType.TRAIL; + return ParticleModuleTypeRegistry.TRAIL; } } diff --git a/common/src/main/java/foundry/veil/api/quasar/data/module/update/TickSizeParticleModuleData.java b/common/src/main/java/foundry/veil/api/quasar/data/module/update/TickSizeParticleModuleData.java index d33e6044..8d91f846 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/module/update/TickSizeParticleModuleData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/module/update/TickSizeParticleModuleData.java @@ -2,6 +2,7 @@ import com.mojang.serialization.Codec; import foundry.veil.api.molang.MolangExpressionCodec; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.emitters.module.UpdateParticleModule; @@ -27,6 +28,6 @@ public void addModules(ParticleModuleSet.Builder builder) { @Override public ModuleType getType() { - return ModuleType.TICK_SIZE; + return ParticleModuleTypeRegistry.TICK_SIZE; } } diff --git a/common/src/main/java/foundry/veil/api/quasar/data/module/update/TickSubEmitterModuleData.java b/common/src/main/java/foundry/veil/api/quasar/data/module/update/TickSubEmitterModuleData.java index e588b576..e86b7ee9 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/module/update/TickSubEmitterModuleData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/module/update/TickSubEmitterModuleData.java @@ -2,6 +2,7 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.emitters.module.update.TickSubEmitterModule; @@ -22,6 +23,6 @@ public void addModules(ParticleModuleSet.Builder builder) { @Override public ModuleType getType() { - return ModuleType.TICK_SUB_EMITTER; + return ParticleModuleTypeRegistry.TICK_SUB_EMITTER; } } diff --git a/common/src/main/java/foundry/veil/api/quasar/emitters/module/init/InitRandomRotationModuleData.java b/common/src/main/java/foundry/veil/api/quasar/emitters/module/init/InitRandomRotationModuleData.java index 0109a719..2719f8ed 100644 --- a/common/src/main/java/foundry/veil/api/quasar/emitters/module/init/InitRandomRotationModuleData.java +++ b/common/src/main/java/foundry/veil/api/quasar/emitters/module/init/InitRandomRotationModuleData.java @@ -2,6 +2,7 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import foundry.veil.api.quasar.data.ParticleModuleTypeRegistry; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.emitters.module.InitParticleModule; @@ -27,6 +28,6 @@ public void addModules(ParticleModuleSet.Builder builder) { @Override public ModuleType getType() { - return ModuleType.INIT_RANDOM_ROTATION; + return ParticleModuleTypeRegistry.INIT_RANDOM_ROTATION; } } diff --git a/common/src/main/java/foundry/veil/api/quasar/emitters/module/update/FaceVelocityModule.java b/common/src/main/java/foundry/veil/api/quasar/emitters/module/update/FaceVelocityModule.java index d3c605b1..da7fa95c 100644 --- a/common/src/main/java/foundry/veil/api/quasar/emitters/module/update/FaceVelocityModule.java +++ b/common/src/main/java/foundry/veil/api/quasar/emitters/module/update/FaceVelocityModule.java @@ -3,6 +3,7 @@ import foundry.veil.api.quasar.emitters.module.UpdateParticleModule; import foundry.veil.api.quasar.particle.QuasarParticle; import foundry.veil.api.quasar.particle.RenderData; +import foundry.veil.api.quasar.registry.RenderStyleRegistry; import net.minecraft.util.Mth; import org.joml.Vector3d; import org.joml.Vector3f; @@ -21,7 +22,7 @@ public void update(QuasarParticle particle) { Vector3f rotation = particle.getRotation(); rotation.x = (float) Mth.atan2(normalizedMotion.y, Math.sqrt(normalizedMotion.x * normalizedMotion.x + normalizedMotion.z * normalizedMotion.z)); rotation.y = (float) Mth.atan2(normalizedMotion.x, normalizedMotion.z); - if (particle.getData().renderStyle() == RenderData.RenderStyle.BILLBOARD) { + if (particle.getData().renderStyle() == RenderStyleRegistry.BILLBOARD.get()) { rotation.y += (float) (Math.PI / 2.0); } } diff --git a/common/src/main/java/foundry/veil/api/quasar/emitters/shape/EmitterShape.java b/common/src/main/java/foundry/veil/api/quasar/emitters/shape/EmitterShape.java index 29387a72..78c65491 100644 --- a/common/src/main/java/foundry/veil/api/quasar/emitters/shape/EmitterShape.java +++ b/common/src/main/java/foundry/veil/api/quasar/emitters/shape/EmitterShape.java @@ -2,14 +2,23 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.datafixers.util.Either; import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; +import foundry.veil.Veil; +import foundry.veil.api.quasar.registry.EmitterShapeRegistry; +import foundry.veil.api.util.CodecUtil; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; import net.minecraft.util.RandomSource; import org.joml.Vector3d; import org.joml.Vector3dc; import org.joml.Vector3fc; import java.util.Locale; +import java.util.Optional; +import java.util.function.Function; public interface EmitterShape { @@ -17,38 +26,5 @@ public interface EmitterShape { void renderShape(PoseStack stack, VertexConsumer consumer, Vector3fc dimensions, Vector3fc rotation); - enum Shape implements EmitterShape { - POINT(new Point()), - HEMISPHERE(new Hemisphere()), - CYLINDER(new Cylinder()), - SPHERE(new Sphere()), - CUBE(new Cube()), - TORUS(new Torus()), - DISC(new Disc()), - PLANE(new Plane()); - - public static final Codec CODEC = Codec.STRING.flatXmap(name -> { - for (Shape value : Shape.values()) { - if (value.name().equalsIgnoreCase(name)) { - return DataResult.success(value); - } - } - return DataResult.error(() -> "Unknown shape: " + name, POINT); - }, shape -> DataResult.success(shape.name().toLowerCase(Locale.ROOT))); - private final EmitterShape shape; - - Shape(EmitterShape shape) { - this.shape = shape; - } - - @Override - public Vector3d getPoint(RandomSource randomSource, Vector3fc dimensions, Vector3fc rotation, Vector3dc position, boolean fromSurface) { - return this.shape.getPoint(randomSource, dimensions, rotation, position, fromSurface); - } - - @Override - public void renderShape(PoseStack stack, VertexConsumer consumer, Vector3fc dimensions, Vector3fc rotation) { - this.shape.renderShape(stack, consumer, dimensions, rotation); - } - } + Codec CODEC = CodecUtil.registryOrLegacyCodec(EmitterShapeRegistry.REGISTRY); } diff --git a/common/src/main/java/foundry/veil/api/quasar/particle/ParticleEmitter.java b/common/src/main/java/foundry/veil/api/quasar/particle/ParticleEmitter.java index 3fc0167c..6a385495 100644 --- a/common/src/main/java/foundry/veil/api/quasar/particle/ParticleEmitter.java +++ b/common/src/main/java/foundry/veil/api/quasar/particle/ParticleEmitter.java @@ -214,7 +214,7 @@ void tick() { @ApiStatus.Internal public void render(PoseStack poseStack, MultiBufferSource bufferSource, Camera camera, float partialTicks) { Vec3 projectedView = camera.getPosition(); - RenderData.RenderStyle renderStyle = this.particleData.renderStyle(); + RenderStyle renderStyle = this.particleData.renderStyle(); Vector3f renderOffset = new Vector3f(); RenderType lastRenderType = null; diff --git a/common/src/main/java/foundry/veil/api/quasar/particle/RenderData.java b/common/src/main/java/foundry/veil/api/quasar/particle/RenderData.java index bc998785..80ce190b 100644 --- a/common/src/main/java/foundry/veil/api/quasar/particle/RenderData.java +++ b/common/src/main/java/foundry/veil/api/quasar/particle/RenderData.java @@ -1,14 +1,10 @@ package foundry.veil.api.quasar.particle; import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; import foundry.veil.Veil; import foundry.veil.api.client.render.rendertype.VeilRenderType; import foundry.veil.api.quasar.data.QuasarParticleData; import foundry.veil.api.quasar.fx.Trail; -import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; @@ -29,29 +25,6 @@ public class RenderData { @Deprecated private static final ResourceLocation BLANK = Veil.veilPath("textures/special/blank.png"); - private static final Vector3fc[] PLANE_POSITIONS = { - // plane from -1 to 1 on Y axis and -1 to 1 on X axis - new Vector3f(1, -1, 0), new Vector3f(-1, -1, 0), new Vector3f(-1, 1, 0), new Vector3f(1, 1, 0) - }; - private static final Vector3fc[] CUBE_POSITIONS = { - // TOP - new Vector3f(1, 1, -1), new Vector3f(1, 1, 1), new Vector3f(-1, 1, 1), new Vector3f(-1, 1, -1), - - // BOTTOM - new Vector3f(-1, -1, -1), new Vector3f(-1, -1, 1), new Vector3f(1, -1, 1), new Vector3f(1, -1, -1), - - // FRONT - new Vector3f(-1, -1, 1), new Vector3f(-1, 1, 1), new Vector3f(1, 1, 1), new Vector3f(1, -1, 1), - - // BACK - new Vector3f(1, -1, -1), new Vector3f(1, 1, -1), new Vector3f(-1, 1, -1), new Vector3f(-1, -1, -1), - - // LEFT - new Vector3f(-1, -1, -1), new Vector3f(-1, 1, -1), new Vector3f(-1, 1, 1), new Vector3f(-1, -1, 1), - - // RIGHT - new Vector3f(1, -1, 1), new Vector3f(1, 1, 1), new Vector3f(1, 1, -1), new Vector3f(1, -1, -1)}; - private final Vector3d prevPosition; private final Vector3d renderPosition; private final Vector3f prevRotation; @@ -228,117 +201,4 @@ public void setAtlasSprite(@Nullable TextureAtlasSprite atlasSprite) { this.atlasSprite = atlasSprite; this.updateRenderType(); } - - public enum RenderStyle { - CUBE { - @Override - public void render(PoseStack poseStack, QuasarParticle particle, RenderData renderData, Vector3fc renderOffset, VertexConsumer builder, double ageModifier, float partialTicks) { - Matrix4f matrix4f = poseStack.last().pose(); - Vector3fc rotation = renderData.getRenderRotation(); - Vector3f vec = new Vector3f(); - SpriteData spriteData = renderData.getSpriteData(); - - for (int i = 0; i < 6; i++) { - for (int j = 0; j < 4; j++) { - vec.set(CUBE_POSITIONS[i * 4 + j]); - QuasarParticleData data = particle.getData(); - if (vec.z < 0 && data.velocityStretchFactor() != 0.0f) { - vec.z *= 1 + data.velocityStretchFactor(); - } - vec.rotateX(rotation.x()) - .rotateY(rotation.y()) - .rotateZ(rotation.z()) - .mul((float) (renderData.getRenderRadius() * ageModifier)) - .add(renderOffset); - - float u = (int) (j / 2.0F); - float v = j % 2; - - if (spriteData != null) { - u = spriteData.u(renderData.getRenderAge(), renderData.getAgePercent(), u); - v = spriteData.v(renderData.getRenderAge(), renderData.getAgePercent(), v); - } - - builder.vertex(matrix4f, vec.x, vec.y, vec.z); - builder.uv(u, v); - builder.color(renderData.getRed(), renderData.getGreen(), renderData.getBlue(), renderData.getAlpha()); - builder.uv2(renderData.getLightColor()); - builder.endVertex(); - } - } - } - }, - // TODO: FIX UVS THEY'RE FUCKED - BILLBOARD { - @Override - public void render(PoseStack poseStack, QuasarParticle particle, RenderData renderData, Vector3fc renderOffset, VertexConsumer builder, double ageModifier, float partialTicks) { - Matrix4f matrix4f = poseStack.last().pose(); - Vector3fc rotation = renderData.getRenderRotation(); - - Quaternionf faceCameraRotation = Minecraft.getInstance().getEntityRenderDispatcher().cameraOrientation(); - SpriteData spriteData = renderData.getSpriteData(); - - int red = (int) (renderData.getRed() * 255.0F) & 0xFF; - int green = (int) (renderData.getGreen() * 255.0F) & 0xFF; - int blue = (int) (renderData.getBlue() * 255.0F) & 0xFF; - int alpha = (int) (renderData.getAlpha() * 255.0F) & 0xFF; - - // turn quat into pitch and yaw - Vector3f vec = new Vector3f(); - for (int j = 0; j < 4; j++) { - vec.set(PLANE_POSITIONS[j]); - if (particle.getData().velocityStretchFactor() > 0f) { - vec.set(vec.x * (1 + particle.getData().velocityStretchFactor()), vec.y, vec.z); - } - if (particle.getData().faceVelocity()) { - vec.rotateX(rotation.x()) - .rotateY(rotation.y()) - .rotateZ(rotation.z()); - } -// vec = vec.xRot(lerpedPitch).yRot(lerpedYaw).zRot(lerpedRoll); - faceCameraRotation.transform(vec).mul((float) (renderData.getRenderRadius() * ageModifier)).add(renderOffset); - - float u, v; - if (j == 0) { - u = 0; - v = 0; - } else if (j == 1) { - u = 1; - v = 0; - } else if (j == 2) { - u = 1; - v = 1; - } else { - u = 0; - v = 1; - } - if (spriteData != null) { - u = spriteData.u(renderData.getRenderAge(), renderData.getAgePercent(), u); - v = spriteData.v(renderData.getRenderAge(), renderData.getAgePercent(), v); - } -// if (particle.sprite != null) { -// u1 = u; -// v1 = v; -// } - builder.vertex(matrix4f, vec.x, vec.y, vec.z); - builder.uv(u, v); - builder.color(red, green, blue, alpha); - builder.uv2(renderData.getLightColor()); - builder.endVertex(); - } - } - }; - - private static final Map VALUES = Arrays.stream(values()).collect(Collectors.toMap(v -> v.name().toLowerCase(Locale.ROOT), v -> v)); - public static final Codec CODEC = Codec.STRING.flatXmap(name -> { - String key = name.toLowerCase(Locale.ROOT); - RenderStyle renderStyle = VALUES.get(key); - if (renderStyle == null) { - return DataResult.error(() -> "Invalid Render Style: " + key); - } - return DataResult.success(renderStyle); - }, style -> DataResult.success(style.name().toLowerCase(Locale.ROOT))); - - public abstract void render(PoseStack poseStack, QuasarParticle particle, RenderData renderData, Vector3fc renderOffset, VertexConsumer builder, double ageModifier, float partialTicks); - } } diff --git a/common/src/main/java/foundry/veil/api/quasar/particle/RenderStyle.java b/common/src/main/java/foundry/veil/api/quasar/particle/RenderStyle.java new file mode 100644 index 00000000..08781f01 --- /dev/null +++ b/common/src/main/java/foundry/veil/api/quasar/particle/RenderStyle.java @@ -0,0 +1,146 @@ +package foundry.veil.api.quasar.particle; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import foundry.veil.api.quasar.data.QuasarParticleData; +import foundry.veil.api.quasar.registry.RenderStyleRegistry; +import foundry.veil.api.util.CodecUtil; +import net.minecraft.client.Minecraft; +import org.joml.Matrix4f; +import org.joml.Quaternionf; +import org.joml.Vector3f; +import org.joml.Vector3fc; + +import java.util.Locale; + +public interface RenderStyle { + Codec CODEC = CodecUtil.registryOrLegacyCodec(RenderStyleRegistry.REGISTRY); + + void render(PoseStack poseStack, QuasarParticle particle, RenderData renderData, Vector3fc renderOffset, VertexConsumer builder, double ageModifier, float partialTicks); + + final class Cube implements RenderStyle { + private static final Vector3fc[] CUBE_POSITIONS = { + // TOP + new Vector3f(1, 1, -1), new Vector3f(1, 1, 1), new Vector3f(-1, 1, 1), new Vector3f(-1, 1, -1), + + // BOTTOM + new Vector3f(-1, -1, -1), new Vector3f(-1, -1, 1), new Vector3f(1, -1, 1), new Vector3f(1, -1, -1), + + // FRONT + new Vector3f(-1, -1, 1), new Vector3f(-1, 1, 1), new Vector3f(1, 1, 1), new Vector3f(1, -1, 1), + + // BACK + new Vector3f(1, -1, -1), new Vector3f(1, 1, -1), new Vector3f(-1, 1, -1), new Vector3f(-1, -1, -1), + + // LEFT + new Vector3f(-1, -1, -1), new Vector3f(-1, 1, -1), new Vector3f(-1, 1, 1), new Vector3f(-1, -1, 1), + + // RIGHT + new Vector3f(1, -1, 1), new Vector3f(1, 1, 1), new Vector3f(1, 1, -1), new Vector3f(1, -1, -1)}; + + @Override + public void render(PoseStack poseStack, QuasarParticle particle, RenderData renderData, Vector3fc renderOffset, VertexConsumer builder, double ageModifier, float partialTicks) { + Matrix4f matrix4f = poseStack.last().pose(); + Vector3fc rotation = renderData.getRenderRotation(); + Vector3f vec = new Vector3f(); + SpriteData spriteData = renderData.getSpriteData(); + + for (int i = 0; i < 6; i++) { + for (int j = 0; j < 4; j++) { + vec.set(CUBE_POSITIONS[i * 4 + j]); + QuasarParticleData data = particle.getData(); + if (vec.z < 0 && data.velocityStretchFactor() != 0.0f) { + vec.z *= 1 + data.velocityStretchFactor(); + } + vec.rotateX(rotation.x()) + .rotateY(rotation.y()) + .rotateZ(rotation.z()) + .mul((float) (renderData.getRenderRadius() * ageModifier)) + .add(renderOffset); + + float u = (int) (j / 2.0F); + float v = j % 2; + + if (spriteData != null) { + u = spriteData.u(renderData.getRenderAge(), renderData.getAgePercent(), u); + v = spriteData.v(renderData.getRenderAge(), renderData.getAgePercent(), v); + } + + builder.vertex(matrix4f, vec.x, vec.y, vec.z); + builder.uv(u, v); + builder.color(renderData.getRed(), renderData.getGreen(), renderData.getBlue(), renderData.getAlpha()); + builder.uv2(renderData.getLightColor()); + builder.endVertex(); + } + } + } + } + + final class Billboard implements RenderStyle { + private static final Vector3fc[] PLANE_POSITIONS = { + // plane from -1 to 1 on Y axis and -1 to 1 on X axis + new Vector3f(1, -1, 0), new Vector3f(-1, -1, 0), new Vector3f(-1, 1, 0), new Vector3f(1, 1, 0) + }; + + @Override + public void render(PoseStack poseStack, QuasarParticle particle, RenderData renderData, Vector3fc renderOffset, VertexConsumer builder, double ageModifier, float partialTicks) { + //TODO fix UVs theyre fucked + Matrix4f matrix4f = poseStack.last().pose(); + Vector3fc rotation = renderData.getRenderRotation(); + + Quaternionf faceCameraRotation = Minecraft.getInstance().getEntityRenderDispatcher().cameraOrientation(); + SpriteData spriteData = renderData.getSpriteData(); + + int red = (int) (renderData.getRed() * 255.0F) & 0xFF; + int green = (int) (renderData.getGreen() * 255.0F) & 0xFF; + int blue = (int) (renderData.getBlue() * 255.0F) & 0xFF; + int alpha = (int) (renderData.getAlpha() * 255.0F) & 0xFF; + + // turn quat into pitch and yaw + Vector3f vec = new Vector3f(); + for (int j = 0; j < 4; j++) { + vec.set(PLANE_POSITIONS[j]); + if (particle.getData().velocityStretchFactor() > 0f) { + vec.set(vec.x * (1 + particle.getData().velocityStretchFactor()), vec.y, vec.z); + } + if (particle.getData().faceVelocity()) { + vec.rotateX(rotation.x()) + .rotateY(rotation.y()) + .rotateZ(rotation.z()); + } +// vec = vec.xRot(lerpedPitch).yRot(lerpedYaw).zRot(lerpedRoll); + faceCameraRotation.transform(vec).mul((float) (renderData.getRenderRadius() * ageModifier)).add(renderOffset); + + float u, v; + if (j == 0) { + u = 0; + v = 0; + } else if (j == 1) { + u = 1; + v = 0; + } else if (j == 2) { + u = 1; + v = 1; + } else { + u = 0; + v = 1; + } + if (spriteData != null) { + u = spriteData.u(renderData.getRenderAge(), renderData.getAgePercent(), u); + v = spriteData.v(renderData.getRenderAge(), renderData.getAgePercent(), v); + } +// if (particle.sprite != null) { +// u1 = u; +// v1 = v; +// } + builder.vertex(matrix4f, vec.x, vec.y, vec.z); + builder.uv(u, v); + builder.color(red, green, blue, alpha); + builder.uv2(renderData.getLightColor()); + builder.endVertex(); + } + } + } +} diff --git a/common/src/main/java/foundry/veil/api/quasar/registry/EmitterShapeRegistry.java b/common/src/main/java/foundry/veil/api/quasar/registry/EmitterShapeRegistry.java new file mode 100644 index 00000000..a5c70b42 --- /dev/null +++ b/common/src/main/java/foundry/veil/api/quasar/registry/EmitterShapeRegistry.java @@ -0,0 +1,43 @@ +package foundry.veil.api.quasar.registry; + +import com.mojang.serialization.Codec; +import foundry.veil.Veil; +import foundry.veil.api.client.render.post.PostPipeline; +import foundry.veil.api.client.render.post.stage.BlitPostStage; +import foundry.veil.api.client.render.post.stage.CopyPostStage; +import foundry.veil.api.client.render.post.stage.DepthFunctionPostStage; +import foundry.veil.api.client.render.post.stage.MaskPostStage; +import foundry.veil.api.quasar.emitters.shape.*; +import foundry.veil.platform.registry.RegistrationProvider; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import org.jetbrains.annotations.ApiStatus; + +import java.util.function.Supplier; + +/** + * Registry for all emitter shapes. + */ +public class EmitterShapeRegistry { + + public static final ResourceKey> REGISTRY_KEY = ResourceKey.createRegistryKey(Veil.veilPath("quasar/emitter_shape")); + private static final RegistrationProvider PROVIDER = RegistrationProvider.get(REGISTRY_KEY, Veil.MODID); + public static final Registry REGISTRY = PROVIDER.asVanillaRegistry(); + + public static final Supplier POINT = register("point", new Point()); + public static final Supplier HEMISPHERE = register("hemisphere", new Hemisphere()); + public static final Supplier CYLINDER = register("cylinder", new Cylinder()); + public static final Supplier SPHERE = register("sphere", new Sphere()); + public static final Supplier CUBE = register("cube", new Cube()); + public static final Supplier TORUS = register("torus", new Torus()); + public static final Supplier DISC = register("disc", new Disc()); + public static final Supplier PLANE = register("plane", new Plane()); + + @ApiStatus.Internal + public static void bootstrap() { + } + + private static Supplier register(String name, T shape) { + return PROVIDER.register(name, () -> shape); + } +} diff --git a/common/src/main/java/foundry/veil/api/quasar/registry/RenderStyleRegistry.java b/common/src/main/java/foundry/veil/api/quasar/registry/RenderStyleRegistry.java new file mode 100644 index 00000000..8b9dfe90 --- /dev/null +++ b/common/src/main/java/foundry/veil/api/quasar/registry/RenderStyleRegistry.java @@ -0,0 +1,33 @@ +package foundry.veil.api.quasar.registry; + +import foundry.veil.Veil; +import foundry.veil.api.quasar.emitters.shape.*; +import foundry.veil.api.quasar.particle.RenderData; +import foundry.veil.api.quasar.particle.RenderStyle; +import foundry.veil.platform.registry.RegistrationProvider; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import org.jetbrains.annotations.ApiStatus; + +import java.util.function.Supplier; + +/** + * Registry for all render styles. + */ +public class RenderStyleRegistry { + + public static final ResourceKey> REGISTRY_KEY = ResourceKey.createRegistryKey(Veil.veilPath("quasar/render_style")); + private static final RegistrationProvider PROVIDER = RegistrationProvider.get(REGISTRY_KEY, Veil.MODID); + public static final Registry REGISTRY = PROVIDER.asVanillaRegistry(); + + public static final Supplier CUBE = register("cube", new RenderStyle.Cube()); + public static final Supplier BILLBOARD = register("billboard", new RenderStyle.Billboard()); + + @ApiStatus.Internal + public static void bootstrap() { + } + + private static Supplier register(String name, T shape) { + return PROVIDER.register(name, () -> shape); + } +} diff --git a/common/src/main/java/foundry/veil/api/util/CodecUtil.java b/common/src/main/java/foundry/veil/api/util/CodecUtil.java index e0d9d48a..5dd4d9c3 100644 --- a/common/src/main/java/foundry/veil/api/util/CodecUtil.java +++ b/common/src/main/java/foundry/veil/api/util/CodecUtil.java @@ -1,10 +1,20 @@ package foundry.veil.api.util; +import com.mojang.datafixers.util.Either; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.*; +import foundry.veil.Veil; +import foundry.veil.api.quasar.emitters.shape.EmitterShape; +import foundry.veil.api.quasar.registry.EmitterShapeRegistry; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.ExtraCodecs; import org.joml.*; import java.util.List; +import java.util.Locale; +import java.util.Optional; import java.util.function.Function; import java.util.stream.Stream; @@ -36,4 +46,27 @@ private static DataResult> check(int size, List list) { } return DataResult.success(list); } + + /** + * Creates a codec which can accept either resource locations like `veil:cube` + * but also accepts legacy-style names like `CUBE` (used when things used to be + * enums, but are now registries) + */ + public static Codec registryOrLegacyCodec(Registry registry) { + Codec legacyCodec = Codec.STRING + .comapFlatMap( + name -> ResourceLocation.read(Veil.MODID + ":" + name.toLowerCase(Locale.ROOT)), + ResourceLocation::toString) + .flatXmap( + loc -> Optional.ofNullable(registry.get(loc)) + .map(DataResult::success) + .orElseGet(() -> DataResult.error(() -> "Unknown registry key in " + registry.key() + ": " + loc)), + object -> registry.getResourceKey(object) + .map(ResourceKey::location) + .map(DataResult::success) + .orElseGet(() -> DataResult.error(() -> "Unknown registry element in " + registry.key() + ":" + object))); + + return Codec.either(registry.byNameCodec(), legacyCodec) + .xmap(e -> e.map(Function.identity(), Function.identity()), Either::left); + } } diff --git a/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/shape/basic_smoke.json b/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/shape/basic_smoke.json index 0c5a0e39..fb4143ea 100644 --- a/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/shape/basic_smoke.json +++ b/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/shape/basic_smoke.json @@ -1,5 +1,5 @@ { - "shape": "SPHERE", + "shape": "veil:sphere", "dimensions": [ 0.5, 0.5, 0.5 ], diff --git a/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/shape/test_shape.json b/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/shape/test_shape.json index 6f8fe521..a89469f0 100644 --- a/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/shape/test_shape.json +++ b/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/shape/test_shape.json @@ -1,5 +1,5 @@ { - "shape": "CUBE", + "shape": "veil:cube", "dimensions": [ 20.0, 20.0, From 3c4880d332dcde55af3ee19eb2b8393351381e12 Mon Sep 17 00:00:00 2001 From: Will BL Date: Thu, 8 Aug 2024 10:56:28 +0100 Subject: [PATCH 16/47] fix(quasar): discard low-alpha fragments in particles (#31) --- .../veil/pinwheel/shaders/program/quasar/particle.fsh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/common/src/main/resources/assets/veil/pinwheel/shaders/program/quasar/particle.fsh b/common/src/main/resources/assets/veil/pinwheel/shaders/program/quasar/particle.fsh index 78bfd2ee..d0b4a54e 100644 --- a/common/src/main/resources/assets/veil/pinwheel/shaders/program/quasar/particle.fsh +++ b/common/src/main/resources/assets/veil/pinwheel/shaders/program/quasar/particle.fsh @@ -14,5 +14,9 @@ in vec4 vertexColor; out vec4 fragColor; void main() { - fragColor = linear_fog(texture(Sampler0, texCoord0) * vertexColor * ColorModulator, vertexDistance, FogStart, FogEnd, FogColor); + vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; + if (color.a < 0.1) { + discard; + } + fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); } From 64be82962fe1d74f9f9f16f018306d03dfa5ff02 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Thu, 8 Aug 2024 03:59:11 -0600 Subject: [PATCH 17/47] Lowered alpha cutoff --- .../assets/veil/pinwheel/shaders/program/quasar/particle.fsh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/resources/assets/veil/pinwheel/shaders/program/quasar/particle.fsh b/common/src/main/resources/assets/veil/pinwheel/shaders/program/quasar/particle.fsh index d0b4a54e..83f79f6d 100644 --- a/common/src/main/resources/assets/veil/pinwheel/shaders/program/quasar/particle.fsh +++ b/common/src/main/resources/assets/veil/pinwheel/shaders/program/quasar/particle.fsh @@ -15,7 +15,7 @@ out vec4 fragColor; void main() { vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; - if (color.a < 0.1) { + if (color.a < 0.01) { discard; } fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); From 5fe3a5b0b7be9c7ef5acd4fc334b02d020176f88 Mon Sep 17 00:00:00 2001 From: Will BL Date: Thu, 8 Aug 2024 11:00:10 +0100 Subject: [PATCH 18/47] feat(quasar): allow multiple shapes in emitter-settings (#32) Co-authored-by: Ocelot --- .../veil/api/quasar/data/EmitterSettings.java | 12 ++++++---- .../api/quasar/data/ParticleEmitterData.java | 3 +++ .../api/quasar/particle/ParticleEmitter.java | 8 +++---- .../java/foundry/veil/api/util/CodecUtil.java | 11 +++++++++ .../quasar/emitters/double_smoke_rings.json | 11 +++++++++ .../emitter/particle/smoke_bigger.json | 17 +++++++++++++ .../modules/emitter/shape/large_ring.json | 14 +++++++++++ .../modules/emitter/shape/small_ring.json | 14 +++++++++++ .../particle_data/smoke_big_static.json | 24 +++++++++++++++++++ 9 files changed, 106 insertions(+), 8 deletions(-) create mode 100644 common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/emitters/double_smoke_rings.json create mode 100644 common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/particle/smoke_bigger.json create mode 100644 common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/shape/large_ring.json create mode 100644 common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/shape/small_ring.json create mode 100644 common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/particle_data/smoke_big_static.json diff --git a/common/src/main/java/foundry/veil/api/quasar/data/EmitterSettings.java b/common/src/main/java/foundry/veil/api/quasar/data/EmitterSettings.java index 9785f996..83d29549 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/EmitterSettings.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/EmitterSettings.java @@ -2,20 +2,24 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import foundry.veil.api.util.CodecUtil; import net.minecraft.core.Holder; +import net.minecraft.util.ExtraCodecs; -public record EmitterSettings(Holder emitterShapeSettingsHolder, +import java.util.List; + +public record EmitterSettings(List> emitterShapeSettingsHolders, Holder particleSettingsHolder, boolean forceSpawn) { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - EmitterShapeSettings.CODEC.fieldOf("shape").forGetter(EmitterSettings::emitterShapeSettingsHolder), + CodecUtil.singleOrList(EmitterShapeSettings.CODEC).fieldOf("shape").forGetter(EmitterSettings::emitterShapeSettingsHolders), ParticleSettings.CODEC.fieldOf("particle_settings").forGetter(EmitterSettings::particleSettingsHolder), Codec.BOOL.optionalFieldOf("force_spawn", false).forGetter(EmitterSettings::forceSpawn) ).apply(instance, EmitterSettings::new)); - public EmitterShapeSettings emitterShapeSettings() { - return this.emitterShapeSettingsHolder.value(); + public List emitterShapeSettings() { + return this.emitterShapeSettingsHolders.stream().map(Holder::value).toList(); } public ParticleSettings particleSettings() { diff --git a/common/src/main/java/foundry/veil/api/quasar/data/ParticleEmitterData.java b/common/src/main/java/foundry/veil/api/quasar/data/ParticleEmitterData.java index 67b0fc84..0cc2c2bb 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/ParticleEmitterData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/ParticleEmitterData.java @@ -2,11 +2,14 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import foundry.veil.api.util.CodecUtil; import net.minecraft.core.Holder; import net.minecraft.resources.RegistryFileCodec; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.Nullable; +import java.util.List; + /** * @param maxLifetime * @param loop Whether the emitter will loop. If true, the emitter will reset after maxLifetime ticks diff --git a/common/src/main/java/foundry/veil/api/quasar/particle/ParticleEmitter.java b/common/src/main/java/foundry/veil/api/quasar/particle/ParticleEmitter.java index 6a385495..eff9bb8c 100644 --- a/common/src/main/java/foundry/veil/api/quasar/particle/ParticleEmitter.java +++ b/common/src/main/java/foundry/veil/api/quasar/particle/ParticleEmitter.java @@ -60,7 +60,7 @@ public class ParticleEmitter { private int rate; private int count; private int maxParticles; - private EmitterShapeSettings emitterShapeSettings; + private List emitterShapeSettings; private ParticleSettings particleSettings; private boolean forceSpawn; private QuasarParticleData particleData; @@ -107,7 +107,7 @@ private void spawn() { this.particleManager.reserve(count); for (int i = 0; i < count; i++) { - Vector3dc particlePos = this.emitterShapeSettings.getPos(this.randomSource, this.position); + Vector3dc particlePos = this.emitterShapeSettings.get(i % this.emitterShapeSettings.size()).getPos(this.randomSource, this.position); Vector3fc particleDirection = this.particleSettings.particleDirection(this.randomSource); // TODO @@ -376,7 +376,7 @@ public int getMaxParticles() { return this.maxParticles; } - public EmitterShapeSettings getEmitterShapeSettings() { + public List getEmitterShapeSettings() { return this.emitterShapeSettings; } @@ -449,7 +449,7 @@ public void setMaxParticles(int maxParticles) { this.maxParticles = maxParticles; } - public void setEmitterShapeSettings(EmitterShapeSettings emitterShapeSettings) { + public void setEmitterShapeSettings(List emitterShapeSettings) { this.emitterShapeSettings = emitterShapeSettings; } diff --git a/common/src/main/java/foundry/veil/api/util/CodecUtil.java b/common/src/main/java/foundry/veil/api/util/CodecUtil.java index 5dd4d9c3..d0513de1 100644 --- a/common/src/main/java/foundry/veil/api/util/CodecUtil.java +++ b/common/src/main/java/foundry/veil/api/util/CodecUtil.java @@ -47,6 +47,17 @@ private static DataResult> check(int size, List list) { return DataResult.success(list); } + public static Codec> singleOrList(Codec codec) { + return Codec.either( + codec.flatComapMap(List::of, + l -> l.size() == 1 + ? DataResult.success(l.get(0)) + : DataResult.error(() -> "List must have exactly one element.")), + ExtraCodecs.nonEmptyList(codec.listOf())) + .xmap(e -> e.map(Function.identity(), Function.identity()), + l -> l.size() == 1 ? Either.left(l) : Either.right(l)); + } + /** * Creates a codec which can accept either resource locations like `veil:cube` * but also accepts legacy-style names like `CUBE` (used when things used to be diff --git a/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/emitters/double_smoke_rings.json b/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/emitters/double_smoke_rings.json new file mode 100644 index 00000000..baf92c15 --- /dev/null +++ b/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/emitters/double_smoke_rings.json @@ -0,0 +1,11 @@ +{ + "max_lifetime": 40, + "loop": false, + "rate": 1, + "count": 16, + "emitter_settings": { + "shape": ["veil:large_ring", "veil:small_ring"], + "particle_settings": "veil:smoke_bigger" + }, + "particle_data": "veil:smoke_big_static" +} \ No newline at end of file diff --git a/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/particle/smoke_bigger.json b/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/particle/smoke_bigger.json new file mode 100644 index 00000000..ef4614f5 --- /dev/null +++ b/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/particle/smoke_bigger.json @@ -0,0 +1,17 @@ +{ + "random_speed": false, + "random_size": true, + "random_lifetime": true, + "initial_direction": [ + 0.0, + 0.0, + 0.0 + ], + "random_initial_direction": false, + "random_initial_rotation": false, + "particle_size_variation": 0.1, + "particle_lifetime": 48, + "particle_lifetime_variation": 32.0, + "particle_speed": 1.0, + "base_particle_size": 5.0 +} \ No newline at end of file diff --git a/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/shape/large_ring.json b/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/shape/large_ring.json new file mode 100644 index 00000000..44eec832 --- /dev/null +++ b/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/shape/large_ring.json @@ -0,0 +1,14 @@ +{ + "shape": "DISC", + "dimensions": [ + 2.0, + 0.01, + 2.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], + "from_surface": true +} \ No newline at end of file diff --git a/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/shape/small_ring.json b/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/shape/small_ring.json new file mode 100644 index 00000000..8fe259db --- /dev/null +++ b/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/emitter/shape/small_ring.json @@ -0,0 +1,14 @@ +{ + "shape": "DISC", + "dimensions": [ + 1.0, + 0.01, + 1.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], + "from_surface": true +} \ No newline at end of file diff --git a/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/particle_data/smoke_big_static.json b/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/particle_data/smoke_big_static.json new file mode 100644 index 00000000..2f8f828b --- /dev/null +++ b/common/src/main/resources/resourcepacks/test_particles/assets/veil/quasar/modules/particle_data/smoke_big_static.json @@ -0,0 +1,24 @@ +{ + "sprite_data": { + "sprite": "veil:textures/particle/smoke.png", + "frame_count": 64, + "frame_width": 8, + "frame_height": 8, + "stretch_to_lifetime": true + }, + "render_style": "BILLBOARD", + "init_modules": [ + "veil:smoke_random_init_rotation" + ], + "update_modules": [], + "collision_modules": [ + ], + "forces": [ + ], + "render_modules": [ + "veil:color/smoke_color_over_lifetime" + ], + "face_velocity": false, + "velocity_stretch_factor": 0.0, + "should_collide": true +} \ No newline at end of file From 346b7841dd20c11365e61feb573b06de5a834fe0 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Mon, 26 Aug 2024 08:45:52 -0600 Subject: [PATCH 19/47] WIP GLSL parser --- common/build.gradle | 3 - .../client/render/shader/ShaderManager.java | 6 +- .../shader/ShaderModificationManager.java | 30 +- .../shader/processor/ShaderCPreprocessor.java | 29 -- .../render/shader/SimpleShaderProcessor.java | 3 +- .../modifier/InputShaderModification.java | 10 +- .../modifier/ReplaceShaderModification.java | 5 +- .../shader/modifier/ShaderModification.java | 6 +- .../modifier/SimpleShaderModification.java | 122 +++---- .../modifier/VertexShaderModification.java | 116 +++---- .../transformer/VeilASTTransformer.java | 54 +-- .../shader/transformer/VeilJobParameters.java | 3 +- .../foundry/veil/impl/glsl/GlslLexer.java | 320 ++++++++++++++++++ .../foundry/veil/impl/glsl/GlslParser.java | 133 ++++++++ .../veil/impl/glsl/GlslSyntaxException.java | 50 +++ .../veil/impl/glsl/node/DeclarationNode.java | 24 ++ .../impl/glsl/node/DeclareFunctionNode.java | 14 + .../foundry/veil/impl/glsl/node/GlslNode.java | 13 + .../foundry/veil/impl/glsl/node/GlslTree.java | 22 ++ .../foundry/veil/impl/glsl/node/GlslType.java | 23 ++ .../veil/impl/glsl/node/GlslVersion.java | 12 + .../veil/impl/glsl/node/GlslVisitor.java | 4 + .../impl/glsl/type/GlslSpecifiedType.java | 5 + .../impl/glsl/type/GlslTypeQualifier.java | 69 ++++ .../veil/impl/glsl/type/StructSpecifier.java | 4 + .../veil/impl/glsl/type/TypeSpecifier.java | 26 ++ common/src/test/java/GlslTest.java | 53 +++ fabric/build.gradle | 4 - forge/build.gradle | 5 - gradle.properties | 3 - 30 files changed, 927 insertions(+), 244 deletions(-) delete mode 100644 common/src/main/java/foundry/veil/api/client/render/shader/processor/ShaderCPreprocessor.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/GlslLexer.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/GlslParser.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/GlslSyntaxException.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/DeclarationNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/DeclareFunctionNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/GlslNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/GlslType.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/GlslVersion.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/GlslVisitor.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/type/GlslSpecifiedType.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/type/GlslTypeQualifier.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/type/StructSpecifier.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/type/TypeSpecifier.java create mode 100644 common/src/test/java/GlslTest.java diff --git a/common/build.gradle b/common/build.gradle index ffeec0e3..c01cbe79 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -33,9 +33,6 @@ dependencies { compileOnly 'org.spongepowered:mixin:0.8.5' compileOnly 'org.jetbrains:annotations:24.0.1' - implementation "org.antlr:antlr4-runtime:${antlr_version}" - implementation "io.github.douira:glsl-transformer:${glsl_transformer_version}" - implementation "io.github.douira:glsl-preprocessor:${glsl_preprocessor_version}" implementation "gg.moonflower:molang-compiler:${molang_compiler_version}" implementation "io.github.spair:imgui-java-binding:$imgui_version" diff --git a/common/src/main/java/foundry/veil/api/client/render/shader/ShaderManager.java b/common/src/main/java/foundry/veil/api/client/render/shader/ShaderManager.java index c5957474..14dae5e2 100644 --- a/common/src/main/java/foundry/veil/api/client/render/shader/ShaderManager.java +++ b/common/src/main/java/foundry/veil/api/client/render/shader/ShaderManager.java @@ -10,7 +10,6 @@ import foundry.veil.api.client.render.framebuffer.FramebufferManager; import foundry.veil.api.client.render.post.PostProcessingManager; import foundry.veil.api.client.render.shader.definition.ShaderPreDefinitions; -import foundry.veil.api.client.render.shader.processor.ShaderCPreprocessor; import foundry.veil.api.client.render.shader.processor.ShaderCustomProcessor; import foundry.veil.api.client.render.shader.processor.ShaderModifyProcessor; import foundry.veil.api.client.render.shader.program.ProgramDefinition; @@ -198,11 +197,8 @@ private void compile(ShaderProgram program, ProgramDefinition definition, Shader private ShaderCompiler addProcessors(ShaderCompiler compiler, ResourceProvider provider) { return compiler.addDefaultProcessors() - // We need imports to keep their macros and pre-processor directives before the full shader is created - .addPreprocessor(new ShaderCPreprocessor(), false) .addPreprocessor(new ShaderModifyProcessor(), false) - .addPreprocessor(new ShaderCustomProcessor(provider), false) - .addPreprocessor(new ShaderCPreprocessor(), false); + .addPreprocessor(new ShaderCustomProcessor(provider), false); } /** diff --git a/common/src/main/java/foundry/veil/api/client/render/shader/ShaderModificationManager.java b/common/src/main/java/foundry/veil/api/client/render/shader/ShaderModificationManager.java index 4d3796b3..7fb2e5e0 100644 --- a/common/src/main/java/foundry/veil/api/client/render/shader/ShaderModificationManager.java +++ b/common/src/main/java/foundry/veil/api/client/render/shader/ShaderModificationManager.java @@ -5,13 +5,6 @@ import foundry.veil.impl.client.render.shader.modifier.ReplaceShaderModification; import foundry.veil.impl.client.render.shader.modifier.ShaderModification; import foundry.veil.impl.client.render.shader.modifier.SimpleShaderModification; -import foundry.veil.impl.client.render.shader.transformer.VeilASTTransformer; -import foundry.veil.impl.client.render.shader.transformer.VeilJobParameters; -import io.github.douira.glsl_transformer.GLSLLexer; -import io.github.douira.glsl_transformer.ast.print.PrintType; -import io.github.douira.glsl_transformer.ast.query.RootSupplier; -import io.github.douira.glsl_transformer.ast.transform.TransformationException; -import io.github.douira.glsl_transformer.parser.ParsingException; import net.minecraft.resources.FileToIdConverter; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.Resource; @@ -43,16 +36,17 @@ public class ShaderModificationManager extends SimplePreparableReloadListener> shaders; private Map names; public ShaderModificationManager() { - this.transformer = new VeilASTTransformer(); - this.transformer.setPrintType(PrintType.INDENTED_ANNOTATED); - this.transformer.setRootSupplier(RootSupplier.PREFIX_UNORDERED_ED_EXACT); - GLSLLexer lexer = this.transformer.getLexer(); - lexer.enableCustomDirective = true; +// this.transformer = new VeilASTTransformer(); +// this.transformer.setPrintType(PrintType.INDENTED_ANNOTATED); +// this.transformer.setRootSupplier(RootSupplier.PREFIX_UNORDERED_ED_EXACT); +// GLSLLexer lexer = this.transformer.getLexer(); +// lexer.enableCustomDirective = true; this.shaders = Collections.emptyMap(); } @@ -67,11 +61,11 @@ public ShaderModificationManager() { * @see ShaderModification */ public String applyModifiers(ResourceLocation shaderId, String source, int flags) { - try { - return this.transformer.transform(source, new VeilJobParameters(this, shaderId, flags)); - } catch (TransformationException | ParsingException | IllegalStateException | IllegalArgumentException e) { - Veil.LOGGER.error("Failed to transform shader: {}", shaderId, e); - } +// try { +// return this.transformer.transform(source, new VeilJobParameters(this, shaderId, flags)); +// } catch (TransformationException | ParsingException | IllegalStateException | IllegalArgumentException e) { +// Veil.LOGGER.error("Failed to transform shader: {}", shaderId, e); +// } return source; } diff --git a/common/src/main/java/foundry/veil/api/client/render/shader/processor/ShaderCPreprocessor.java b/common/src/main/java/foundry/veil/api/client/render/shader/processor/ShaderCPreprocessor.java deleted file mode 100644 index b932577a..00000000 --- a/common/src/main/java/foundry/veil/api/client/render/shader/processor/ShaderCPreprocessor.java +++ /dev/null @@ -1,29 +0,0 @@ -package foundry.veil.api.client.render.shader.processor; - -import foundry.veil.Veil; -import io.github.douira.glsl_preprocessor.DefaultPreprocessorListener; -import io.github.douira.glsl_preprocessor.Feature; -import io.github.douira.glsl_preprocessor.Preprocessor; -import io.github.douira.glsl_preprocessor.StringLexerSource; -import io.github.douira.glsl_transformer.ast.transform.TransformationException; -import io.github.douira.glsl_transformer.parser.ParsingException; - -import java.io.IOException; - -public class ShaderCPreprocessor implements ShaderPreProcessor { - - @Override - public String modify(Context ctx, String source) throws IOException { - try (Preprocessor preprocessor = new Preprocessor()) { - preprocessor.setListener(new DefaultPreprocessorListener()); - preprocessor.addInput(new StringLexerSource(source, true)); - preprocessor.addFeature(Feature.KEEPCOMMENTS); - preprocessor.addFeature(Feature.GLSL_PASSTHROUGH); - - return preprocessor.printToString(); - } catch (TransformationException | ParsingException | IllegalStateException | IllegalArgumentException e) { - Veil.LOGGER.error("Failed to parse shader: {}", ctx.name(), e); - } - return source; - } -} diff --git a/common/src/main/java/foundry/veil/impl/client/render/shader/SimpleShaderProcessor.java b/common/src/main/java/foundry/veil/impl/client/render/shader/SimpleShaderProcessor.java index 03f1eea5..1345796c 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/shader/SimpleShaderProcessor.java +++ b/common/src/main/java/foundry/veil/impl/client/render/shader/SimpleShaderProcessor.java @@ -1,7 +1,6 @@ package foundry.veil.impl.client.render.shader; import foundry.veil.api.client.render.shader.definition.ShaderPreDefinitions; -import foundry.veil.api.client.render.shader.processor.ShaderCPreprocessor; import foundry.veil.api.client.render.shader.processor.ShaderCustomProcessor; import foundry.veil.api.client.render.shader.processor.ShaderModifyProcessor; import foundry.veil.api.client.render.shader.processor.ShaderPreProcessor; @@ -24,7 +23,7 @@ public class SimpleShaderProcessor { private static ShaderPreProcessor processor; public static void setup(ResourceProvider resourceProvider) { - processor = ShaderPreProcessor.allOf(new ShaderCPreprocessor(), new ShaderModifyProcessor(), new ShaderCustomProcessor(resourceProvider), new ShaderCPreprocessor()); + processor = ShaderPreProcessor.allOf(new ShaderModifyProcessor(), new ShaderCustomProcessor(resourceProvider)); } public static void free() { diff --git a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/InputShaderModification.java b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/InputShaderModification.java index 9a76ee2a..807f0375 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/InputShaderModification.java +++ b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/InputShaderModification.java @@ -1,14 +1,10 @@ package foundry.veil.impl.client.render.shader.modifier; import foundry.veil.impl.client.render.shader.transformer.VeilJobParameters; -import io.github.douira.glsl_transformer.ast.node.TranslationUnit; -import io.github.douira.glsl_transformer.ast.transform.ASTInjectionPoint; -import io.github.douira.glsl_transformer.ast.transform.ASTParser; +import foundry.veil.impl.glsl.node.GlslTree; import org.jetbrains.annotations.ApiStatus; import java.io.IOException; -import java.util.function.Supplier; -import java.util.regex.Matcher; @ApiStatus.Internal public class InputShaderModification implements ShaderModification { @@ -22,8 +18,8 @@ public InputShaderModification(int priority, String input) { } @Override - public void inject(ASTParser parser, TranslationUnit tree, VeilJobParameters parameters) throws IOException { - tree.parseAndInjectNodes(parser, ASTInjectionPoint.BEFORE_DECLARATIONS, this.input.split("\n")); + public void inject(GlslTree tree, VeilJobParameters parameters) throws IOException { +// tree.parseAndInjectNodes(parser, ASTInjectionPoint.BEFORE_DECLARATIONS, this.input.split("\n")); } @Override diff --git a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/ReplaceShaderModification.java b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/ReplaceShaderModification.java index 3fa15f79..f7c28618 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/ReplaceShaderModification.java +++ b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/ReplaceShaderModification.java @@ -1,8 +1,7 @@ package foundry.veil.impl.client.render.shader.modifier; import foundry.veil.impl.client.render.shader.transformer.VeilJobParameters; -import io.github.douira.glsl_transformer.ast.node.TranslationUnit; -import io.github.douira.glsl_transformer.ast.transform.ASTParser; +import foundry.veil.impl.glsl.node.GlslTree; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.ApiStatus; @@ -13,7 +12,7 @@ public record ReplaceShaderModification(int priority, ResourceLocation veilShader) implements ShaderModification { @Override - public void inject(ASTParser parser, TranslationUnit tree, VeilJobParameters parameters) throws IOException { + public void inject(GlslTree tree, VeilJobParameters parameters) throws IOException { throw new UnsupportedEncodingException("Replace modification replaces file"); } } diff --git a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/ShaderModification.java b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/ShaderModification.java index 1d369ba0..719bd548 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/ShaderModification.java +++ b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/ShaderModification.java @@ -1,8 +1,7 @@ package foundry.veil.impl.client.render.shader.modifier; import foundry.veil.impl.client.render.shader.transformer.VeilJobParameters; -import io.github.douira.glsl_transformer.ast.node.TranslationUnit; -import io.github.douira.glsl_transformer.ast.transform.ASTParser; +import foundry.veil.impl.glsl.node.GlslTree; import org.jetbrains.annotations.ApiStatus; import java.io.IOException; @@ -26,12 +25,11 @@ public interface ShaderModification { /** * Injects this modification into the specified shader source. * - * @param parser The parser instance * @param tree The source to modify * @param parameters The parameters to use when injecting * @throws IOException If an error occurs with the format or applying the modifications */ - void inject(ASTParser parser, TranslationUnit tree, VeilJobParameters parameters) throws IOException; + void inject(GlslTree tree, VeilJobParameters parameters) throws IOException; /** * @return The priority of this modification. A higher priority will be applied before a lower priority modification diff --git a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/SimpleShaderModification.java b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/SimpleShaderModification.java index e2075231..9cb75b4a 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/SimpleShaderModification.java +++ b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/SimpleShaderModification.java @@ -1,22 +1,12 @@ package foundry.veil.impl.client.render.shader.modifier; import foundry.veil.impl.client.render.shader.transformer.VeilJobParameters; -import io.github.douira.glsl_transformer.ast.data.ChildNodeList; -import io.github.douira.glsl_transformer.ast.node.TranslationUnit; -import io.github.douira.glsl_transformer.ast.node.Version; -import io.github.douira.glsl_transformer.ast.node.VersionStatement; -import io.github.douira.glsl_transformer.ast.node.external_declaration.FunctionDefinition; -import io.github.douira.glsl_transformer.ast.node.statement.Statement; -import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.transform.ASTInjectionPoint; -import io.github.douira.glsl_transformer.ast.transform.ASTParser; +import foundry.veil.impl.glsl.node.GlslTree; import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.StringUtil; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.util.Objects; import java.util.regex.Matcher; @ApiStatus.Internal @@ -39,61 +29,61 @@ public SimpleShaderModification(int version, int priority, ResourceLocation[] in } @Override - public void inject(ASTParser parser, TranslationUnit tree, VeilJobParameters parameters) throws IOException { - if (parameters.applyVersion()) { - tree.ensureVersionStatement(); - VersionStatement statement = tree.getVersionStatement(); - if (statement.version.number < this.version) { - statement.version = Version.fromNumber(this.version); - } - } - - String[] includes = new String[this.includes.length]; - for (int i = 0; i < this.includes.length; i++) { - includes[i] = "#custom veil:include " + this.includes[i] + "\n"; - } - tree.parseAndInjectNodes(parser, ASTInjectionPoint.BEFORE_DECLARATIONS, includes); - - if (!StringUtil.isNullOrEmpty(this.uniform)) { - tree.parseAndInjectNodes(parser, ASTInjectionPoint.BEFORE_DECLARATIONS, this.fillPlaceholders(this.uniform).split("\n")); - } - - if (!StringUtil.isNullOrEmpty(this.output)) { - tree.parseAndInjectNodes(parser, ASTInjectionPoint.BEFORE_DECLARATIONS, this.fillPlaceholders(this.output).split("\n")); - } - - Root root = tree.getRoot(); - for (Function function : this.functions) { - String name = function.name(); - ChildNodeList statements = root.identifierIndex.getStream(name) - .map(id -> id.getBranchAncestor(FunctionDefinition.class, FunctionDefinition::getFunctionPrototype)) - .filter(definition -> { - if (definition == null) { - return false; - } - - int paramCount = function.parameters(); - if (paramCount == -1) { - return true; - } - return definition.getFunctionPrototype().getParameters().size() == paramCount; - }) - .findFirst() - .map(FunctionDefinition::getBody).orElseThrow(() -> { - int paramCount = function.parameters(); - if (paramCount == -1) { - return new IOException("Unknown function: " + name); - } - return new IOException("Unknown function with " + paramCount + " parameters: " + name); - }).getStatements(); - - Statement statement = parser.parseStatement(root, this.fillPlaceholders("{" + function.code() + "}")); - if (function.head()) { - statements.add(0, statement); - } else { - statements.add(statement); - } - } + public void inject(GlslTree tree, VeilJobParameters parameters) throws IOException { +// if (parameters.applyVersion()) { +// tree.ensureVersionStatement(); +// VersionStatement statement = tree.getVersionStatement(); +// if (statement.version.number < this.version) { +// statement.version = Version.fromNumber(this.version); +// } +// } +// +// String[] includes = new String[this.includes.length]; +// for (int i = 0; i < this.includes.length; i++) { +// includes[i] = "#custom veil:include " + this.includes[i] + "\n"; +// } +// tree.parseAndInjectNodes(parser, ASTInjectionPoint.BEFORE_DECLARATIONS, includes); +// +// if (!StringUtil.isNullOrEmpty(this.uniform)) { +// tree.parseAndInjectNodes(parser, ASTInjectionPoint.BEFORE_DECLARATIONS, this.fillPlaceholders(this.uniform).split("\n")); +// } +// +// if (!StringUtil.isNullOrEmpty(this.output)) { +// tree.parseAndInjectNodes(parser, ASTInjectionPoint.BEFORE_DECLARATIONS, this.fillPlaceholders(this.output).split("\n")); +// } +// +// Root root = tree.getRoot(); +// for (Function function : this.functions) { +// String name = function.name(); +// ChildNodeList statements = root.identifierIndex.getStream(name) +// .map(id -> id.getBranchAncestor(FunctionDefinition.class, FunctionDefinition::getFunctionPrototype)) +// .filter(definition -> { +// if (definition == null) { +// return false; +// } +// +// int paramCount = function.parameters(); +// if (paramCount == -1) { +// return true; +// } +// return definition.getFunctionPrototype().getParameters().size() == paramCount; +// }) +// .findFirst() +// .map(FunctionDefinition::getBody).orElseThrow(() -> { +// int paramCount = function.parameters(); +// if (paramCount == -1) { +// return new IOException("Unknown function: " + name); +// } +// return new IOException("Unknown function with " + paramCount + " parameters: " + name); +// }).getStatements(); +// +// Statement statement = parser.parseStatement(root, this.fillPlaceholders("{" + function.code() + "}")); +// if (function.head()) { +// statements.add(0, statement); +// } else { +// statements.add(statement); +// } +// } } public String fillPlaceholders(String code) { diff --git a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/VertexShaderModification.java b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/VertexShaderModification.java index eae9a4a3..7fe5a6ce 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/VertexShaderModification.java +++ b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/VertexShaderModification.java @@ -1,38 +1,22 @@ package foundry.veil.impl.client.render.shader.modifier; -import foundry.veil.impl.client.render.shader.transformer.VeilJobParameters; -import io.github.douira.glsl_transformer.ast.node.TranslationUnit; -import io.github.douira.glsl_transformer.ast.node.declaration.DeclarationMember; -import io.github.douira.glsl_transformer.ast.node.external_declaration.ExternalDeclaration; -import io.github.douira.glsl_transformer.ast.node.type.specifier.BuiltinNumericTypeSpecifier; -import io.github.douira.glsl_transformer.ast.node.type.specifier.TypeSpecifier; -import io.github.douira.glsl_transformer.ast.print.ASTPrinter; -import io.github.douira.glsl_transformer.ast.query.Root; -import io.github.douira.glsl_transformer.ast.query.match.Matcher; -import io.github.douira.glsl_transformer.ast.transform.ASTInjectionPoint; -import io.github.douira.glsl_transformer.ast.transform.ASTParser; -import io.github.douira.glsl_transformer.ast.traversal.ASTListener; -import io.github.douira.glsl_transformer.ast.traversal.ASTWalker; -import io.github.douira.glsl_transformer.parser.ParseShape; -import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; -import java.io.IOException; import java.util.HashMap; import java.util.Map; @ApiStatus.Internal public class VertexShaderModification extends SimpleShaderModification { - public static final Matcher INPUT = new Matcher<>("in type name;", ParseShape.EXTERNAL_DECLARATION) { - { - Root root = this.pattern.getRoot(); - this.markClassWildcard("type", root.identifierIndex.getUnique("type").getAncestor(TypeSpecifier.class), BuiltinNumericTypeSpecifier.class); - this.markClassWildcard("name*", root.identifierIndex.getUnique("name").getAncestor(DeclarationMember.class)); - } - }; +// public static final Matcher INPUT = new Matcher<>("in type name;", ParseShape.EXTERNAL_DECLARATION) { +// { +// Root root = this.pattern.getRoot(); +// this.markClassWildcard("type", root.identifierIndex.getUnique("type").getAncestor(TypeSpecifier.class), BuiltinNumericTypeSpecifier.class); +// this.markClassWildcard("name*", root.identifierIndex.getUnique("name").getAncestor(DeclarationMember.class)); +// } +// }; private final Attribute[] attributes; private final Map mapper; @@ -43,49 +27,49 @@ public VertexShaderModification(int version, int priority, ResourceLocation[] in this.mapper = new HashMap<>(this.attributes.length); } - @Override - public void inject(ASTParser parser, TranslationUnit tree, VeilJobParameters parameters) throws IOException { - if (this.attributes.length > 0) { - Map validInputs = new Int2ObjectArrayMap<>(); - - Root root = tree.getRoot(); - - root.processMatches(parser, tree.getChildren().stream().filter(dec -> dec.hasAncestor(INPUT.getPatternClass())), INPUT, externalDeclaration -> { - String[] parts = {null, null}; - ASTWalker.walk(new ASTListener() { - @Override - public void enterTypeSpecifier(TypeSpecifier node) { - parts[0] = ASTPrinter.printSimple(node); - } - - @Override - public void enterDeclarationMember(DeclarationMember node) { - parts[1] = node.getName().getName(); - } - }, externalDeclaration); - validInputs.put(validInputs.size(), new Attribute(validInputs.size(), parts[0], parts[1])); - }); - - this.mapper.clear(); - for (Attribute attribute : this.attributes) { - Attribute sourceAttribute = validInputs.get(attribute.index); - if (sourceAttribute == null) { - // TODO this might be messed up on mac. It needs to be tested - tree.parseAndInjectNode(parser, ASTInjectionPoint.BEFORE_DECLARATIONS, "layout(location = " + attribute.index + ") in " + attribute.type + " " + attribute.name + ";"); - this.mapper.put(attribute.name, attribute.name); - continue; - } - - if (!sourceAttribute.type.equals(attribute.type)) { - throw new IOException("Expected attribute " + attribute.index + " to be " + attribute.type + " but was " + sourceAttribute.type); - } - - this.mapper.put(attribute.name, sourceAttribute.name); - } - } - - super.inject(parser, tree, parameters); - } +// @Override +// public void inject(ASTParser parser, TranslationUnit tree, VeilJobParameters parameters) throws IOException { +// if (this.attributes.length > 0) { +// Map validInputs = new Int2ObjectArrayMap<>(); +// +// Root root = tree.getRoot(); +// +// root.processMatches(parser, tree.getChildren().stream().filter(dec -> dec.hasAncestor(INPUT.getPatternClass())), INPUT, externalDeclaration -> { +// String[] parts = {null, null}; +// ASTWalker.walk(new ASTListener() { +// @Override +// public void enterTypeSpecifier(TypeSpecifier node) { +// parts[0] = ASTPrinter.printSimple(node); +// } +// +// @Override +// public void enterDeclarationMember(DeclarationMember node) { +// parts[1] = node.getName().getName(); +// } +// }, externalDeclaration); +// validInputs.put(validInputs.size(), new Attribute(validInputs.size(), parts[0], parts[1])); +// }); +// +// this.mapper.clear(); +// for (Attribute attribute : this.attributes) { +// Attribute sourceAttribute = validInputs.get(attribute.index); +// if (sourceAttribute == null) { +// // TODO this might be messed up on mac. It needs to be tested +// tree.parseAndInjectNode(parser, ASTInjectionPoint.BEFORE_DECLARATIONS, "layout(location = " + attribute.index + ") in " + attribute.type + " " + attribute.name + ";"); +// this.mapper.put(attribute.name, attribute.name); +// continue; +// } +// +// if (!sourceAttribute.type.equals(attribute.type)) { +// throw new IOException("Expected attribute " + attribute.index + " to be " + attribute.type + " but was " + sourceAttribute.type); +// } +// +// this.mapper.put(attribute.name, sourceAttribute.name); +// } +// } +// +// super.inject(parser, tree, parameters); +// } @Override protected String getPlaceholder(String key) { diff --git a/common/src/main/java/foundry/veil/impl/client/render/shader/transformer/VeilASTTransformer.java b/common/src/main/java/foundry/veil/impl/client/render/shader/transformer/VeilASTTransformer.java index 848f1929..a26de66f 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/shader/transformer/VeilASTTransformer.java +++ b/common/src/main/java/foundry/veil/impl/client/render/shader/transformer/VeilASTTransformer.java @@ -1,27 +1,27 @@ -package foundry.veil.impl.client.render.shader.transformer; - -import foundry.veil.Veil; -import foundry.veil.impl.client.render.shader.modifier.ShaderModification; -import io.github.douira.glsl_transformer.ast.node.TranslationUnit; -import io.github.douira.glsl_transformer.ast.print.ASTPrinter; -import io.github.douira.glsl_transformer.ast.query.RootSupplier; -import io.github.douira.glsl_transformer.ast.transform.ASTTransformer; - -public class VeilASTTransformer extends ASTTransformer { - - @Override - public String transform(RootSupplier rootSupplier, String input) { - TranslationUnit tree = this.parseTranslationUnit(rootSupplier, input); - VeilJobParameters parameters = this.getJobParameters(); - - for (ShaderModification modification : parameters.modifiers()) { - try { - modification.inject(this, tree, parameters); - } catch (Exception e) { - Veil.LOGGER.error("Failed to apply modification {} to shader instance {}. Skipping", parameters.modificationManager().getModifierId(modification), parameters.shaderId(), e); - } - } - - return ASTPrinter.print(this.getPrintType(), tree); - } -} +//package foundry.veil.impl.client.render.shader.transformer; +// +//import foundry.veil.Veil; +//import foundry.veil.impl.client.render.shader.modifier.ShaderModification; +//import io.github.douira.glsl_transformer.ast.node.TranslationUnit; +//import io.github.douira.glsl_transformer.ast.print.ASTPrinter; +//import io.github.douira.glsl_transformer.ast.query.RootSupplier; +//import io.github.douira.glsl_transformer.ast.transform.ASTTransformer; +// +//public class VeilASTTransformer extends ASTTransformer { +// +// @Override +// public String transform(RootSupplier rootSupplier, String input) { +// TranslationUnit tree = this.parseTranslationUnit(rootSupplier, input); +// VeilJobParameters parameters = this.getJobParameters(); +// +// for (ShaderModification modification : parameters.modifiers()) { +// try { +// modification.inject(this, tree, parameters); +// } catch (Exception e) { +// Veil.LOGGER.error("Failed to apply modification {} to shader instance {}. Skipping", parameters.modificationManager().getModifierId(modification), parameters.shaderId(), e); +// } +// } +// +// return ASTPrinter.print(this.getPrintType(), tree); +// } +//} diff --git a/common/src/main/java/foundry/veil/impl/client/render/shader/transformer/VeilJobParameters.java b/common/src/main/java/foundry/veil/impl/client/render/shader/transformer/VeilJobParameters.java index 386b1a82..0b16fad3 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/shader/transformer/VeilJobParameters.java +++ b/common/src/main/java/foundry/veil/impl/client/render/shader/transformer/VeilJobParameters.java @@ -2,14 +2,13 @@ import foundry.veil.api.client.render.shader.ShaderModificationManager; import foundry.veil.impl.client.render.shader.modifier.ShaderModification; -import io.github.douira.glsl_transformer.ast.transform.JobParameters; import net.minecraft.resources.ResourceLocation; import java.util.Collection; public record VeilJobParameters(ShaderModificationManager modificationManager, ResourceLocation shaderId, - int flags) implements JobParameters { + int flags) { /** * Whether the version is required and will be applied diff --git a/common/src/main/java/foundry/veil/impl/glsl/GlslLexer.java b/common/src/main/java/foundry/veil/impl/glsl/GlslLexer.java new file mode 100644 index 00000000..c222c91e --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/GlslLexer.java @@ -0,0 +1,320 @@ +package foundry.veil.impl.glsl; + +import com.mojang.brigadier.StringReader; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author Ocelot + */ +@ApiStatus.Internal +public final class GlslLexer { + + public static Token[] createTokens(String input) throws GlslSyntaxException { + StringReader reader = new StringReader(input); + List tokens = new ArrayList<>(); + + reader.skipWhitespace(); + while (reader.canRead()) { + Token token = getToken(reader); + if (token != null) { + tokens.add(token); + reader.skipWhitespace(); + continue; + } + + throw new GlslSyntaxException("Unknown Token", reader.getString(), reader.getCursor() + 1); + } + + return tokens.toArray(Token[]::new); + } + + private static @Nullable Token getToken(StringReader reader) { + String word = reader.getRemaining(); + for (TokenType type : TokenType.values()) { + Matcher matcher = type.pattern.matcher(word); + if (matcher.find() && matcher.start() == 0) { + reader.setCursor(reader.getCursor() + matcher.end()); + return new Token(type, word.substring(0, matcher.end())); + } + } + + return null; + } + + private static @Nullable Token getToken(StringReader reader, TokenType type) { + String word = reader.getRemaining(); + Matcher matcher = type.pattern.matcher(word); + if (matcher.find() && matcher.start() == 0) { + reader.setCursor(reader.getCursor() + matcher.end()); + return new Token(type, word.substring(0, matcher.end())); + } + return null; + } + + public record Token(TokenType type, String value) { + @Override + public String toString() { + return this.type + "[" + this.value + "]"; + } + } + + private static final int FLAG_TYPE = 1; + private static final int FLAG_MODIFIER = 2; + + public enum TokenType { + DIRECTIVE("#.*"), + GLSL_MACRO("__LINE__|__FILE__|__VERSION__"), + COMMENT("\\/\\/.*"), + MULTI_COMMENT("\\/\\*(?:.|[\\n\\r])*\\*\\/|\\/\\/(?:.*\\\\[\\n\\r]?)+[\\n\\r]?(?:.*)"), + + CONST("const", FLAG_MODIFIER), + BOOL("bool", FLAG_TYPE), + FLOAT("float", FLAG_TYPE), + INT("int", FLAG_TYPE), + UINT("uint", FLAG_TYPE), + DOUBLE("double", FLAG_TYPE), + + BVEC2("bvec2", FLAG_TYPE), + BVEC3("bvec3", FLAG_TYPE), + BVEC4("bvec4", FLAG_TYPE), + IVEC2("ivec2", FLAG_TYPE), + IVEC3("ivec3", FLAG_TYPE), + IVEC4("ivec4", FLAG_TYPE), + UVEC2("uvec2", FLAG_TYPE), + UVEC3("uvec3", FLAG_TYPE), + UVEC4("uvec4", FLAG_TYPE), + VEC2("vec2", FLAG_TYPE), + VEC3("vec3", FLAG_TYPE), + VEC4("vec4", FLAG_TYPE), + + MAT2("mat2", FLAG_TYPE), + MAT3("mat3", FLAG_TYPE), + MAT4("mat4", FLAG_TYPE), + MAT2X2("mat2x2", FLAG_TYPE), + MAT2X3("mat2x3", FLAG_TYPE), + MAT2X4("mat2x4", FLAG_TYPE), + MAT3X2("mat3x2", FLAG_TYPE), + MAT3X3("mat3x3", FLAG_TYPE), + MAT3X4("mat3x4", FLAG_TYPE), + MAT4X2("mat4x2", FLAG_TYPE), + MAT4X3("mat4x3", FLAG_TYPE), + MAT4X4("mat4x4", FLAG_TYPE), + + DVEC2("dvec2", FLAG_TYPE), + DVEC3("dvec3", FLAG_TYPE), + DVEC4("dvec4", FLAG_TYPE), + DMAT2("dmat2", FLAG_TYPE), + DMAT3("dmat3", FLAG_TYPE), + DMAT4("dmat4", FLAG_TYPE), + DMAT2X2("dmat2x2", FLAG_TYPE), + DMAT2X3("dmat2x3", FLAG_TYPE), + DMAT2X4("dmat2x4", FLAG_TYPE), + DMAT3X2("dmat3x2", FLAG_TYPE), + DMAT3X3("dmat3x3", FLAG_TYPE), + DMAT3X4("dmat3x4", FLAG_TYPE), + DMAT4X2("dmat4x2", FLAG_TYPE), + DMAT4X3("dmat4x3", FLAG_TYPE), + DMAT4X4("dmat4x4", FLAG_TYPE), + + CENTROID("centroid", FLAG_MODIFIER), + IN("in"), + OUT("out"), + INOUT("inout"), + UNIFORM("uniform"), + PATCH("patch"), + SAMPLE("sample"), + BUFFER("buffer"), + SHARED("shared"), + COHERENT("cohent"), + VOLATILE("volatile", FLAG_MODIFIER), + RESTRICT("restrict", FLAG_MODIFIER), + READONLY("readonly", FLAG_MODIFIER), + WRITEONLY("writeonly", FLAG_MODIFIER), + NOPERSPECTIVE("noperspective", FLAG_MODIFIER), + FLAT("flat", FLAG_MODIFIER), + SMOOTH("smooth", FLAG_MODIFIER), + LAYOUT("layout", FLAG_MODIFIER), + + ATOMIC_UINT("atomic_uint", FLAG_TYPE), + + SAMPLER2D("sampler2D", FLAG_TYPE), + SAMPLER3D("sampler3D", FLAG_TYPE), + SAMPLERCUBE("samplerCube", FLAG_TYPE), + SAMPLER2DSHADOW("sampler2DShadow", FLAG_TYPE), + SAMPLERCUBESHADOW("samplerCubeShadow", FLAG_TYPE), + SAMPLER2DARRAY("sampler2DArray", FLAG_TYPE), + SAMPLER2DARRAYSHADOW("sampler2DArrayShadow", FLAG_TYPE), + ISAMPLER2D("isampler2D", FLAG_TYPE), + ISAMPLER3D("isampler3D", FLAG_TYPE), + ISAMPLERCUBE("isamplerCube", FLAG_TYPE), + ISAMPLER2DARRAY("isampler2DArray", FLAG_TYPE), + USAMPLER2D("usampler2D", FLAG_TYPE), + USAMPLER3D("usampler3D", FLAG_TYPE), + USAMPLERCUBE("usamplerCube", FLAG_TYPE), + USAMPLER2DARRAY("uSampler2DArray", FLAG_TYPE), + + SAMPLER1D("sampler1D", FLAG_TYPE), + SAMPLER1DSHADOW("sampler1DShadow", FLAG_TYPE), + SAMPLER1DARRAY("sampler1DArray", FLAG_TYPE), + SAMPLER1DARRAYSHADOW("sampler1DArrayShadow", FLAG_TYPE), + ISAMPLER1D("isampler1D", FLAG_TYPE), + ISAMPLER1DARRAY("isampler1DArray", FLAG_TYPE), + USAMPLER1D("usampler1D", FLAG_TYPE), + USAMPLER1DARRAY("usampler1DArray", FLAG_TYPE), + SAMPLER2DRECT("sampler2DRect", FLAG_TYPE), + SAMPLER2DRECTSHADOW("sampler2DRectShadow", FLAG_TYPE), + ISAMPLER2DRECT("isampler2DRect", FLAG_TYPE), + USAMPLER2DRECT("usampler2DRect", FLAG_TYPE), + + SAMPLERBUFFER("samplerBuffer", FLAG_TYPE), + ISAMPLERBUFFER("isamplerBuffer", FLAG_TYPE), + USAMPLERBUFFER("usamplerBuffer", FLAG_TYPE), + SAMPLERCUBEARRAY("samplerCubeArray", FLAG_TYPE), + SAMPLERCUBEARRAYSHADOW("samplerCubeArrayShadow", FLAG_TYPE), + ISAMPLERCUBEARRAY("isamplerCubeArray", FLAG_TYPE), + USAMPLERCUBEARRAY("usamplerCubeArray", FLAG_TYPE), + SAMPLER2DMS("sampler2Dms", FLAG_TYPE), + ISAMPLER2DMS("isampler2Dms", FLAG_TYPE), + USAMPLER2DMS("usampler2Dms", FLAG_TYPE), + SAMPLER2DMSARRAY("sampler2DMSArray", FLAG_TYPE), + ISAMPLER2DMSARRAY("isampler2DMSArray", FLAG_TYPE), + USAMPLER2DMSARRAY("usampler2DMSArray", FLAG_TYPE), + IMAGE2D("image2D", FLAG_TYPE), + IIMAGE2D("iimage2D", FLAG_TYPE), + UIMAGE2D("uimage2D", FLAG_TYPE), + IMAGE3D("image3D", FLAG_TYPE), + IIMAGE3D("iimage3D", FLAG_TYPE), + UIMAGE3D("uimage3D", FLAG_TYPE), + IMAGECUBE("imagecube", FLAG_TYPE), + IIMAGECUBE("iimageCube", FLAG_TYPE), + UIMAGECUBE("uimageCube", FLAG_TYPE), + IMAGEBUFFER("imageBuffer", FLAG_TYPE), + IIMAGEBUFFER("iimageBuffer", FLAG_TYPE), + UIMAGEBUFFER("uimageBuffer", FLAG_TYPE), + IMAGE2DARRAY("image2DArray", FLAG_TYPE), + IIMAGE2DARRAY("iimage2DArray", FLAG_TYPE), + UIMAGE2DARRAY("uimage2DArray", FLAG_TYPE), + IMAGECUBEARRAY("imagecubeArray", FLAG_TYPE), + IIMAGECUBEARRAY("iimageCubeArray", FLAG_TYPE), + UIMAGECUBEARRAY("uimageCubeArray", FLAG_TYPE), + + IMAGE1D("image1D", FLAG_TYPE), + IIMAGE1D("iimage1D", FLAG_TYPE), + UIMAGE1D("uimage1D", FLAG_TYPE), + IMAGE1DARRAY("image1DArray", FLAG_TYPE), + IIMAGE1DARRAY("iimage1DArray", FLAG_TYPE), + UIMAGE1DARRAY("uimage1DArray", FLAG_TYPE), + IMAGE2DRECT("image2DRect", FLAG_TYPE), + IIMAGE2DRECT("iimage2DRect", FLAG_TYPE), + UIMAGE2DRECT("uimage2DRect", FLAG_TYPE), + IMAGE2DMS("image2Dms", FLAG_TYPE), + IIMAGE2DMS("iimage2DMS", FLAG_TYPE), + UIMAGE2DMS("uimage2DMS", FLAG_TYPE), + IMAGE2DMSARRAY("image2DMSArray", FLAG_TYPE), + IIMAGE2DMSARRAY("iimage2DMSArray", FLAG_TYPE), + UIMAGE2DMSARRAY("uimage2DMSArray", FLAG_TYPE), + + STRUCT("struct"), + VOID("void", FLAG_TYPE), + + WHILE("while"), + BREAK("break"), + CONTINUE("continue"), + DO("do"), + ELSE("else"), + FOR("for"), + IF("if"), + DISCARD("discard"), + RETURN("return"), + SWITCH("switch"), + CASE("case"), + DEFAULT("default"), + SUBROUTINE("subroutine"), + + // TYPE_NAME ?? + FLOATING_CONSTANT("(?:(?:\\d+\\.\\d+|\\d+\\.|\\.\\d+)(?:[eE][+-]?\\d+)?(?:f|F|lf|LF)?)|(?:\\d+)(?:\\.|[eE][+-]?\\d+)(?:f|F|lf|LF)?"), + INTEGER_HEXADECIMAL_CONSTANT("0[xX][0-9a-fA-F]*[uU]?"), + INTEGER_OCTAL_CONSTANT("0[0-7]*[uU]?"), + INTEGER_DECIMAL_CONSTANT("[1-9][\\d]*[uU]?"), + // UINTCONSTANT + BOOL_CONSTANT("true|false"), + // FIELD_SELECTION + + LEFT_OP("<<"), + RIGHT_OP(">>"), + INC_OP("\\+\\+"), + DEC_OP("--"), + LE_OP("<="), + GE_OP(">="), + EQ_OP("=="), + NE_OP("!="), + AND_OP("&&"), + OR_OP("\\|\\|"), + XOR_OP("\\^\\^"), + MUL_ASSIGN("\\*="), + DIV_ASSIGN("\\/="), + ADD_ASSIGN("\\+="), + MOD_ASSIGN("%="), + LEFT_ASSIGN("<<="), + RIGHT_ASSIGN(">>="), + AND_ASSIGN("&="), + XOR_ASSIGN("\\^="), + OR_ASSIGN("\\|="), + SUB_ASSIGN("-="), + LEFT_PAREN("\\("), + RIGHT_PAREN("\\)"), + LEFT_BRACKET("\\["), + RIGHT_BRACKET("\\]"), + LEFT_BRACE("\\{"), + RIGHT_BRACE("\\}"), + DOT("\\."), + COMMA(","), + COLON(":"), + EQUAL("="), + SEMICOLON(";"), + BANG("!"), + DASH("-"), + TILDE("~"), + PLUS("\\+"), + STAR("\\*"), + SLASH("\\/"), + PERCENT("%"), + LEFT_ANGLE("<"), + RIGHT_ANGLE(">"), + VERTICAL_BAR("\\|"), + CARET("\\^"), + AMPERSAND("&"), + QUESTION("\\?"), + + INVARIANT("invariant"), + PRECISE("precise"), + HIGH_PRECISION("highp"), + MEDIUM_PRECISION("mediump"), + LOW_PRECISION("lowp"), + PRECISION("precision"), + + IDENTIFIER("[_a-zA-Z][\\d_a-zA-Z]*"); + + private final Pattern pattern; + private final int flags; + + TokenType(String regex) { + this(regex, 0); + } + + TokenType(String regex, int flags) { + this.pattern = Pattern.compile(regex); + this.flags = flags; + } + + public boolean isType() { + return (this.flags & FLAG_TYPE) != 0; + } + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java b/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java new file mode 100644 index 00000000..fc527b6a --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java @@ -0,0 +1,133 @@ +package foundry.veil.impl.glsl; + +import foundry.veil.impl.glsl.node.DeclarationNode; +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.node.GlslTree; +import foundry.veil.impl.glsl.node.GlslVersion; +import org.jetbrains.annotations.Nullable; + +public final class GlslParser { + + private GlslParser() { + } + + public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxException { + TokenReader reader = new TokenReader(tokens); + + GlslVersion version = new GlslVersion(110, true); + + // Try to parse version statements + GlslLexer.Token token = reader.peek(); + if (token.type() == GlslLexer.TokenType.DIRECTIVE && token.value().startsWith("#version ")) { + reader.skip(); + String[] parts = token.value().substring(9).split(" +", 2); + try { + int ver = Integer.parseInt(parts[0]); + boolean core = parts.length == 1 || parts[1].equals("core"); + version = new GlslVersion(ver, core); + } catch (NumberFormatException e) { + throw reader.error("Invalid Version: " + token.value() + ". " + e.getMessage()); + } + } + + while (reader.canRead()) { + GlslNode node = parseExpression(reader); + System.out.println(node); + } + + return new GlslTree(version); + } + + private static GlslNode parseExpression(TokenReader reader) throws GlslSyntaxException { + GlslLexer.Token token = reader.peek(); + + GlslNode left; + + // Declaration + if (token.type().isType()) { + reader.skip(); + GlslLexer.Token name = reader.consume(GlslLexer.TokenType.IDENTIFIER); + left = new DeclarationNode(token, name.value()); + } else { + throw reader.error("Invalid expression: " + token.value()); + } + + token = reader.peek(); + if (token.type() == GlslLexer.TokenType.SEMICOLON) { + reader.skip(); + return left; + } + + switch (token.type()) { + case EQUAL -> { + reader.skip(); + } + } + } + + private static GlslLexer.Token parseTypeSpecifier(TokenReader reader) throws GlslSyntaxException { + GlslLexer.Token token = reader.peek(); + if (!token.type().isType()) { + throw reader.error("Invalid type specifier: " + token.value()); + } + return token; + } + + private static class TokenReader { + + private final GlslLexer.Token[] tokens; + private int cursor; + + public TokenReader(GlslLexer.Token[] tokens) { + this.tokens = tokens; + } + + public String getString() { + StringBuilder builder = new StringBuilder(); + for (GlslLexer.Token token : this.tokens) { + builder.append(token.value()); + } + return builder.toString(); + } + + public boolean canRead(int length) { + return this.cursor + length <= this.tokens.length; + } + + public boolean canRead() { + return this.canRead(1); + } + + public int getCursorOffset() { + int offset = 0; + for (int i = 0; i <= Math.min(this.cursor, this.tokens.length - 1); i++) { + offset += this.tokens[i].value().length(); + } + return offset; + } + + public GlslLexer.Token peek() { + return this.peek(0); + } + + public @Nullable GlslLexer.Token peek(int amount) { + return this.cursor + amount < this.tokens.length ? this.tokens[this.cursor + amount] : null; + } + + public GlslLexer.Token consume(GlslLexer.TokenType token) throws GlslSyntaxException { + if (!this.canRead() || this.peek().type() != token) { + throw this.error("Expected " + token); + } + this.cursor++; + return this.peek(-1); + } + + public GlslSyntaxException error(String error) { + return new GlslSyntaxException(error, this.getString(), this.getCursorOffset()); + } + + public void skip() { + this.cursor++; + } + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/GlslSyntaxException.java b/common/src/main/java/foundry/veil/impl/glsl/GlslSyntaxException.java new file mode 100644 index 00000000..cd5ef199 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/GlslSyntaxException.java @@ -0,0 +1,50 @@ +package foundry.veil.impl.glsl; + +import org.jetbrains.annotations.ApiStatus; + +/** + * @author Ocelot + */ +@ApiStatus.Internal +public class GlslSyntaxException extends Exception { + + public static final int CONTEXT_AMOUNT = 64; + + private final String message; + private final String input; + private final int cursor; + + public GlslSyntaxException(String message, String input, int cursor) { + super(message); + this.message = message; + this.input = input; + this.cursor = cursor; + } + + @Override + public String getMessage() { + String message = this.message; + String context = this.getContext(); + if (context != null) { + message += " at position " + this.cursor + ": " + context; + } + return message; + } + + private String getContext() { + if (this.input == null || this.cursor < 0) { + return null; + } + StringBuilder builder = new StringBuilder(); + int cursor = Math.min(this.input.length(), this.cursor); + + if (cursor > CONTEXT_AMOUNT) { + builder.append("..."); + } + + builder.append(this.input, Math.max(0, cursor - CONTEXT_AMOUNT), cursor); + builder.append("<--[HERE]"); + + return builder.toString(); + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/DeclarationNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/DeclarationNode.java new file mode 100644 index 00000000..4062871d --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/DeclarationNode.java @@ -0,0 +1,24 @@ +package foundry.veil.impl.glsl.node; + +import foundry.veil.impl.glsl.GlslLexer; + +public class DeclarationNode implements GlslNode { + + private final GlslLexer.Token type; + private final String name; + + public DeclarationNode(GlslLexer.Token type, String name) { + this.type = type; + this.name = name; + } + + @Override + public void visit(GlslVisitor visitor) { + + } + + @Override + public String toString() { + return this.type.value() + " " + this.name; + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/DeclareFunctionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/DeclareFunctionNode.java new file mode 100644 index 00000000..2b0f97b1 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/DeclareFunctionNode.java @@ -0,0 +1,14 @@ +package foundry.veil.impl.glsl.node; + +import foundry.veil.impl.glsl.GlslLexer; + +public class DeclareFunctionNode implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } + + public record ParameterDeclaration() { + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslNode.java new file mode 100644 index 00000000..34642360 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslNode.java @@ -0,0 +1,13 @@ +package foundry.veil.impl.glsl.node; + +import java.util.Collection; +import java.util.Collections; + +public interface GlslNode { + + void visit(GlslVisitor visitor); + + default Collection children() { + return Collections.emptySet(); + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java new file mode 100644 index 00000000..587dcf8f --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java @@ -0,0 +1,22 @@ +package foundry.veil.impl.glsl.node; + +public class GlslTree { + + private GlslVersion version; + + public GlslTree(GlslVersion version) { + this.version = version; + } + + public void visit(GlslVisitor visitor) { + + } + + public GlslVersion getVersion() { + return this.version; + } + + public void setVersion(GlslVersion version) { + this.version = version; + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslType.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslType.java new file mode 100644 index 00000000..fc0b3ed9 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslType.java @@ -0,0 +1,23 @@ +package foundry.veil.impl.glsl.node; + +public record GlslType() { + + public enum StorageQualifier { + CONST, + IN, + OUT, + INOUT, + CENTROID, + PATCH, + SAMPLE, + UNIFORM, + BUFFER, + SHARED, + COHERENT, + VOLATILE, + RESTRICT, + READONLY, + WRITEONLY, + SUBROUTINE + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslVersion.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslVersion.java new file mode 100644 index 00000000..af914d93 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslVersion.java @@ -0,0 +1,12 @@ +package foundry.veil.impl.glsl.node; + +public record GlslVersion(int version, boolean core) { + + public GlslVersion withVersion(int version) { + return new GlslVersion(version, this.core); + } + + public GlslVersion withCore(boolean core) { + return new GlslVersion(this.version, core); + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslVisitor.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslVisitor.java new file mode 100644 index 00000000..d971205a --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslVisitor.java @@ -0,0 +1,4 @@ +package foundry.veil.impl.glsl.node; + +public interface GlslVisitor { +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/type/GlslSpecifiedType.java b/common/src/main/java/foundry/veil/impl/glsl/type/GlslSpecifiedType.java new file mode 100644 index 00000000..496f420d --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/type/GlslSpecifiedType.java @@ -0,0 +1,5 @@ +package foundry.veil.impl.glsl.type; + +public record GlslSpecifiedType(TypeSpecifier type, GlslTypeQualifier[] qualifiers) { + +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/type/GlslTypeQualifier.java b/common/src/main/java/foundry/veil/impl/glsl/type/GlslTypeQualifier.java new file mode 100644 index 00000000..079af84c --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/type/GlslTypeQualifier.java @@ -0,0 +1,69 @@ +package foundry.veil.impl.glsl.type; + +import foundry.veil.impl.glsl.node.GlslNode; +import org.jetbrains.annotations.Nullable; + +public interface GlslTypeQualifier { + + record Storage(Type type, String[] typeNames) implements GlslTypeQualifier { + + public Storage(Type type) { + this(type, new String[0]); + } + + public Storage(String[] typeNames) { + this(Type.SUBROUTINE, typeNames); + } + + public enum Type { + CONST, + IN, + OUT, + INOUT, + CENTROID, + PATCH, + SAMPLE, + UNIFORM, + BUFFER, + SHARED, + COHERENT, + VOLATILE, + RESTRICT, + READONLY, + WRITEONLY, + SUBROUTINE + } + } + + record Layout(String identifier, @Nullable GlslNode constantExpression) implements GlslTypeQualifier { + + public boolean shared() { + return "shared".equals(this.identifier); + } + + @Override + public @Nullable GlslNode constantExpression() { + return this.shared() ? null : this.constantExpression; + } + } + + enum Precision implements GlslTypeQualifier { + HIGH_PRECISION, + MEDIUM_PRECISION, + LOW_PRECISION + } + + enum Interpolation implements GlslTypeQualifier { + SMOOTH, + FLAT, + NOPERSPECTIVE + } + + enum Invariant implements GlslTypeQualifier { + INVARIANT + } + + enum Precise implements GlslTypeQualifier { + PRECISE + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/type/StructSpecifier.java b/common/src/main/java/foundry/veil/impl/glsl/type/StructSpecifier.java new file mode 100644 index 00000000..981b1f37 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/type/StructSpecifier.java @@ -0,0 +1,4 @@ +package foundry.veil.impl.glsl.type; + +public record StructSpecifier() { +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/type/TypeSpecifier.java b/common/src/main/java/foundry/veil/impl/glsl/type/TypeSpecifier.java new file mode 100644 index 00000000..9d738f98 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/type/TypeSpecifier.java @@ -0,0 +1,26 @@ +package foundry.veil.impl.glsl.type; + +import foundry.veil.impl.glsl.GlslLexer; + +public interface TypeSpecifier { + + static TypeSpecifier simple(GlslLexer.Token token) { + if (!token.type().isType()) { + throw new IllegalArgumentException("Invalid type: " + token); + } + return new SimpleType(token); + } + + static TypeSpecifier struct(StructSpecifier structSpecifier) { + return new Struct(structSpecifier); + } + + record SimpleType(GlslLexer.Token type) implements TypeSpecifier { + } + + record Struct(StructSpecifier structSpecifier) implements TypeSpecifier { + } + + record Name(String name) implements TypeSpecifier { + } +} diff --git a/common/src/test/java/GlslTest.java b/common/src/test/java/GlslTest.java new file mode 100644 index 00000000..9c14318b --- /dev/null +++ b/common/src/test/java/GlslTest.java @@ -0,0 +1,53 @@ +import foundry.veil.impl.glsl.GlslLexer; +import foundry.veil.impl.glsl.GlslParser; +import foundry.veil.impl.glsl.GlslSyntaxException; +import foundry.veil.impl.glsl.node.GlslTree; +import foundry.veil.impl.glsl.node.GlslVersion; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class GlslTest { + + @Test + void testLexer() throws GlslSyntaxException { + GlslLexer.Token[] tokens = GlslLexer.createTokens("float a = 4e2; // comment"); + Assertions.assertEquals("float a = 4e2 ;\n// comment\n", this.toString(tokens)); + } + + private String toString(GlslLexer.Token[] tokens) { + StringBuilder build = new StringBuilder(); + for (GlslLexer.Token token : tokens) { + build.append(token.value()); + if (token.type() == GlslLexer.TokenType.COMMENT || token.type() == GlslLexer.TokenType.SEMICOLON) { + build.append('\n'); + } else { + build.append(' '); + } + } + return build.toString(); + } + + @Test + void testParser() throws GlslSyntaxException { + GlslLexer.Token[] tokens = GlslLexer.createTokens("#version 330 core\nfloat a = 32.0;"); + GlslTree tree = GlslParser.parse(tokens); + Assertions.assertEquals(new GlslVersion(330, true), tree.getVersion()); + } + + @Test + void testPrecision() throws GlslSyntaxException { + GlslLexer.Token[] tokens = GlslLexer.createTokens(""" + uniform highp float h1; + highp float h2 = 2.3 * 4.7; // operation and result are highp + precision + mediump float m; + m = 3.7 * h1 * h2; // all operations are highp precision + h2 = m * h1; // operation is highp precision + m = h2 - h1; // operation is highp precision + h2 = m + m; // addition and result at mediump precision + void f(highp float p); + f(3.3); // 3.3 will be passed in at highp precision"""); + GlslTree tree = GlslParser.parse(tokens); + System.out.println(this.toString(tokens)); + } +} diff --git a/fabric/build.gradle b/fabric/build.gradle index 44f70d27..76a2d95e 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -67,10 +67,6 @@ dependencies { // modRuntimeOnly "maven.modrinth:iris:1.6.11+1.20.1" // modRuntimeOnly "maven.modrinth:replaymod:1.20.1-2.6.15" - api(include("org.antlr:antlr4-runtime:${antlr_version}")) - api(include("io.github.douira:glsl-transformer:${glsl_transformer_version}")) - api(include("io.github.douira:glsl-preprocessor:${glsl_preprocessor_version}")) - api(include("gg.moonflower:molang-compiler:${molang_compiler_version}")) api(include("io.github.spair:imgui-java-binding:$imgui_version")) diff --git a/forge/build.gradle b/forge/build.gradle index 8b15e9cc..3b4e5e27 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -109,11 +109,6 @@ dependencies { // runtimeOnly fg.deobf("maven.modrinth:embeddium:0.3.4+mc1.20.1") - shade "org.antlr:antlr4-runtime:$antlr_version" - shade "io.github.douira:glsl-transformer:$glsl_transformer_version" - shade("io.github.douira:glsl-preprocessor:${glsl_preprocessor_version}") { - transitive false - } shade "gg.moonflower:molang-compiler:$molang_compiler_version" shade "io.github.spair:imgui-java-binding:$imgui_version" diff --git a/gradle.properties b/gradle.properties index 7b9bce31..c8f004cd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -27,9 +27,6 @@ description=This is the Veil project.\nIt is a collection of tools and utilities minecraft_version_range=1.20.1 # Dependencies -antlr_version=4.13.1 -glsl_transformer_version=2.0.1 -glsl_preprocessor_version=1.0.0 molang_compiler_version=3.1.1.19 imgui_version=1.86.11 lwjgl_version=3.3.1 From 0ef903dd0c0d2ce8c2959e96d1898c0de8172455 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Mon, 26 Aug 2024 08:46:07 -0600 Subject: [PATCH 20/47] Disabled old shader editor --- common/src/main/java/foundry/veil/VeilClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/foundry/veil/VeilClient.java b/common/src/main/java/foundry/veil/VeilClient.java index 49243865..64150ccd 100644 --- a/common/src/main/java/foundry/veil/VeilClient.java +++ b/common/src/main/java/foundry/veil/VeilClient.java @@ -53,7 +53,7 @@ public static void init() { // debug editors editorManager.add(new DemoEditor()); editorManager.add(new PostEditor()); - editorManager.add(new ShaderEditor()); +// editorManager.add(new ShaderEditor()); editorManager.add(new TextureEditor()); editorManager.add(new OpenCLEditor()); editorManager.add(new DeviceInfoViewer()); From 17ac0899e634012e18a7c6f1b6dbfcc033d8c0a3 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Sat, 31 Aug 2024 10:55:46 -0600 Subject: [PATCH 21/47] WIP nodes --- .../foundry/veil/impl/glsl/GlslLexer.java | 103 +++-- .../foundry/veil/impl/glsl/GlslParser.java | 415 +++++++++++++++++- .../impl/glsl/node/DeclareFunctionNode.java | 14 - .../impl/glsl/node/GlslAssignableNode.java | 20 + .../veil/impl/glsl/node/GlslConstantNode.java | 6 + .../glsl/node/postfix/GlslFunctionNode.java | 13 + .../glsl/node/postfix/GlslGetArrayNode.java | 26 ++ .../glsl/node/postfix/GlslGetFieldNode.java | 26 ++ .../glsl/node/postfix/GlslGetVarNode.java | 21 + .../node/postfix/GlslInitializerNode.java | 22 + .../impl/glsl/node/postfix/GlslNewNode.java | 21 + .../glsl/node/postfix/GlslSetArrayNode.java | 24 + .../glsl/node/postfix/GlslSetFieldNode.java | 24 + .../glsl/node/postfix/GlslSetVarNode.java | 23 + .../node/postfix/GlslUnaryExpressionNode.java | 24 + .../node/primary/GlslBoolConstantNode.java | 18 + .../node/primary/GlslDoubleConstantNode.java | 18 + .../glsl/node/primary/GlslExpressionNode.java | 12 + .../node/primary/GlslFloatConstantNode.java | 18 + .../node/primary/GlslIntConstantNode.java | 18 + .../impl/glsl/node/primary/GlslIntFormat.java | 5 + .../node/primary/GlslUIntConstantNode.java | 18 + .../impl/glsl/type/GlslSpecifiedType.java | 6 + .../impl/glsl/type/GlslTypeQualifier.java | 22 +- .../veil/impl/glsl/type/TypeSpecifier.java | 8 +- 25 files changed, 859 insertions(+), 66 deletions(-) delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/DeclareFunctionNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/GlslAssignableNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/GlslConstantNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslFunctionNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetArrayNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetFieldNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetVarNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslInitializerNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslNewNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetArrayNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetFieldNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetVarNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslUnaryExpressionNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslBoolConstantNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslDoubleConstantNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslExpressionNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslFloatConstantNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslIntConstantNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslIntFormat.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslUIntConstantNode.java diff --git a/common/src/main/java/foundry/veil/impl/glsl/GlslLexer.java b/common/src/main/java/foundry/veil/impl/glsl/GlslLexer.java index c222c91e..cc88268d 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/GlslLexer.java +++ b/common/src/main/java/foundry/veil/impl/glsl/GlslLexer.java @@ -65,7 +65,9 @@ public String toString() { } private static final int FLAG_TYPE = 1; - private static final int FLAG_MODIFIER = 2; + private static final int FLAG_STORAGE_QUALIFIER = 2; + private static final int FLAG_CONSTANT_EXPRESSION = 4; + private static final int FLAG_ASSIGNMENT_OP = 8; public enum TokenType { DIRECTIVE("#.*"), @@ -73,7 +75,7 @@ public enum TokenType { COMMENT("\\/\\/.*"), MULTI_COMMENT("\\/\\*(?:.|[\\n\\r])*\\*\\/|\\/\\/(?:.*\\\\[\\n\\r]?)+[\\n\\r]?(?:.*)"), - CONST("const", FLAG_MODIFIER), + CONST("const", FLAG_STORAGE_QUALIFIER), BOOL("bool", FLAG_TYPE), FLOAT("float", FLAG_TYPE), INT("int", FLAG_TYPE), @@ -122,24 +124,24 @@ public enum TokenType { DMAT4X3("dmat4x3", FLAG_TYPE), DMAT4X4("dmat4x4", FLAG_TYPE), - CENTROID("centroid", FLAG_MODIFIER), - IN("in"), - OUT("out"), - INOUT("inout"), - UNIFORM("uniform"), - PATCH("patch"), - SAMPLE("sample"), - BUFFER("buffer"), - SHARED("shared"), - COHERENT("cohent"), - VOLATILE("volatile", FLAG_MODIFIER), - RESTRICT("restrict", FLAG_MODIFIER), - READONLY("readonly", FLAG_MODIFIER), - WRITEONLY("writeonly", FLAG_MODIFIER), - NOPERSPECTIVE("noperspective", FLAG_MODIFIER), - FLAT("flat", FLAG_MODIFIER), - SMOOTH("smooth", FLAG_MODIFIER), - LAYOUT("layout", FLAG_MODIFIER), + CENTROID("centroid", FLAG_STORAGE_QUALIFIER), + IN("in", FLAG_STORAGE_QUALIFIER), + OUT("out", FLAG_STORAGE_QUALIFIER), + INOUT("inout", FLAG_STORAGE_QUALIFIER), + UNIFORM("uniform", FLAG_STORAGE_QUALIFIER), + PATCH("patch", FLAG_STORAGE_QUALIFIER), + SAMPLE("sample", FLAG_STORAGE_QUALIFIER), + BUFFER("buffer", FLAG_STORAGE_QUALIFIER), + SHARED("shared", FLAG_STORAGE_QUALIFIER), + COHERENT("cohent", FLAG_STORAGE_QUALIFIER), + VOLATILE("volatile", FLAG_STORAGE_QUALIFIER), + RESTRICT("restrict", FLAG_STORAGE_QUALIFIER), + READONLY("readonly", FLAG_STORAGE_QUALIFIER), + WRITEONLY("writeonly", FLAG_STORAGE_QUALIFIER), + NOPERSPECTIVE("noperspective"), + FLAT("flat"), + SMOOTH("smooth"), + LAYOUT("layout"), ATOMIC_UINT("atomic_uint", FLAG_TYPE), @@ -235,15 +237,17 @@ public enum TokenType { SWITCH("switch"), CASE("case"), DEFAULT("default"), - SUBROUTINE("subroutine"), + SUBROUTINE("subroutine", FLAG_STORAGE_QUALIFIER), // TYPE_NAME ?? - FLOATING_CONSTANT("(?:(?:\\d+\\.\\d+|\\d+\\.|\\.\\d+)(?:[eE][+-]?\\d+)?(?:f|F|lf|LF)?)|(?:\\d+)(?:\\.|[eE][+-]?\\d+)(?:f|F|lf|LF)?"), - INTEGER_HEXADECIMAL_CONSTANT("0[xX][0-9a-fA-F]*[uU]?"), - INTEGER_OCTAL_CONSTANT("0[0-7]*[uU]?"), - INTEGER_DECIMAL_CONSTANT("[1-9][\\d]*[uU]?"), - // UINTCONSTANT - BOOL_CONSTANT("true|false"), + FLOATING_CONSTANT("(?:(?:\\d+\\.\\d+|\\d+\\.|\\.\\d+)(?:[eE][+-]?\\d+)?(?:f|F|lf|LF)?)|(?:\\d+)(?:\\.|[eE][+-]?\\d+)(?:f|F|lf|LF)?", FLAG_CONSTANT_EXPRESSION), + UINTEGER_HEXADECIMAL_CONSTANT("0[xX][0-9a-fA-F]*[uU]?", FLAG_CONSTANT_EXPRESSION), + UINTEGER_OCTAL_CONSTANT("0[0-7]*[uU]?", FLAG_CONSTANT_EXPRESSION), + UINTEGER_DECIMAL_CONSTANT("[1-9][\\d]*[uU]?", FLAG_CONSTANT_EXPRESSION), + INTEGER_HEXADECIMAL_CONSTANT("0[xX][0-9a-fA-F]*", FLAG_CONSTANT_EXPRESSION), + INTEGER_OCTAL_CONSTANT("0[0-7]*", FLAG_CONSTANT_EXPRESSION), + INTEGER_DECIMAL_CONSTANT("[1-9][\\d]*", FLAG_CONSTANT_EXPRESSION), + BOOL_CONSTANT("true|false", FLAG_CONSTANT_EXPRESSION), // FIELD_SELECTION LEFT_OP("<<"), @@ -316,5 +320,50 @@ public enum TokenType { public boolean isType() { return (this.flags & FLAG_TYPE) != 0; } + + public boolean isStorageQualifier() { + return (this.flags & FLAG_STORAGE_QUALIFIER) != 0; + } + + public boolean isLayoutQualifier() { + return this == LAYOUT; + } + + public boolean isPrecisionQualifier() { + return this == HIGH_PRECISION || this == MEDIUM_PRECISION || this == LOW_PRECISION; + } + + public boolean isInterpolationQualifier() { + return this == SMOOTH || this == FLAT || this == NOPERSPECTIVE; + } + + public boolean isInvariantQualifier() { + return this == INVARIANT; + } + + public boolean isPreciseQualifier() { + return this == PRECISE; + } + + public boolean isAssignmentOperator() { + return (this.flags & FLAG_ASSIGNMENT_OP) != 0; + } + + public boolean isUnaryOperator() { + return this == PLUS || this == DASH || this == BANG || this == TILDE; + } + + public boolean isUnaryExpression() { + if(this == INC_OP || this == DEC_OP || this.isUnaryOperator()) { + return true; + } + + // Primary Expression + if(this == IDENTIFIER || (this.flags & FLAG_CONSTANT_EXPRESSION) != 0 || this == LEFT_PAREN) { + return true; + } + + return this.isType(); + } } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java b/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java index fc527b6a..5122f768 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java +++ b/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java @@ -1,11 +1,19 @@ package foundry.veil.impl.glsl; -import foundry.veil.impl.glsl.node.DeclarationNode; +import foundry.veil.impl.glsl.node.GlslAssignableNode; import foundry.veil.impl.glsl.node.GlslNode; import foundry.veil.impl.glsl.node.GlslTree; import foundry.veil.impl.glsl.node.GlslVersion; +import foundry.veil.impl.glsl.node.postfix.*; +import foundry.veil.impl.glsl.node.primary.*; +import foundry.veil.impl.glsl.type.GlslSpecifiedType; +import foundry.veil.impl.glsl.type.GlslTypeQualifier; +import foundry.veil.impl.glsl.type.TypeSpecifier; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.List; + public final class GlslParser { private GlslParser() { @@ -30,47 +38,408 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio } } + reader.skipWhitespace(); while (reader.canRead()) { - GlslNode node = parseExpression(reader); + GlslNode node = parseCondition(reader); System.out.println(node); + reader.skipWhitespace(); } return new GlslTree(version); } + private static @Nullable GlslNode parseCondition(TokenReader reader) throws GlslSyntaxException { + if (!reader.canRead()) { + return null; + } + if (reader.peek().type().isType()) { + GlslSpecifiedType type = parseFullySpecifiedType(reader); + String name = reader.consume(GlslLexer.TokenType.IDENTIFIER).value(); + reader.consume(GlslLexer.TokenType.EQUAL); + GlslNode value = parseInitializer(reader); + return new GlslNewNode(type, name, value); + } + + return parseExpression(reader); + } + + private static GlslNode parseInitializer(TokenReader reader) throws GlslSyntaxException { + if (!reader.canRead()) { + throw reader.error("Expected initializer"); + } + + if (reader.peek().type() == GlslLexer.TokenType.LEFT_BRACE) { + reader.skip(); + List expressions = new ArrayList<>(); + expressions.add(parseInitializer(reader)); + while (reader.peek().type() == GlslLexer.TokenType.COMMA) { + reader.skip(); + if (!reader.canRead()) { + throw reader.error("Expected initializer or right brace"); + } + + if (reader.peek().type() == GlslLexer.TokenType.RIGHT_BRACE) { + break; + } + + expressions.add(parseInitializer(reader)); + } + reader.consume(GlslLexer.TokenType.RIGHT_BRACE); + return new GlslInitializerNode(expressions.toArray(GlslNode[]::new)); + } + + return parseAssignmentExpression(reader); + } + private static GlslNode parseExpression(TokenReader reader) throws GlslSyntaxException { - GlslLexer.Token token = reader.peek(); + return parseAssignmentExpression(reader); + } + + private static GlslNode parseAssignmentExpression(TokenReader reader) throws GlslSyntaxException { + if (!reader.canRead()) { + throw reader.error("Expected assignment expression"); + } - GlslNode left; + GlslNode expression = parseConditionalExpression(reader); + if (reader.canRead() && reader.peek().type().isAssignmentOperator()) { + if (!(expression instanceof GlslAssignableNode left)) { + throw reader.error("Invalid left-hand operand"); + } - // Declaration - if (token.type().isType()) { + GlslAssignableNode.Assignment assignment = switch (reader.peek().type()) { + case EQUAL -> GlslAssignableNode.Assignment.EQUAL; + case MUL_ASSIGN -> GlslAssignableNode.Assignment.MUL_ASSIGN; + case DIV_ASSIGN -> GlslAssignableNode.Assignment.DIV_ASSIGN; + case MOD_ASSIGN -> GlslAssignableNode.Assignment.MOD_ASSIGN; + case ADD_ASSIGN -> GlslAssignableNode.Assignment.ADD_ASSIGN; + case SUB_ASSIGN -> GlslAssignableNode.Assignment.SUB_ASSIGN; + case LEFT_ASSIGN -> GlslAssignableNode.Assignment.LEFT_ASSIGN; + case RIGHT_ASSIGN -> GlslAssignableNode.Assignment.RIGHT_ASSIGN; + case AND_ASSIGN -> GlslAssignableNode.Assignment.AND_ASSIGN; + case XOR_ASSIGN -> GlslAssignableNode.Assignment.XOR_ASSIGN; + case OR_ASSIGN -> GlslAssignableNode.Assignment.OR_ASSIGN; + default -> throw reader.error("Expected assignment operator"); + }; reader.skip(); - GlslLexer.Token name = reader.consume(GlslLexer.TokenType.IDENTIFIER); - left = new DeclarationNode(token, name.value()); + GlslNode value = parseAssignmentExpression(reader); + return left.toAssignment(assignment, value); + } + + return expression; + } + + private static GlslNode parseUnaryExpression(TokenReader reader) throws GlslSyntaxException { + if (!reader.canRead()) { + throw reader.error("Expected unary expression"); + } + + switch (reader.peek().type()) { + case INC_OP -> { + reader.skip(); + return new GlslUnaryExpressionNode(GlslUnaryExpressionNode.Operator.PRE_INCREMENT, parseUnaryExpression(reader)); + } + case DEC_OP -> { + reader.skip(); + return new GlslUnaryExpressionNode(GlslUnaryExpressionNode.Operator.PRE_DECREMENT, parseUnaryExpression(reader)); + } + case PLUS -> { + reader.skip(); + return new GlslUnaryExpressionNode(GlslUnaryExpressionNode.Operator.PLUS, parseUnaryExpression(reader)); + } + case DASH -> { + reader.skip(); + return new GlslUnaryExpressionNode(GlslUnaryExpressionNode.Operator.DASH, parseUnaryExpression(reader)); + } + case BANG -> { + reader.skip(); + return new GlslUnaryExpressionNode(GlslUnaryExpressionNode.Operator.BANG, parseUnaryExpression(reader)); + } + case TILDE -> { + reader.skip(); + return new GlslUnaryExpressionNode(GlslUnaryExpressionNode.Operator.TILDE, parseUnaryExpression(reader)); + } + } + + return parsePostfixExpression(reader); + } + + private static GlslNode parsePostfixExpression(TokenReader reader) throws GlslSyntaxException { + if (!reader.canRead()) { + throw reader.error("Expected postfix expression"); + } + + TypeSpecifier functionIdentifier; + String varName; + GlslNode postFixExpression; + + GlslLexer.TokenType type = reader.peek().type(); + if (type.isType()) { + functionIdentifier = parseTypeSpecifier(reader); + varName = null; + postFixExpression = null; + } else if (type == GlslLexer.TokenType.IDENTIFIER) { + functionIdentifier = null; + varName = reader.consume(GlslLexer.TokenType.IDENTIFIER).value(); + postFixExpression = null; } else { - throw reader.error("Invalid expression: " + token.value()); + varName = null; + functionIdentifier = null; + postFixExpression = switch (type) { + case UINTEGER_HEXADECIMAL_CONSTANT -> { + try { + int value = Integer.parseUnsignedInt(reader.consume(GlslLexer.TokenType.UINTEGER_HEXADECIMAL_CONSTANT).value(), 16); + yield new GlslUIntConstantNode(GlslIntFormat.HEXADECIMAL, value); + } catch (NumberFormatException e) { + throw reader.error(e.getMessage()); + } + } + case UINTEGER_OCTAL_CONSTANT -> { + try { + int value = Integer.parseUnsignedInt(reader.consume(GlslLexer.TokenType.UINTEGER_OCTAL_CONSTANT).value(), 8); + yield new GlslUIntConstantNode(GlslIntFormat.OCTAL, value); + } catch (NumberFormatException e) { + throw reader.error(e.getMessage()); + } + } + case UINTEGER_DECIMAL_CONSTANT -> { + try { + int value = Integer.parseUnsignedInt(reader.consume(GlslLexer.TokenType.UINTEGER_DECIMAL_CONSTANT).value()); + yield new GlslUIntConstantNode(GlslIntFormat.DECIMAL, value); + } catch (NumberFormatException e) { + throw reader.error(e.getMessage()); + } + } + case INTEGER_HEXADECIMAL_CONSTANT -> { + try { + int value = Integer.parseInt(reader.consume(GlslLexer.TokenType.INTEGER_HEXADECIMAL_CONSTANT).value(), 16); + yield new GlslIntConstantNode(GlslIntFormat.HEXADECIMAL, value); + } catch (NumberFormatException e) { + throw reader.error(e.getMessage()); + } + } + case INTEGER_OCTAL_CONSTANT -> { + try { + int value = Integer.parseInt(reader.consume(GlslLexer.TokenType.INTEGER_OCTAL_CONSTANT).value(), 8); + yield new GlslIntConstantNode(GlslIntFormat.OCTAL, value); + } catch (NumberFormatException e) { + throw reader.error(e.getMessage()); + } + } + case INTEGER_DECIMAL_CONSTANT -> { + try { + int value = Integer.parseInt(reader.consume(GlslLexer.TokenType.INTEGER_DECIMAL_CONSTANT).value()); + yield new GlslIntConstantNode(GlslIntFormat.DECIMAL, value); + } catch (NumberFormatException e) { + throw reader.error(e.getMessage()); + } + } + case FLOATING_CONSTANT -> { + try { + float value = Float.parseFloat(reader.consume(GlslLexer.TokenType.FLOATING_CONSTANT).value()); + yield new GlslFloatConstantNode(value); + } catch (NumberFormatException e) { + throw reader.error(e.getMessage()); + } + } + case BOOL_CONSTANT -> + new GlslBoolConstantNode("true".equalsIgnoreCase(reader.consume(GlslLexer.TokenType.BOOL_CONSTANT).value())); + case DOUBLE -> { + try { + double value = Double.parseDouble(reader.consume(GlslLexer.TokenType.DOUBLE).value()); + yield new GlslDoubleConstantNode(value); + } catch (NumberFormatException e) { + throw reader.error(e.getMessage()); + } + } + case LEFT_PAREN -> { + reader.skip(); + GlslNode expression = parseExpression(reader); + reader.consume(GlslLexer.TokenType.RIGHT_PAREN); + yield new GlslExpressionNode(expression); + } + default -> throw reader.error("Expected postfix expression"); + }; } - token = reader.peek(); - if (token.type() == GlslLexer.TokenType.SEMICOLON) { + if (functionIdentifier != null) { + reader.consume(GlslLexer.TokenType.LEFT_PAREN); reader.skip(); - return left; + if (!reader.canRead(2)) { + throw reader.error("Unexpected end of function definition"); + } + + if (reader.peek().type() == GlslLexer.TokenType.VOID) { + reader.skip(); + } else if (reader.peek().type() != GlslLexer.TokenType.RIGHT_PAREN) { + List params = new ArrayList<>(); + params.add(parseConditionalExpression(reader)); + while (reader.canRead() && reader.peek().type() == GlslLexer.TokenType.COMMA) { + reader.skip(); + params.add(parseConditionalExpression(reader)); + } + reader.consume(GlslLexer.TokenType.RIGHT_PAREN); + postFixExpression = new GlslFunctionNode(functionIdentifier, params.toArray(GlslNode[]::new)); + } else { + reader.consume(GlslLexer.TokenType.RIGHT_PAREN); + postFixExpression = new GlslFunctionNode(functionIdentifier, new GlslNode[0]); + } + } + if (varName != null) { + postFixExpression = new GlslGetVarNode(varName); + } + + if (reader.canRead()) { + GlslLexer.Token token = reader.peek(); + switch (token.type()) { + case LEFT_BRACKET -> { + reader.skip(); + GlslNode index = parseExpression(reader); + reader.consume(GlslLexer.TokenType.RIGHT_BRACKET); + return new GlslGetArrayNode(postFixExpression, index); + } + case DOT -> { + reader.skip(); + String fieldSelection = reader.consume(GlslLexer.TokenType.IDENTIFIER).value(); + return new GlslGetFieldNode(postFixExpression, fieldSelection); + } + case INC_OP -> { + reader.skip(); + return new GlslUnaryExpressionNode(GlslUnaryExpressionNode.Operator.POST_INCREMENT, postFixExpression); + } + case DEC_OP -> { + reader.skip(); + return new GlslUnaryExpressionNode(GlslUnaryExpressionNode.Operator.POST_DECREMENT, postFixExpression); + } + } + } + return postFixExpression; + } + + private static GlslNode parseConditionalExpression(TokenReader reader) throws GlslSyntaxException { + if (!reader.canRead()) { + throw reader.error("Expected expression"); + } + + GlslNode left = parseUnaryExpression(reader); + + return left; // TODO + } + + private static GlslNode parseMultiplicativeExpression(TokenReader reader) throws GlslSyntaxException { + if (!reader.canRead()) { + throw reader.error("Expected expression"); + } + + GlslNode left = parseUnaryExpression(reader); + + return left; // TODO + } + + private static GlslSpecifiedType parseFullySpecifiedType(TokenReader reader) throws GlslSyntaxException { + List typeQualifiers = new ArrayList<>(); + while (reader.canRead() && !reader.peek().type().isType()) { + GlslLexer.Token token = reader.peek(); + GlslLexer.TokenType type = token.type(); + + if (type.isStorageQualifier()) { + if (type == GlslLexer.TokenType.SUBROUTINE) { + GlslLexer.Token next = reader.peek(2); + if (next != null && next.type() == GlslLexer.TokenType.LEFT_PAREN) { + reader.skip(2); + List typeNames = new ArrayList<>(); + typeNames.add(reader.consume(GlslLexer.TokenType.IDENTIFIER).value()); + + while (reader.canRead() && reader.peek().type() == GlslLexer.TokenType.COMMA) { + reader.skip(); + typeNames.add(reader.consume(GlslLexer.TokenType.IDENTIFIER).value()); + } + + reader.consume(GlslLexer.TokenType.RIGHT_PAREN); + GlslTypeQualifier.storage(typeNames.toArray(String[]::new)); + } + } else { + GlslTypeQualifier.storage(new String[0]); + reader.skip(); + } + } else if (type.isLayoutQualifier()) { + reader.skip(); + reader.consume(GlslLexer.TokenType.LEFT_PAREN); + + typeQualifiers.add(parseLayout(reader)); + while (reader.canRead() && reader.peek().type() == GlslLexer.TokenType.COMMA) { + reader.skip(); + typeQualifiers.add(parseLayout(reader)); + } + + reader.consume(GlslLexer.TokenType.RIGHT_PAREN); + } else if (type.isPrecisionQualifier()) { + GlslTypeQualifier.Precision precision = switch (type) { + case HIGH_PRECISION -> GlslTypeQualifier.Precision.HIGH_PRECISION; + case MEDIUM_PRECISION -> GlslTypeQualifier.Precision.MEDIUM_PRECISION; + case LOW_PRECISION -> GlslTypeQualifier.Precision.LOW_PRECISION; + default -> throw new AssertionError(); + }; + typeQualifiers.add(precision); + reader.skip(); + } else if (type.isInterpolationQualifier()) { + GlslTypeQualifier.Interpolation interpolation = switch (type) { + case SMOOTH -> GlslTypeQualifier.Interpolation.SMOOTH; + case FLAT -> GlslTypeQualifier.Interpolation.FLAT; + case NOPERSPECTIVE -> GlslTypeQualifier.Interpolation.NOPERSPECTIVE; + default -> throw new AssertionError(); + }; + typeQualifiers.add(interpolation); + reader.skip(); + } else if (type.isInvariantQualifier()) { + typeQualifiers.add(GlslTypeQualifier.Invariant.INVARIANT); + reader.skip(); + } else if (type.isPreciseQualifier()) { + typeQualifiers.add(GlslTypeQualifier.Precise.PRECISE); + reader.skip(); + } else { + break; + } } + TypeSpecifier type = parseTypeSpecifier(reader); + return new GlslSpecifiedType(type, typeQualifiers.toArray(GlslTypeQualifier[]::new)); + } + + private static GlslTypeQualifier parseLayout(TokenReader reader) throws GlslSyntaxException { + if (!reader.canRead()) { + throw reader.error("Expected IDENTIFIER or SHARED"); + } + + GlslLexer.Token token = reader.peek(); switch (token.type()) { - case EQUAL -> { + case IDENTIFIER -> { reader.skip(); + String identifier = reader.consume(GlslLexer.TokenType.IDENTIFIER).value(); + if (reader.canConsume(GlslLexer.TokenType.EQUAL)) { + reader.skip(); + GlslNode expression = parseConditionalExpression(reader); + return GlslTypeQualifier.identifierLayout(identifier, expression); + } else { + return GlslTypeQualifier.identifierLayout(identifier, null); + } + } + case SHARED -> { + return GlslTypeQualifier.sharedLayout(); } + default -> throw reader.error("Expected IDENTIFIER or SHARED, got: " + token); } } - private static GlslLexer.Token parseTypeSpecifier(TokenReader reader) throws GlslSyntaxException { + private static TypeSpecifier parseTypeSpecifier(TokenReader reader) throws GlslSyntaxException { + if (!reader.canRead()) { + throw reader.error("Expected type specifier"); + } GlslLexer.Token token = reader.peek(); if (!token.type().isType()) { throw reader.error("Invalid type specifier: " + token.value()); } - return token; + reader.skip(); + return TypeSpecifier.simple(token); } private static class TokenReader { @@ -106,7 +475,7 @@ public int getCursorOffset() { return offset; } - public GlslLexer.Token peek() { + public @Nullable GlslLexer.Token peek() { return this.peek(0); } @@ -114,6 +483,10 @@ public GlslLexer.Token peek() { return this.cursor + amount < this.tokens.length ? this.tokens[this.cursor + amount] : null; } + public boolean canConsume(GlslLexer.TokenType token) { + return this.canRead() && this.peek().type() == token; + } + public GlslLexer.Token consume(GlslLexer.TokenType token) throws GlslSyntaxException { if (!this.canRead() || this.peek().type() != token) { throw this.error("Expected " + token); @@ -129,5 +502,15 @@ public GlslSyntaxException error(String error) { public void skip() { this.cursor++; } + + public void skip(int amount) { + this.cursor += amount; + } + + public void skipWhitespace() { + while (this.canRead() && this.peek().type() == GlslLexer.TokenType.COMMENT) { + this.skip(); + } + } } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/DeclareFunctionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/DeclareFunctionNode.java deleted file mode 100644 index 2b0f97b1..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/node/DeclareFunctionNode.java +++ /dev/null @@ -1,14 +0,0 @@ -package foundry.veil.impl.glsl.node; - -import foundry.veil.impl.glsl.GlslLexer; - -public class DeclareFunctionNode implements GlslNode { - - @Override - public void visit(GlslVisitor visitor) { - - } - - public record ParameterDeclaration() { - } -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslAssignableNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslAssignableNode.java new file mode 100644 index 00000000..9262c31c --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslAssignableNode.java @@ -0,0 +1,20 @@ +package foundry.veil.impl.glsl.node; + +public interface GlslAssignableNode extends GlslNode { + + GlslNode toAssignment(Assignment assignment, GlslNode value); + + enum Assignment { + EQUAL, + MUL_ASSIGN, + DIV_ASSIGN, + MOD_ASSIGN, + ADD_ASSIGN, + SUB_ASSIGN, + LEFT_ASSIGN, + RIGHT_ASSIGN, + AND_ASSIGN, + XOR_ASSIGN, + OR_ASSIGN, + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslConstantNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslConstantNode.java new file mode 100644 index 00000000..ac5ce723 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslConstantNode.java @@ -0,0 +1,6 @@ +package foundry.veil.impl.glsl.node; + +public interface GlslConstantNode extends GlslNode { + + Object rawValue(); +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslFunctionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslFunctionNode.java new file mode 100644 index 00000000..e74e9a5b --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslFunctionNode.java @@ -0,0 +1,13 @@ +package foundry.veil.impl.glsl.node.postfix; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.node.GlslVisitor; +import foundry.veil.impl.glsl.type.TypeSpecifier; + +public record GlslFunctionNode(TypeSpecifier typeSpecifier, GlslNode[] params) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetArrayNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetArrayNode.java new file mode 100644 index 00000000..284516cc --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetArrayNode.java @@ -0,0 +1,26 @@ +package foundry.veil.impl.glsl.node.postfix; + +import foundry.veil.impl.glsl.node.GlslAssignableNode; +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.node.GlslVisitor; + +import java.util.Collection; +import java.util.List; + +public record GlslGetArrayNode(GlslNode expression, GlslNode index) implements GlslAssignableNode { + + @Override + public void visit(GlslVisitor visitor) { + + } + + @Override + public Collection children() { + return List.of(this.expression, this.index); + } + + @Override + public GlslNode toAssignment(Assignment assignment, GlslNode value) { + return new GlslSetArrayNode(this.expression, this.index, assignment, value); + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetFieldNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetFieldNode.java new file mode 100644 index 00000000..2b6a2b94 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetFieldNode.java @@ -0,0 +1,26 @@ +package foundry.veil.impl.glsl.node.postfix; + +import foundry.veil.impl.glsl.node.GlslAssignableNode; +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.node.GlslVisitor; + +import java.util.Collection; +import java.util.Collections; + +public record GlslGetFieldNode(GlslNode expression, String fieldSelection) implements GlslAssignableNode { + + @Override + public void visit(GlslVisitor visitor) { + + } + + @Override + public Collection children() { + return Collections.singleton(this.expression); + } + + @Override + public GlslNode toAssignment(Assignment assignment, GlslNode value) { + return new GlslSetFieldNode(this.expression, this.fieldSelection, assignment, value); + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetVarNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetVarNode.java new file mode 100644 index 00000000..ed052e3b --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetVarNode.java @@ -0,0 +1,21 @@ +package foundry.veil.impl.glsl.node.postfix; + +import foundry.veil.impl.glsl.node.GlslAssignableNode; +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.node.GlslVisitor; + +import java.util.Collection; +import java.util.Collections; + +public record GlslGetVarNode(String name) implements GlslAssignableNode { + + @Override + public void visit(GlslVisitor visitor) { + + } + + @Override + public GlslNode toAssignment(Assignment assignment, GlslNode value) { + return new GlslSetVarNode(this.name, assignment, value); + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslInitializerNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslInitializerNode.java new file mode 100644 index 00000000..76c0fed2 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslInitializerNode.java @@ -0,0 +1,22 @@ +package foundry.veil.impl.glsl.node.postfix; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.node.GlslVisitor; +import foundry.veil.impl.glsl.node.primary.GlslExpressionNode; +import foundry.veil.impl.glsl.type.TypeSpecifier; + +import java.util.Arrays; +import java.util.Collection; + +public record GlslInitializerNode(GlslNode[] expressions) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } + + @Override + public Collection children() { + return Arrays.asList(this.expressions); + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslNewNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslNewNode.java new file mode 100644 index 00000000..087dc726 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslNewNode.java @@ -0,0 +1,21 @@ +package foundry.veil.impl.glsl.node.postfix; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.node.GlslVisitor; +import foundry.veil.impl.glsl.type.GlslSpecifiedType; + +import java.util.Collection; +import java.util.List; + +public record GlslNewNode(GlslSpecifiedType type, String name, GlslNode value) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } + + @Override + public Collection children() { + return List.of(this.value); + } +} \ No newline at end of file diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetArrayNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetArrayNode.java new file mode 100644 index 00000000..42a90ce1 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetArrayNode.java @@ -0,0 +1,24 @@ +package foundry.veil.impl.glsl.node.postfix; + +import foundry.veil.impl.glsl.node.GlslAssignableNode; +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.node.GlslVisitor; + +import java.util.Collection; +import java.util.List; + +public record GlslSetArrayNode(GlslNode expression, + GlslNode index, + GlslAssignableNode.Assignment assignment, + GlslNode values) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } + + @Override + public Collection children() { + return List.of(this.expression, this.index, this.values); + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetFieldNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetFieldNode.java new file mode 100644 index 00000000..bf536d58 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetFieldNode.java @@ -0,0 +1,24 @@ +package foundry.veil.impl.glsl.node.postfix; + +import foundry.veil.impl.glsl.node.GlslAssignableNode; +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.node.GlslVisitor; + +import java.util.Collection; +import java.util.List; + +public record GlslSetFieldNode(GlslNode expression, + String fieldSelection, + GlslAssignableNode.Assignment assignment, + GlslNode value) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } + + @Override + public Collection children() { + return List.of(this.expression, this.value); + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetVarNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetVarNode.java new file mode 100644 index 00000000..57d5ae38 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetVarNode.java @@ -0,0 +1,23 @@ +package foundry.veil.impl.glsl.node.postfix; + +import foundry.veil.impl.glsl.node.GlslAssignableNode; +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.node.GlslVisitor; + +import java.util.Collection; +import java.util.Collections; + +public record GlslSetVarNode(String name, + GlslAssignableNode.Assignment assignment, + GlslNode value) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } + + @Override + public Collection children() { + return Collections.singleton(this.value); + } +} \ No newline at end of file diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslUnaryExpressionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslUnaryExpressionNode.java new file mode 100644 index 00000000..eed916c9 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslUnaryExpressionNode.java @@ -0,0 +1,24 @@ +package foundry.veil.impl.glsl.node.postfix; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.node.GlslVisitor; + +import java.util.Collection; +import java.util.Collections; + +public record GlslUnaryExpressionNode(Operator operator, GlslNode expression) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } + + @Override + public Collection children() { + return Collections.singleton(this.expression); + } + + public enum Operator { + PRE_INCREMENT, PRE_DECREMENT, POST_INCREMENT, POST_DECREMENT, PLUS, DASH, BANG, TILDE + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslBoolConstantNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslBoolConstantNode.java new file mode 100644 index 00000000..30dc27a9 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslBoolConstantNode.java @@ -0,0 +1,18 @@ +package foundry.veil.impl.glsl.node.primary; + +import foundry.veil.impl.glsl.node.GlslConstantNode; +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.node.GlslVisitor; + +public record GlslBoolConstantNode(boolean value) implements GlslConstantNode { + + @Override + public void visit(GlslVisitor visitor) { + + } + + @Override + public Object rawValue() { + return this.value; + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslDoubleConstantNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslDoubleConstantNode.java new file mode 100644 index 00000000..ecafe140 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslDoubleConstantNode.java @@ -0,0 +1,18 @@ +package foundry.veil.impl.glsl.node.primary; + +import foundry.veil.impl.glsl.node.GlslConstantNode; +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.node.GlslVisitor; + +public record GlslDoubleConstantNode(double value) implements GlslConstantNode { + + @Override + public void visit(GlslVisitor visitor) { + + } + + @Override + public Object rawValue() { + return this.value; + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslExpressionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslExpressionNode.java new file mode 100644 index 00000000..8627b43f --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslExpressionNode.java @@ -0,0 +1,12 @@ +package foundry.veil.impl.glsl.node.primary; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.node.GlslVisitor; + +public record GlslExpressionNode(GlslNode node) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslFloatConstantNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslFloatConstantNode.java new file mode 100644 index 00000000..b4809093 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslFloatConstantNode.java @@ -0,0 +1,18 @@ +package foundry.veil.impl.glsl.node.primary; + +import foundry.veil.impl.glsl.node.GlslConstantNode; +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.node.GlslVisitor; + +public record GlslFloatConstantNode(float value) implements GlslConstantNode { + + @Override + public void visit(GlslVisitor visitor) { + + } + + @Override + public Object rawValue() { + return this.value; + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslIntConstantNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslIntConstantNode.java new file mode 100644 index 00000000..8a57cd3a --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslIntConstantNode.java @@ -0,0 +1,18 @@ +package foundry.veil.impl.glsl.node.primary; + +import foundry.veil.impl.glsl.node.GlslConstantNode; +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.node.GlslVisitor; + +public record GlslIntConstantNode(GlslIntFormat format, int value) implements GlslConstantNode { + + @Override + public void visit(GlslVisitor visitor) { + + } + + @Override + public Object rawValue() { + return this.value; + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslIntFormat.java b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslIntFormat.java new file mode 100644 index 00000000..543dd7ce --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslIntFormat.java @@ -0,0 +1,5 @@ +package foundry.veil.impl.glsl.node.primary; + +public enum GlslIntFormat { + HEXADECIMAL, OCTAL, DECIMAL +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslUIntConstantNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslUIntConstantNode.java new file mode 100644 index 00000000..02163013 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslUIntConstantNode.java @@ -0,0 +1,18 @@ +package foundry.veil.impl.glsl.node.primary; + +import foundry.veil.impl.glsl.node.GlslConstantNode; +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.node.GlslVisitor; + +public record GlslUIntConstantNode(GlslIntFormat format, int value) implements GlslConstantNode { + + @Override + public void visit(GlslVisitor visitor) { + + } + + @Override + public Object rawValue() { + return this.value; + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/type/GlslSpecifiedType.java b/common/src/main/java/foundry/veil/impl/glsl/type/GlslSpecifiedType.java index 496f420d..c59a29dc 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/type/GlslSpecifiedType.java +++ b/common/src/main/java/foundry/veil/impl/glsl/type/GlslSpecifiedType.java @@ -1,5 +1,11 @@ package foundry.veil.impl.glsl.type; +import java.util.Arrays; + public record GlslSpecifiedType(TypeSpecifier type, GlslTypeQualifier[] qualifiers) { + @Override + public String toString() { + return "GlslSpecifiedType[type=" + this.type + ", qualifiers=" + Arrays.toString(this.qualifiers); + } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/type/GlslTypeQualifier.java b/common/src/main/java/foundry/veil/impl/glsl/type/GlslTypeQualifier.java index 079af84c..0b4d1fae 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/type/GlslTypeQualifier.java +++ b/common/src/main/java/foundry/veil/impl/glsl/type/GlslTypeQualifier.java @@ -5,15 +5,23 @@ public interface GlslTypeQualifier { - record Storage(Type type, String[] typeNames) implements GlslTypeQualifier { + static GlslTypeQualifier storage(Storage.Type type) { + return new Storage(type, new String[0]); + } - public Storage(Type type) { - this(type, new String[0]); - } + static GlslTypeQualifier storage(String[] typeNames) { + return new Storage(Storage.Type.SUBROUTINE, typeNames); + } - public Storage(String[] typeNames) { - this(Type.SUBROUTINE, typeNames); - } + static GlslTypeQualifier identifierLayout(String identifier, @Nullable GlslNode constantExpression) { + return new Layout(identifier, constantExpression); + } + + static GlslTypeQualifier sharedLayout() { + return new Layout("shared", null); + } + + record Storage(Type type, String[] typeNames) implements GlslTypeQualifier { public enum Type { CONST, diff --git a/common/src/main/java/foundry/veil/impl/glsl/type/TypeSpecifier.java b/common/src/main/java/foundry/veil/impl/glsl/type/TypeSpecifier.java index 9d738f98..ff4f8b20 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/type/TypeSpecifier.java +++ b/common/src/main/java/foundry/veil/impl/glsl/type/TypeSpecifier.java @@ -8,14 +8,18 @@ static TypeSpecifier simple(GlslLexer.Token token) { if (!token.type().isType()) { throw new IllegalArgumentException("Invalid type: " + token); } - return new SimpleType(token); + return new Simple(token); } static TypeSpecifier struct(StructSpecifier structSpecifier) { return new Struct(structSpecifier); } - record SimpleType(GlslLexer.Token type) implements TypeSpecifier { + static TypeSpecifier named(String name) { + return new Name(name); + } + + record Simple(GlslLexer.Token type) implements TypeSpecifier { } record Struct(StructSpecifier structSpecifier) implements TypeSpecifier { From 3e21c32d5604bd3b08133628125ceb98d54ed13b Mon Sep 17 00:00:00 2001 From: RedstoneWizard08 <94275204+RedstoneWizard08@users.noreply.github.com> Date: Sat, 31 Aug 2024 10:05:39 -0700 Subject: [PATCH 22/47] Add Color#CODEC (#39) * Add Color#CODEC * oopsie --- common/src/main/java/foundry/veil/api/client/color/Color.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/src/main/java/foundry/veil/api/client/color/Color.java b/common/src/main/java/foundry/veil/api/client/color/Color.java index 3867a3c6..84f25052 100644 --- a/common/src/main/java/foundry/veil/api/client/color/Color.java +++ b/common/src/main/java/foundry/veil/api/client/color/Color.java @@ -2,10 +2,13 @@ import net.minecraft.util.Mth; +import com.mojang.serialization.Codec; + /** * A simple color class that can be used to represent a color in RGBA format with utility functions. */ public class Color { + public static Codec CODEC = Codec.INT.xmap(Color::new, Color::getRGB); public static final Color WHITE = new Color(255, 255, 255, 255); public static final Color BLACK = new Color(0, 0, 0, 255); From 931bfe3ce0d0335cb9a620c445b25fa730d30554 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Fri, 1 Nov 2024 11:18:12 -0600 Subject: [PATCH 23/47] Added dynamic cubemap texture init --- .../foundry/veil/api/client/color/Color.java | 3 +-- .../veil/api/client/color/ColorTheme.java | 2 -- .../veil/api/client/editor/Editor.java | 2 -- .../veil/api/client/editor/EditorManager.java | 1 - .../api/client/necromancer/Constraint.java | 2 -- .../veil/api/client/necromancer/Skin.java | 4 ---- .../client/render/shader/CompiledShader.java | 1 - .../processor/ShaderVersionProcessor.java | 1 - .../render/texture/DynamicCubemapTexture.java | 24 +++++++++++++++++++ .../api/client/ui/util/PoseStackAnimator.java | 6 ++--- .../api/client/util/DebugFrustumRenderer.java | 2 -- .../veil/api/quasar/data/EmitterSettings.java | 1 - .../api/quasar/data/ParticleEmitterData.java | 3 --- .../data/ParticleModuleTypeRegistry.java | 1 - .../api/quasar/data/QuasarParticleData.java | 1 - .../module/update/FaceVelocityModule.java | 1 - .../quasar/emitters/shape/EmitterShape.java | 10 -------- .../veil/api/quasar/particle/RenderData.java | 4 ++-- .../veil/api/quasar/particle/RenderStyle.java | 3 --- .../quasar/registry/EmitterShapeRegistry.java | 6 ----- .../quasar/registry/RenderStyleRegistry.java | 2 -- .../api/resource/type/McMetaResource.java | 2 +- .../api/resource/type/TextureResource.java | 2 +- .../api/resource/type/UnknownResource.java | 2 +- .../java/foundry/veil/api/util/CodecUtil.java | 7 ++---- .../veil/impl/client/editor/DemoEditor.java | 1 - .../veil/impl/client/editor/OpenCLEditor.java | 1 - .../veil/impl/client/editor/PostEditor.java | 1 - .../client/imgui/InactiveVeilImGuiImpl.java | 2 -- .../imgui/style/VeilImGuiStylesheet.java | 2 -- .../modifier/InputShaderModification.java | 2 -- .../modifier/SimpleShaderModification.java | 1 - .../veil/impl/compat/SodiumShaderMap.java | 5 ---- .../action/FramebufferEditAction.java | 1 - .../resource/loader/ShaderResourceLoader.java | 1 - .../client/deferred/LevelRendererMixin.java | 2 +- .../mixin/client/imgui/MouseHandlerMixin.java | 2 -- .../deferred/vanilla/LevelRendererMixin.java | 2 +- .../main/resources/veil.fabric.mixins.json | 8 +++---- .../ForgeVeilRegisterBlockLayerEvent.java | 3 --- .../deferred/vanilla/LevelRendererMixin.java | 2 +- 41 files changed, 42 insertions(+), 87 deletions(-) diff --git a/common/src/main/java/foundry/veil/api/client/color/Color.java b/common/src/main/java/foundry/veil/api/client/color/Color.java index 84f25052..75e99b0e 100644 --- a/common/src/main/java/foundry/veil/api/client/color/Color.java +++ b/common/src/main/java/foundry/veil/api/client/color/Color.java @@ -1,8 +1,7 @@ package foundry.veil.api.client.color; -import net.minecraft.util.Mth; - import com.mojang.serialization.Codec; +import net.minecraft.util.Mth; /** * A simple color class that can be used to represent a color in RGBA format with utility functions. diff --git a/common/src/main/java/foundry/veil/api/client/color/ColorTheme.java b/common/src/main/java/foundry/veil/api/client/color/ColorTheme.java index 14003473..f36a44eb 100644 --- a/common/src/main/java/foundry/veil/api/client/color/ColorTheme.java +++ b/common/src/main/java/foundry/veil/api/client/color/ColorTheme.java @@ -2,14 +2,12 @@ import foundry.veil.api.client.color.theme.IThemeProperty; import foundry.veil.api.client.tooltip.Tooltippable; -import net.minecraft.Util; import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.function.Supplier; /** * A color theme is a collection of colors. The colors can be accessed by name. Themes are intended to be used for color schemes. diff --git a/common/src/main/java/foundry/veil/api/client/editor/Editor.java b/common/src/main/java/foundry/veil/api/client/editor/Editor.java index 2321c272..0efedb62 100644 --- a/common/src/main/java/foundry/veil/api/client/editor/Editor.java +++ b/common/src/main/java/foundry/veil/api/client/editor/Editor.java @@ -1,8 +1,6 @@ package foundry.veil.api.client.editor; import foundry.veil.api.client.render.VeilRenderSystem; -import imgui.ImGui; -import imgui.type.ImBoolean; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import org.lwjgl.system.NativeResource; diff --git a/common/src/main/java/foundry/veil/api/client/editor/EditorManager.java b/common/src/main/java/foundry/veil/api/client/editor/EditorManager.java index 9009828e..42b7c830 100644 --- a/common/src/main/java/foundry/veil/api/client/editor/EditorManager.java +++ b/common/src/main/java/foundry/veil/api/client/editor/EditorManager.java @@ -1,7 +1,6 @@ package foundry.veil.api.client.editor; import foundry.veil.Veil; -import foundry.veil.api.client.imgui.VeilImGuiUtil; import foundry.veil.api.client.registry.VeilResourceEditorRegistry; import foundry.veil.api.resource.editor.ResourceFileEditor; import foundry.veil.api.util.CompositeReloadListener; diff --git a/common/src/main/java/foundry/veil/api/client/necromancer/Constraint.java b/common/src/main/java/foundry/veil/api/client/necromancer/Constraint.java index 846ddeea..d2e69fbf 100644 --- a/common/src/main/java/foundry/veil/api/client/necromancer/Constraint.java +++ b/common/src/main/java/foundry/veil/api/client/necromancer/Constraint.java @@ -1,8 +1,6 @@ package foundry.veil.api.client.necromancer; import com.mojang.blaze3d.vertex.PoseStack; -import foundry.veil.api.client.graveyard.skeleton.InterpolatedSkeleton; -import foundry.veil.api.client.graveyard.skeleton.InterpolatedSkeletonParent; import net.minecraft.client.renderer.MultiBufferSource; // W.I.P. replacement for graveyard diff --git a/common/src/main/java/foundry/veil/api/client/necromancer/Skin.java b/common/src/main/java/foundry/veil/api/client/necromancer/Skin.java index 571d1f0f..ea435358 100644 --- a/common/src/main/java/foundry/veil/api/client/necromancer/Skin.java +++ b/common/src/main/java/foundry/veil/api/client/necromancer/Skin.java @@ -5,10 +5,6 @@ import foundry.veil.Veil; import foundry.veil.api.client.render.VeilRenderSystem; import foundry.veil.api.client.render.VeilVertexFormat; -import foundry.veil.api.client.render.shader.VeilShaders; -import foundry.veil.ext.VertexBufferExtension; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.renderer.RenderType; import net.minecraft.resources.ResourceLocation; import java.util.HashMap; diff --git a/common/src/main/java/foundry/veil/api/client/render/shader/CompiledShader.java b/common/src/main/java/foundry/veil/api/client/render/shader/CompiledShader.java index 6e14ca67..ce4c6549 100644 --- a/common/src/main/java/foundry/veil/api/client/render/shader/CompiledShader.java +++ b/common/src/main/java/foundry/veil/api/client/render/shader/CompiledShader.java @@ -5,7 +5,6 @@ import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.Nullable; -import java.util.Map; import java.util.Set; /** diff --git a/common/src/main/java/foundry/veil/api/client/render/shader/processor/ShaderVersionProcessor.java b/common/src/main/java/foundry/veil/api/client/render/shader/processor/ShaderVersionProcessor.java index 07e6f374..8f86cd51 100644 --- a/common/src/main/java/foundry/veil/api/client/render/shader/processor/ShaderVersionProcessor.java +++ b/common/src/main/java/foundry/veil/api/client/render/shader/processor/ShaderVersionProcessor.java @@ -2,7 +2,6 @@ import org.jetbrains.annotations.NotNull; -import java.util.regex.Matcher; import java.util.regex.Pattern; /** diff --git a/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java b/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java index c47fb9ff..384cc2aa 100644 --- a/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java +++ b/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java @@ -10,9 +10,33 @@ import java.io.IOException; import static org.lwjgl.opengl.GL11C.*; +import static org.lwjgl.opengl.GL13C.GL_TEXTURE_CUBE_MAP_POSITIVE_X; public class DynamicCubemapTexture extends CubemapTexture { + public void init(int width, int height) { + try (NativeImage image = new NativeImage(width, height, true)) { + this.upload(image); + } + } + + public void upload(NativeImage image) { + this.bind(); + + int width = image.getWidth(); + int height = image.getHeight(); + RenderSystem.assertOnRenderThreadOrInit(); + NativeImageAccessor accessor = (NativeImageAccessor) (Object) image; + accessor.invokeCheckAllocated(); + GlStateManager._pixelStore(GL_UNPACK_ROW_LENGTH, 0); + GlStateManager._pixelStore(GL_UNPACK_SKIP_ROWS, 0); + GlStateManager._pixelStore(GL_UNPACK_SKIP_PIXELS, 0); + image.format().setUnpackPixelStoreState(); + for (int i = 0; i < 6; i++) { + GlStateManager._texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, width, height, image.format().glFormat(), GL_UNSIGNED_BYTE, accessor.getPixels()); + } + } + public void upload(Direction face, NativeImage image) { this.upload(getGlFace(face), image); } diff --git a/common/src/main/java/foundry/veil/api/client/ui/util/PoseStackAnimator.java b/common/src/main/java/foundry/veil/api/client/ui/util/PoseStackAnimator.java index 529a8376..79fc8f9f 100644 --- a/common/src/main/java/foundry/veil/api/client/ui/util/PoseStackAnimator.java +++ b/common/src/main/java/foundry/veil/api/client/ui/util/PoseStackAnimator.java @@ -1,11 +1,11 @@ package foundry.veil.api.client.ui.util; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.util.Mth; + import java.util.ArrayList; import java.util.List; import java.util.function.BiConsumer; -import java.util.function.Consumer; -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.util.Mth; /** * A utility class to manage and apply animations to a {@link PoseStack}. diff --git a/common/src/main/java/foundry/veil/api/client/util/DebugFrustumRenderer.java b/common/src/main/java/foundry/veil/api/client/util/DebugFrustumRenderer.java index 40aefef0..bc50e72d 100644 --- a/common/src/main/java/foundry/veil/api/client/util/DebugFrustumRenderer.java +++ b/common/src/main/java/foundry/veil/api/client/util/DebugFrustumRenderer.java @@ -2,8 +2,6 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; -import foundry.veil.api.client.render.MatrixStack; -import foundry.veil.api.client.render.VeilRenderBridge; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import org.jetbrains.annotations.NotNull; diff --git a/common/src/main/java/foundry/veil/api/quasar/data/EmitterSettings.java b/common/src/main/java/foundry/veil/api/quasar/data/EmitterSettings.java index 83d29549..1bc9addf 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/EmitterSettings.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/EmitterSettings.java @@ -4,7 +4,6 @@ import com.mojang.serialization.codecs.RecordCodecBuilder; import foundry.veil.api.util.CodecUtil; import net.minecraft.core.Holder; -import net.minecraft.util.ExtraCodecs; import java.util.List; diff --git a/common/src/main/java/foundry/veil/api/quasar/data/ParticleEmitterData.java b/common/src/main/java/foundry/veil/api/quasar/data/ParticleEmitterData.java index 0cc2c2bb..67b0fc84 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/ParticleEmitterData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/ParticleEmitterData.java @@ -2,14 +2,11 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import foundry.veil.api.util.CodecUtil; import net.minecraft.core.Holder; import net.minecraft.resources.RegistryFileCodec; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.Nullable; -import java.util.List; - /** * @param maxLifetime * @param loop Whether the emitter will loop. If true, the emitter will reset after maxLifetime ticks diff --git a/common/src/main/java/foundry/veil/api/quasar/data/ParticleModuleTypeRegistry.java b/common/src/main/java/foundry/veil/api/quasar/data/ParticleModuleTypeRegistry.java index 6670e828..b3d82728 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/ParticleModuleTypeRegistry.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/ParticleModuleTypeRegistry.java @@ -1,7 +1,6 @@ package foundry.veil.api.quasar.data; import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; import foundry.veil.Veil; import foundry.veil.api.quasar.data.module.ModuleType; import foundry.veil.api.quasar.data.module.ParticleModuleData; diff --git a/common/src/main/java/foundry/veil/api/quasar/data/QuasarParticleData.java b/common/src/main/java/foundry/veil/api/quasar/data/QuasarParticleData.java index d5a6d1dd..bcb86e6b 100644 --- a/common/src/main/java/foundry/veil/api/quasar/data/QuasarParticleData.java +++ b/common/src/main/java/foundry/veil/api/quasar/data/QuasarParticleData.java @@ -4,7 +4,6 @@ import com.mojang.serialization.codecs.RecordCodecBuilder; import foundry.veil.api.quasar.data.module.ParticleModuleData; import foundry.veil.api.quasar.particle.QuasarParticle; -import foundry.veil.api.quasar.particle.RenderData; import foundry.veil.api.quasar.particle.RenderStyle; import foundry.veil.api.quasar.particle.SpriteData; import foundry.veil.api.quasar.registry.RenderStyleRegistry; diff --git a/common/src/main/java/foundry/veil/api/quasar/emitters/module/update/FaceVelocityModule.java b/common/src/main/java/foundry/veil/api/quasar/emitters/module/update/FaceVelocityModule.java index da7fa95c..a02a5e2a 100644 --- a/common/src/main/java/foundry/veil/api/quasar/emitters/module/update/FaceVelocityModule.java +++ b/common/src/main/java/foundry/veil/api/quasar/emitters/module/update/FaceVelocityModule.java @@ -2,7 +2,6 @@ import foundry.veil.api.quasar.emitters.module.UpdateParticleModule; import foundry.veil.api.quasar.particle.QuasarParticle; -import foundry.veil.api.quasar.particle.RenderData; import foundry.veil.api.quasar.registry.RenderStyleRegistry; import net.minecraft.util.Mth; import org.joml.Vector3d; diff --git a/common/src/main/java/foundry/veil/api/quasar/emitters/shape/EmitterShape.java b/common/src/main/java/foundry/veil/api/quasar/emitters/shape/EmitterShape.java index 78c65491..a9bf3ab2 100644 --- a/common/src/main/java/foundry/veil/api/quasar/emitters/shape/EmitterShape.java +++ b/common/src/main/java/foundry/veil/api/quasar/emitters/shape/EmitterShape.java @@ -2,24 +2,14 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.datafixers.util.Either; import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; -import foundry.veil.Veil; import foundry.veil.api.quasar.registry.EmitterShapeRegistry; import foundry.veil.api.util.CodecUtil; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; import net.minecraft.util.RandomSource; import org.joml.Vector3d; import org.joml.Vector3dc; import org.joml.Vector3fc; -import java.util.Locale; -import java.util.Optional; -import java.util.function.Function; - public interface EmitterShape { Vector3d getPoint(RandomSource randomSource, Vector3fc dimensions, Vector3fc rotation, Vector3dc position, boolean fromSurface); diff --git a/common/src/main/java/foundry/veil/api/quasar/particle/RenderData.java b/common/src/main/java/foundry/veil/api/quasar/particle/RenderData.java index 80ce190b..67dd1d7e 100644 --- a/common/src/main/java/foundry/veil/api/quasar/particle/RenderData.java +++ b/common/src/main/java/foundry/veil/api/quasar/particle/RenderData.java @@ -17,8 +17,8 @@ import org.joml.*; import java.lang.Math; -import java.util.*; -import java.util.stream.Collectors; +import java.util.ArrayList; +import java.util.List; public class RenderData { diff --git a/common/src/main/java/foundry/veil/api/quasar/particle/RenderStyle.java b/common/src/main/java/foundry/veil/api/quasar/particle/RenderStyle.java index 08781f01..df614a45 100644 --- a/common/src/main/java/foundry/veil/api/quasar/particle/RenderStyle.java +++ b/common/src/main/java/foundry/veil/api/quasar/particle/RenderStyle.java @@ -3,7 +3,6 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; import foundry.veil.api.quasar.data.QuasarParticleData; import foundry.veil.api.quasar.registry.RenderStyleRegistry; import foundry.veil.api.util.CodecUtil; @@ -13,8 +12,6 @@ import org.joml.Vector3f; import org.joml.Vector3fc; -import java.util.Locale; - public interface RenderStyle { Codec CODEC = CodecUtil.registryOrLegacyCodec(RenderStyleRegistry.REGISTRY); diff --git a/common/src/main/java/foundry/veil/api/quasar/registry/EmitterShapeRegistry.java b/common/src/main/java/foundry/veil/api/quasar/registry/EmitterShapeRegistry.java index a5c70b42..5ad9388f 100644 --- a/common/src/main/java/foundry/veil/api/quasar/registry/EmitterShapeRegistry.java +++ b/common/src/main/java/foundry/veil/api/quasar/registry/EmitterShapeRegistry.java @@ -1,12 +1,6 @@ package foundry.veil.api.quasar.registry; -import com.mojang.serialization.Codec; import foundry.veil.Veil; -import foundry.veil.api.client.render.post.PostPipeline; -import foundry.veil.api.client.render.post.stage.BlitPostStage; -import foundry.veil.api.client.render.post.stage.CopyPostStage; -import foundry.veil.api.client.render.post.stage.DepthFunctionPostStage; -import foundry.veil.api.client.render.post.stage.MaskPostStage; import foundry.veil.api.quasar.emitters.shape.*; import foundry.veil.platform.registry.RegistrationProvider; import net.minecraft.core.Registry; diff --git a/common/src/main/java/foundry/veil/api/quasar/registry/RenderStyleRegistry.java b/common/src/main/java/foundry/veil/api/quasar/registry/RenderStyleRegistry.java index 8b9dfe90..26139299 100644 --- a/common/src/main/java/foundry/veil/api/quasar/registry/RenderStyleRegistry.java +++ b/common/src/main/java/foundry/veil/api/quasar/registry/RenderStyleRegistry.java @@ -1,8 +1,6 @@ package foundry.veil.api.quasar.registry; import foundry.veil.Veil; -import foundry.veil.api.quasar.emitters.shape.*; -import foundry.veil.api.quasar.particle.RenderData; import foundry.veil.api.quasar.particle.RenderStyle; import foundry.veil.platform.registry.RegistrationProvider; import net.minecraft.core.Registry; diff --git a/common/src/main/java/foundry/veil/api/resource/type/McMetaResource.java b/common/src/main/java/foundry/veil/api/resource/type/McMetaResource.java index 51e28206..7089781f 100644 --- a/common/src/main/java/foundry/veil/api/resource/type/McMetaResource.java +++ b/common/src/main/java/foundry/veil/api/resource/type/McMetaResource.java @@ -1,8 +1,8 @@ package foundry.veil.api.resource.type; -import foundry.veil.api.resource.VeilResourceInfo; import foundry.veil.api.resource.VeilResource; import foundry.veil.api.resource.VeilResourceAction; +import foundry.veil.api.resource.VeilResourceInfo; import net.minecraft.server.packs.resources.ResourceMetadata; import java.util.List; diff --git a/common/src/main/java/foundry/veil/api/resource/type/TextureResource.java b/common/src/main/java/foundry/veil/api/resource/type/TextureResource.java index 8c288b90..b39560cf 100644 --- a/common/src/main/java/foundry/veil/api/resource/type/TextureResource.java +++ b/common/src/main/java/foundry/veil/api/resource/type/TextureResource.java @@ -1,9 +1,9 @@ package foundry.veil.api.resource.type; import foundry.veil.api.client.imgui.VeilImGuiUtil; -import foundry.veil.api.resource.VeilResourceInfo; import foundry.veil.api.resource.VeilResource; import foundry.veil.api.resource.VeilResourceAction; +import foundry.veil.api.resource.VeilResourceInfo; import imgui.ImGui; import imgui.flag.ImGuiCol; import imgui.flag.ImGuiStyleVar; diff --git a/common/src/main/java/foundry/veil/api/resource/type/UnknownResource.java b/common/src/main/java/foundry/veil/api/resource/type/UnknownResource.java index d2d7972a..5f5413c8 100644 --- a/common/src/main/java/foundry/veil/api/resource/type/UnknownResource.java +++ b/common/src/main/java/foundry/veil/api/resource/type/UnknownResource.java @@ -1,8 +1,8 @@ package foundry.veil.api.resource.type; -import foundry.veil.api.resource.VeilResourceInfo; import foundry.veil.api.resource.VeilResource; import foundry.veil.api.resource.VeilResourceAction; +import foundry.veil.api.resource.VeilResourceInfo; import java.util.List; diff --git a/common/src/main/java/foundry/veil/api/util/CodecUtil.java b/common/src/main/java/foundry/veil/api/util/CodecUtil.java index d0513de1..51860b7a 100644 --- a/common/src/main/java/foundry/veil/api/util/CodecUtil.java +++ b/common/src/main/java/foundry/veil/api/util/CodecUtil.java @@ -1,11 +1,9 @@ package foundry.veil.api.util; import com.mojang.datafixers.util.Either; -import com.mojang.datafixers.util.Pair; -import com.mojang.serialization.*; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; import foundry.veil.Veil; -import foundry.veil.api.quasar.emitters.shape.EmitterShape; -import foundry.veil.api.quasar.registry.EmitterShapeRegistry; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; @@ -16,7 +14,6 @@ import java.util.Locale; import java.util.Optional; import java.util.function.Function; -import java.util.stream.Stream; public class CodecUtil { diff --git a/common/src/main/java/foundry/veil/impl/client/editor/DemoEditor.java b/common/src/main/java/foundry/veil/impl/client/editor/DemoEditor.java index 122742a1..3538f3a4 100644 --- a/common/src/main/java/foundry/veil/impl/client/editor/DemoEditor.java +++ b/common/src/main/java/foundry/veil/impl/client/editor/DemoEditor.java @@ -6,7 +6,6 @@ import imgui.type.ImBoolean; import net.minecraft.network.chat.Component; import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; @ApiStatus.Internal public class DemoEditor implements Editor { diff --git a/common/src/main/java/foundry/veil/impl/client/editor/OpenCLEditor.java b/common/src/main/java/foundry/veil/impl/client/editor/OpenCLEditor.java index 22d41549..e5373a99 100644 --- a/common/src/main/java/foundry/veil/impl/client/editor/OpenCLEditor.java +++ b/common/src/main/java/foundry/veil/impl/client/editor/OpenCLEditor.java @@ -9,7 +9,6 @@ import imgui.ImGui; import imgui.flag.ImGuiDataType; import imgui.type.ImInt; -import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.ApiStatus; diff --git a/common/src/main/java/foundry/veil/impl/client/editor/PostEditor.java b/common/src/main/java/foundry/veil/impl/client/editor/PostEditor.java index 31d76b08..5a4d5c5e 100644 --- a/common/src/main/java/foundry/veil/impl/client/editor/PostEditor.java +++ b/common/src/main/java/foundry/veil/impl/client/editor/PostEditor.java @@ -12,7 +12,6 @@ import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; import java.util.HashSet; import java.util.Set; diff --git a/common/src/main/java/foundry/veil/impl/client/imgui/InactiveVeilImGuiImpl.java b/common/src/main/java/foundry/veil/impl/client/imgui/InactiveVeilImGuiImpl.java index 008c28e8..c0d2537d 100644 --- a/common/src/main/java/foundry/veil/impl/client/imgui/InactiveVeilImGuiImpl.java +++ b/common/src/main/java/foundry/veil/impl/client/imgui/InactiveVeilImGuiImpl.java @@ -1,10 +1,8 @@ package foundry.veil.impl.client.imgui; import foundry.veil.api.client.imgui.VeilImGui; -import imgui.ImFont; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; import java.util.function.ObjIntConsumer; diff --git a/common/src/main/java/foundry/veil/impl/client/imgui/style/VeilImGuiStylesheet.java b/common/src/main/java/foundry/veil/impl/client/imgui/style/VeilImGuiStylesheet.java index d78cc926..8bf2dca2 100644 --- a/common/src/main/java/foundry/veil/impl/client/imgui/style/VeilImGuiStylesheet.java +++ b/common/src/main/java/foundry/veil/impl/client/imgui/style/VeilImGuiStylesheet.java @@ -6,8 +6,6 @@ import imgui.flag.ImGuiCol; import imgui.flag.ImGuiDir; -import java.io.IOException; - public class VeilImGuiStylesheet { public static void initStyles() { diff --git a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/InputShaderModification.java b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/InputShaderModification.java index 9a76ee2a..c8ff68f2 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/InputShaderModification.java +++ b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/InputShaderModification.java @@ -7,8 +7,6 @@ import org.jetbrains.annotations.ApiStatus; import java.io.IOException; -import java.util.function.Supplier; -import java.util.regex.Matcher; @ApiStatus.Internal public class InputShaderModification implements ShaderModification { diff --git a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/SimpleShaderModification.java b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/SimpleShaderModification.java index e2075231..4c3dcd6b 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/SimpleShaderModification.java +++ b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/SimpleShaderModification.java @@ -16,7 +16,6 @@ import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.util.Objects; import java.util.regex.Matcher; @ApiStatus.Internal diff --git a/common/src/main/java/foundry/veil/impl/compat/SodiumShaderMap.java b/common/src/main/java/foundry/veil/impl/compat/SodiumShaderMap.java index 7beeff24..f24263c6 100644 --- a/common/src/main/java/foundry/veil/impl/compat/SodiumShaderMap.java +++ b/common/src/main/java/foundry/veil/impl/compat/SodiumShaderMap.java @@ -1,16 +1,11 @@ package foundry.veil.impl.compat; import foundry.veil.Veil; -import it.unimi.dsi.fastutil.ints.IntSet; -import it.unimi.dsi.fastutil.ints.IntSets; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntMaps; -import net.minecraft.client.renderer.ShaderInstance; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.ApiStatus; -import java.util.Collections; -import java.util.Set; import java.util.function.Supplier; @ApiStatus.Internal diff --git a/common/src/main/java/foundry/veil/impl/resource/action/FramebufferEditAction.java b/common/src/main/java/foundry/veil/impl/resource/action/FramebufferEditAction.java index d3cbc936..8fb83a16 100644 --- a/common/src/main/java/foundry/veil/impl/resource/action/FramebufferEditAction.java +++ b/common/src/main/java/foundry/veil/impl/resource/action/FramebufferEditAction.java @@ -6,7 +6,6 @@ import foundry.veil.api.resource.type.FramebufferResource; import net.minecraft.network.chat.Component; -import java.util.Comparator; import java.util.OptionalInt; public class FramebufferEditAction implements VeilResourceAction { diff --git a/common/src/main/java/foundry/veil/impl/resource/loader/ShaderResourceLoader.java b/common/src/main/java/foundry/veil/impl/resource/loader/ShaderResourceLoader.java index 9e769bb7..804af7a8 100644 --- a/common/src/main/java/foundry/veil/impl/resource/loader/ShaderResourceLoader.java +++ b/common/src/main/java/foundry/veil/impl/resource/loader/ShaderResourceLoader.java @@ -7,7 +7,6 @@ import foundry.veil.api.resource.VeilResourceManager; import foundry.veil.api.resource.type.VeilShaderDefinitionResource; import foundry.veil.api.resource.type.VeilShaderFileResource; -import foundry.veil.api.resource.type.VeilShaderResource; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.resources.ResourceProvider; diff --git a/common/src/main/java/foundry/veil/mixin/client/deferred/LevelRendererMixin.java b/common/src/main/java/foundry/veil/mixin/client/deferred/LevelRendererMixin.java index 9e23ac26..da89564b 100644 --- a/common/src/main/java/foundry/veil/mixin/client/deferred/LevelRendererMixin.java +++ b/common/src/main/java/foundry/veil/mixin/client/deferred/LevelRendererMixin.java @@ -4,8 +4,8 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import foundry.veil.api.client.render.VeilRenderSystem; -import foundry.veil.impl.client.render.shader.VeilVanillaShaders; import foundry.veil.impl.client.render.deferred.DeferredShaderStateCache; +import foundry.veil.impl.client.render.shader.VeilVanillaShaders; import net.minecraft.client.Camera; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.LevelRenderer; diff --git a/common/src/main/java/foundry/veil/mixin/client/imgui/MouseHandlerMixin.java b/common/src/main/java/foundry/veil/mixin/client/imgui/MouseHandlerMixin.java index 1b81e436..e3f65a22 100644 --- a/common/src/main/java/foundry/veil/mixin/client/imgui/MouseHandlerMixin.java +++ b/common/src/main/java/foundry/veil/mixin/client/imgui/MouseHandlerMixin.java @@ -1,8 +1,6 @@ package foundry.veil.mixin.client.imgui; import foundry.veil.Veil; -import foundry.veil.api.client.imgui.VeilImGui; -import foundry.veil.impl.client.imgui.VeilImGuiImpl; import net.minecraft.client.MouseHandler; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; diff --git a/fabric/src/main/java/foundry/veil/fabric/mixin/client/deferred/vanilla/LevelRendererMixin.java b/fabric/src/main/java/foundry/veil/fabric/mixin/client/deferred/vanilla/LevelRendererMixin.java index d5a65534..462a4b38 100644 --- a/fabric/src/main/java/foundry/veil/fabric/mixin/client/deferred/vanilla/LevelRendererMixin.java +++ b/fabric/src/main/java/foundry/veil/fabric/mixin/client/deferred/vanilla/LevelRendererMixin.java @@ -3,8 +3,8 @@ import com.mojang.blaze3d.shaders.Uniform; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; -import foundry.veil.impl.client.render.shader.VeilVanillaShaders; import foundry.veil.impl.client.render.deferred.DeferredShaderStateCache; +import foundry.veil.impl.client.render.shader.VeilVanillaShaders; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.ShaderInstance; diff --git a/fabric/src/main/resources/veil.fabric.mixins.json b/fabric/src/main/resources/veil.fabric.mixins.json index 50d3582b..87c7ec8b 100644 --- a/fabric/src/main/resources/veil.fabric.mixins.json +++ b/fabric/src/main/resources/veil.fabric.mixins.json @@ -21,12 +21,12 @@ "client.stage.LevelRendererMixin", "client.stage.sodium.SodiumWorldRendererMixin", "client.stage.vanilla.LevelRendererMixin", - "compat.sodium.SodiumWorldRendererAccessor", - "compat.sodium.ShaderChunkRendererAccessor", - "compat.sodium.RenderSectionManagerAccessor", "compat.iris.NewWorldRenderingPipelineAccessor", "compat.replaymod.PipelineMixin", - "compat.sodium.ShaderLoaderMixin" + "compat.sodium.RenderSectionManagerAccessor", + "compat.sodium.ShaderChunkRendererAccessor", + "compat.sodium.ShaderLoaderMixin", + "compat.sodium.SodiumWorldRendererAccessor" ], "injectors": { "defaultRequire": 1 diff --git a/forge/src/main/java/foundry/veil/forge/event/ForgeVeilRegisterBlockLayerEvent.java b/forge/src/main/java/foundry/veil/forge/event/ForgeVeilRegisterBlockLayerEvent.java index 6540f903..ab08c79c 100644 --- a/forge/src/main/java/foundry/veil/forge/event/ForgeVeilRegisterBlockLayerEvent.java +++ b/forge/src/main/java/foundry/veil/forge/event/ForgeVeilRegisterBlockLayerEvent.java @@ -2,13 +2,10 @@ import foundry.veil.api.event.VeilRegisterBlockLayerEvent; import foundry.veil.api.event.VeilRegisterFixedBuffersEvent; -import foundry.veil.api.event.VeilRenderLevelStageEvent; import net.minecraft.client.renderer.RenderType; import net.minecraftforge.eventbus.api.Event; import net.minecraftforge.fml.event.IModBusEvent; -import java.util.function.Consumer; - /** *

Fired to register block layers.

*

Note: This does not add fixed buffers automatically. To do that, also register the render type with {@link VeilRegisterFixedBuffersEvent}

diff --git a/forge/src/main/java/foundry/veil/forge/mixin/client/deferred/vanilla/LevelRendererMixin.java b/forge/src/main/java/foundry/veil/forge/mixin/client/deferred/vanilla/LevelRendererMixin.java index 51cc5736..5153bf29 100644 --- a/forge/src/main/java/foundry/veil/forge/mixin/client/deferred/vanilla/LevelRendererMixin.java +++ b/forge/src/main/java/foundry/veil/forge/mixin/client/deferred/vanilla/LevelRendererMixin.java @@ -3,8 +3,8 @@ import com.mojang.blaze3d.shaders.Uniform; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; -import foundry.veil.impl.client.render.shader.VeilVanillaShaders; import foundry.veil.impl.client.render.deferred.DeferredShaderStateCache; +import foundry.veil.impl.client.render.shader.VeilVanillaShaders; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.ShaderInstance; From 9f7911c4af8d81c54d58b8bdaadd2086b88e77a3 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Fri, 1 Nov 2024 13:49:32 -0600 Subject: [PATCH 24/47] Documentation --- .../client/render/texture/CubemapTexture.java | 11 +++++ .../render/texture/DynamicCubemapTexture.java | 48 +++++++++++++++++-- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/common/src/main/java/foundry/veil/api/client/render/texture/CubemapTexture.java b/common/src/main/java/foundry/veil/api/client/render/texture/CubemapTexture.java index 1b09ee9f..6b11500d 100644 --- a/common/src/main/java/foundry/veil/api/client/render/texture/CubemapTexture.java +++ b/common/src/main/java/foundry/veil/api/client/render/texture/CubemapTexture.java @@ -8,8 +8,19 @@ import static org.lwjgl.opengl.GL11C.*; import static org.lwjgl.opengl.GL13C.*; +/** + * {@link AbstractTexture} implementation for using a cubemap texture. + * + * @author Ocelot + */ public abstract class CubemapTexture extends AbstractTexture { + /** + * Converts the {@link Direction} value to the correct GL cubemap enum. + * + * @param direction The direction to convert + * @return The OpenGL enum + */ public static int getGlFace(Direction direction) { return switch (direction) { case DOWN -> GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; diff --git a/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java b/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java index 384cc2aa..aa09eb27 100644 --- a/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java +++ b/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java @@ -10,18 +10,40 @@ import java.io.IOException; import static org.lwjgl.opengl.GL11C.*; +import static org.lwjgl.opengl.GL12C.*; import static org.lwjgl.opengl.GL13C.GL_TEXTURE_CUBE_MAP_POSITIVE_X; +import static org.lwjgl.opengl.GL14C.GL_TEXTURE_LOD_BIAS; +/** + * Dynamic implementation of {@link CubemapTexture}. Must be initialized before it can be used. + * + * @author Ocelot + */ public class DynamicCubemapTexture extends CubemapTexture { + /** + * Initializes each face to the same size white texture. + * + * @param width The width of each face + * @param height The height of each face + */ public void init(int width, int height) { try (NativeImage image = new NativeImage(width, height, true)) { this.upload(image); } } + /** + * Uploads the same image to all faces of the cubemap. + * + * @param image The image to upload + */ public void upload(NativeImage image) { this.bind(); + GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); + GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); + GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, 0.0F); int width = image.getWidth(); int height = image.getHeight(); @@ -31,18 +53,35 @@ public void upload(NativeImage image) { GlStateManager._pixelStore(GL_UNPACK_ROW_LENGTH, 0); GlStateManager._pixelStore(GL_UNPACK_SKIP_ROWS, 0); GlStateManager._pixelStore(GL_UNPACK_SKIP_PIXELS, 0); - image.format().setUnpackPixelStoreState(); + NativeImage.Format format = image.format(); + format.setUnpackPixelStoreState(); for (int i = 0; i < 6; i++) { - GlStateManager._texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, width, height, image.format().glFormat(), GL_UNSIGNED_BYTE, accessor.getPixels()); + GlStateManager._texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, width, height, format.glFormat(), GL_UNSIGNED_BYTE, accessor.getPixels()); } } + /** + * Uploads the specified image to the specified face. + * + * @param face The face to upload to + * @param image The image to upload + */ public void upload(Direction face, NativeImage image) { this.upload(getGlFace(face), image); } + /** + * Uploads the specified image to the specified face. + * + * @param face The face to upload to + * @param image The image to upload + */ public void upload(int face, NativeImage image) { this.bind(); + GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); + GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); + GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, 0.0F); int width = image.getWidth(); int height = image.getHeight(); @@ -52,8 +91,9 @@ public void upload(int face, NativeImage image) { GlStateManager._pixelStore(GL_UNPACK_ROW_LENGTH, 0); GlStateManager._pixelStore(GL_UNPACK_SKIP_ROWS, 0); GlStateManager._pixelStore(GL_UNPACK_SKIP_PIXELS, 0); - image.format().setUnpackPixelStoreState(); - GlStateManager._texSubImage2D(face, 0, 0, 0, width, height, image.format().glFormat(), GL_UNSIGNED_BYTE, accessor.getPixels()); + NativeImage.Format format = image.format(); + format.setUnpackPixelStoreState(); + GlStateManager._texSubImage2D(face, 0, 0, 0, width, height, format.glFormat(), GL_UNSIGNED_BYTE, accessor.getPixels()); } @Override From ba822a6e911395794ea6d15e9c354f31ab12ca26 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Sat, 2 Nov 2024 13:05:11 -0600 Subject: [PATCH 25/47] Fixed issue with cubemap texture --- .../render/framebuffer/AdvancedFbo.java | 70 +++++++------------ .../framebuffer/AdvancedFboAttachment.java | 10 --- .../AdvancedFboMutableTextureAttachment.java | 40 ++++------- .../AdvancedFboRenderAttachment.java | 10 --- .../AdvancedFboTextureAttachment.java | 10 --- .../render/texture/DynamicCubemapTexture.java | 39 +++++++---- .../impl/client/render/AdvancedFboImpl.java | 5 +- .../pipeline/VeilFirstPersonRenderer.java | 2 +- .../wrapper/VanillaAdvancedFboWrapper.java | 10 --- 9 files changed, 70 insertions(+), 126 deletions(-) diff --git a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java index 004d9c8e..ddb514ac 100644 --- a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java +++ b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java @@ -327,13 +327,11 @@ default AdvancedFboTextureAttachment getColorTextureAttachment(int attachment) { * * @param attachment The attachment to modify * @param textureId The id of the texture to draw into - * @param width The width of the texture - * @param height The height of the texture * @throws IllegalArgumentException If there is no attachment in the specified attachment * slot, or it is not an {@link AdvancedFboMutableTextureAttachment} */ - default void setColorAttachmentTexture(int attachment, int textureId, int width, int height) { - this.setColorAttachmentTexture(attachment, GL_TEXTURE_2D, textureId, width, height); + default void setColorAttachmentTexture(int attachment, int textureId) { + this.setColorAttachmentTexture(attachment, GL_TEXTURE_2D, textureId); } /** @@ -341,19 +339,17 @@ default void setColorAttachmentTexture(int attachment, int textureId, int width, * If the attachment is not known to be an {@link AdvancedFboMutableTextureAttachment}, * use {@link #isMutableColorTextureAttachment(int)} before calling this. * - * @param attachment The attachment to modify - * @param textureTarget The texture target to upload - * @param textureId The id of the texture to draw into - * @param width The width of the texture - * @param height The height of the texture + * @param attachment The attachment to modify + * @param textureId The id of the texture to draw into + * @param layer The texture layer to attach. For cubemaps this is the attachment face * @throws IllegalArgumentException If there is no attachment in the specified attachment * slot, or it is not an {@link AdvancedFboMutableTextureAttachment} */ - default void setColorAttachmentTexture(int attachment, int textureTarget, int textureId, int width, int height) { + default void setColorAttachmentTexture(int attachment, int textureId, int layer) { AdvancedFboAttachment advancedFboAttachment = this.getColorAttachment(attachment); Validate.isTrue(this.isMutableColorTextureAttachment(attachment), "Color attachment " + attachment + " must be a mutable texture attachment to modify texture information."); AdvancedFboMutableTextureAttachment mutableTextureAttachment = (AdvancedFboMutableTextureAttachment) advancedFboAttachment; - if (mutableTextureAttachment.setTexture(textureTarget, textureId, width, height)) { + if (mutableTextureAttachment.setTexture(textureId, layer)) { this.bind(false); mutableTextureAttachment.attach(attachment); AdvancedFbo.unbind(); @@ -424,13 +420,11 @@ default AdvancedFboTextureAttachment getDepthTextureAttachment() { * use {@link #isMutableColorTextureAttachment(int)} before calling this. * * @param textureId The id of the texture to draw into - * @param width The width of the texture - * @param height The height of the texture * @throws IllegalArgumentException If there is no attachment in the specified attachment * slot, or it is not an {@link AdvancedFboMutableTextureAttachment} */ - default void setDepthAttachmentTexture(int textureId, int width, int height) { - this.setDepthAttachmentTexture(GL_TEXTURE_2D, textureId, width, height); + default void setDepthAttachmentTexture(int textureId) { + this.setDepthAttachmentTexture(GL_TEXTURE_2D, textureId); } /** @@ -438,18 +432,16 @@ default void setDepthAttachmentTexture(int textureId, int width, int height) { * If the attachment is not known to be an {@link AdvancedFboMutableTextureAttachment}, * use {@link #isMutableColorTextureAttachment(int)} before calling this. * - * @param textureTarget The texture target to upload - * @param textureId The id of the texture to draw into - * @param width The width of the texture - * @param height The height of the texture + * @param textureId The id of the texture to draw into + * @param layer The texture layer to attach. For cubemaps this is the attachment face * @throws IllegalArgumentException If there is no attachment in the specified attachment * slot, or it is not an {@link AdvancedFboMutableTextureAttachment} */ - default void setDepthAttachmentTexture(int textureTarget, int textureId, int width, int height) { + default void setDepthAttachmentTexture(int textureId, int layer) { AdvancedFboAttachment advancedFboAttachment = this.getDepthAttachment(); Validate.isTrue(this.isDepthMutableTextureAttachment(), "Depth attachment must be a mutable texture attachment to modify texture information."); AdvancedFboMutableTextureAttachment mutableTextureAttachment = (AdvancedFboMutableTextureAttachment) advancedFboAttachment; - if (mutableTextureAttachment.setTexture(textureTarget, textureId, width, height)) { + if (mutableTextureAttachment.setTexture(textureId, layer)) { this.bind(false); mutableTextureAttachment.attach(0); AdvancedFbo.unbind(); @@ -677,26 +669,22 @@ public Builder addColorBuffer(AdvancedFboAttachment attachment) { } /** - * Adds the specified texture as a 2D texture attachment. + * Adds the specified texture as a texture attachment. * * @param textureId The id of the texture to add - * @param width The width of the texture - * @param height The height of the texture */ - public Builder addColorTextureWrapper(int textureId, int width, int height) { - return this.addColorTextureWrapper(textureId, GL_TEXTURE_2D, width, height); + public Builder addColorTextureWrapper(int textureId) { + return this.addColorTextureWrapper(textureId, 0); } /** * Adds the specified texture as a texture attachment. * - * @param textureId The id of the texture to add - * @param textureTarget The target to use for the texture - * @param width The width of the texture - * @param height The height of the texture + * @param textureId The id of the texture to add + * @param layer The layer of the texture to use */ - public Builder addColorTextureWrapper(int textureId, int textureTarget, int width, int height) { - return this.addColorBuffer(new AdvancedFboMutableTextureAttachment(textureId, textureTarget, GL_COLOR_ATTACHMENT0, width, height)); + public Builder addColorTextureWrapper(int textureId, int layer) { + return this.addColorBuffer(new AdvancedFboMutableTextureAttachment(GL_COLOR_ATTACHMENT0, textureId, layer)); } /** @@ -780,26 +768,22 @@ public Builder setDepthBuffer(@Nullable AdvancedFboAttachment attachment) { } /** - * Adds the specified texture as a 2D texture attachment. + * Adds the specified texture as a texture attachment. * * @param textureId The id of the texture to add - * @param width The width of the texture - * @param height The height of the texture */ - public Builder setDepthTextureWrapper(int textureId, int width, int height) { - return this.setDepthTextureWrapper(textureId, GL_TEXTURE_2D, width, height); + public Builder setDepthTextureWrapper(int textureId) { + return this.setDepthTextureWrapper(textureId, 0); } /** * Adds the specified texture as a texture attachment. * - * @param textureId The id of the texture to add - * @param textureTarget The target to use for the texture - * @param width The width of the texture - * @param height The height of the texture + * @param textureId The id of the texture to add + * @param layer The layer of the texture to use */ - public Builder setDepthTextureWrapper(int textureId, int textureTarget, int width, int height) { - return this.setDepthBuffer(new AdvancedFboMutableTextureAttachment(textureId, textureTarget, GL_DEPTH_ATTACHMENT, width, height)); + public Builder setDepthTextureWrapper(int textureId, int layer) { + return this.setDepthBuffer(new AdvancedFboMutableTextureAttachment(GL_DEPTH_ATTACHMENT, textureId, layer)); } /** diff --git a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboAttachment.java b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboAttachment.java index 2bed26a9..c2073b57 100644 --- a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboAttachment.java +++ b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboAttachment.java @@ -102,16 +102,6 @@ public interface AdvancedFboAttachment extends NativeResource, Cloneable { */ int getFormat(); - /** - * @return The width of this attachment - */ - int getWidth(); - - /** - * @return The height of this attachment - */ - int getHeight(); - /** * @return Texture targets return mipmaps and render targets return samples. */ diff --git a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java index 7d7d27a4..afc1a5f3 100644 --- a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java +++ b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java @@ -1,34 +1,34 @@ package foundry.veil.api.client.render.framebuffer; -import com.mojang.blaze3d.platform.GlStateManager; import org.apache.commons.lang3.Validate; import org.jetbrains.annotations.ApiStatus; import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER; +import static org.lwjgl.opengl.GL30.glFramebufferTextureLayer; import static org.lwjgl.opengl.GL30C.GL_DEPTH_ATTACHMENT; @ApiStatus.Internal public class AdvancedFboMutableTextureAttachment extends AdvancedFboTextureAttachment { - private int textureTarget; private int textureId; - private int width; - private int height; + private int layer; - public AdvancedFboMutableTextureAttachment(int textureId, int textureTarget, int attachmentType, int width, int height) { + public AdvancedFboMutableTextureAttachment(int attachmentType, int textureId, int layer) { super(attachmentType, 0, 0, 0, 0, 0, 0, false, null); - this.setTexture(textureTarget, textureId, width, height); + this.setTexture(textureId, layer); } @Override public void attach(int attachment) { int attachmentType = this.getAttachmentType(); Validate.isTrue(attachmentType < GL_DEPTH_ATTACHMENT || attachment == 0, "Only one depth buffer attachment is supported."); - GlStateManager._glFramebufferTexture2D(GL_FRAMEBUFFER, + glFramebufferTextureLayer( + GL_FRAMEBUFFER, attachmentType + attachment, - this.textureTarget, - this.getId(), - 0); // Only draw into the first level + this.textureId, + 0, + this.layer + ); } @Override @@ -37,7 +37,7 @@ public void create() { @Override public AdvancedFboMutableTextureAttachment clone() { - return new AdvancedFboMutableTextureAttachment(this.textureId, this.textureTarget, this.getAttachmentType(), this.getWidth(), this.getHeight()); + return new AdvancedFboMutableTextureAttachment(this.textureId, this.getAttachmentType(), this.layer); } @Override @@ -49,25 +49,13 @@ public int getId() { return this.textureId; } - @Override - public int getWidth() { - return this.width; - } - - @Override - public int getHeight() { - return this.height; - } - - public boolean setTexture(int textureTarget, int textureId, int width, int height) { - if (this.textureTarget == textureTarget && this.textureId == textureId && this.width == width && this.height == height) { + public boolean setTexture(int textureId, int layer) { + if (this.textureId == textureId && this.layer == layer) { return false; } - this.textureTarget = textureTarget; this.textureId = textureId; - this.width = width; - this.height = height; + this.layer = layer; return true; } } diff --git a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboRenderAttachment.java b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboRenderAttachment.java index 247d64cf..d670af24 100644 --- a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboRenderAttachment.java +++ b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboRenderAttachment.java @@ -107,16 +107,6 @@ public int getFormat() { return this.attachmentFormat; } - @Override - public int getWidth() { - return this.width; - } - - @Override - public int getHeight() { - return this.height; - } - @Override public int getLevels() { return this.samples; diff --git a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboTextureAttachment.java b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboTextureAttachment.java index a36931be..a7a31169 100644 --- a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboTextureAttachment.java +++ b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboTextureAttachment.java @@ -119,16 +119,6 @@ public int getFormat() { return this.format; } - @Override - public int getWidth() { - return this.width; - } - - @Override - public int getHeight() { - return this.height; - } - @Override public int getLevels() { return this.mipmapLevels; diff --git a/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java b/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java index aa09eb27..a9457f05 100644 --- a/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java +++ b/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java @@ -15,12 +15,15 @@ import static org.lwjgl.opengl.GL14C.GL_TEXTURE_LOD_BIAS; /** - * Dynamic implementation of {@link CubemapTexture}. Must be initialized before it can be used. + * Dynamic implementation of {@link CubemapTexture}. Must call {@link #init(int, int)} before it can be used. * * @author Ocelot */ public class DynamicCubemapTexture extends CubemapTexture { + private int width; + private int height; + /** * Initializes each face to the same size white texture. * @@ -28,8 +31,18 @@ public class DynamicCubemapTexture extends CubemapTexture { * @param height The height of each face */ public void init(int width, int height) { - try (NativeImage image = new NativeImage(width, height, true)) { - this.upload(image); + this.width = width; + this.height = height; + + this.bind(); + GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); + GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); + GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, 0.0F); + + RenderSystem.assertOnRenderThreadOrInit(); + for (int i = 0; i < 6; i++) { + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0L); } } @@ -39,11 +52,11 @@ public void init(int width, int height) { * @param image The image to upload */ public void upload(NativeImage image) { - this.bind(); - GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); - GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); - GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, 0.0F); + if (this.width != image.getWidth() || this.height != image.getHeight()) { + this.init(image.getWidth(), image.getHeight()); + } else { + this.bind(); + } int width = image.getWidth(); int height = image.getHeight(); @@ -77,11 +90,11 @@ public void upload(Direction face, NativeImage image) { * @param image The image to upload */ public void upload(int face, NativeImage image) { - this.bind(); - GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); - GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); - GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, 0.0F); + if (this.width != image.getWidth() || this.height != image.getHeight()) { + this.init(image.getWidth(), image.getHeight()); + } else { + this.bind(); + } int width = image.getWidth(); int height = image.getHeight(); diff --git a/common/src/main/java/foundry/veil/impl/client/render/AdvancedFboImpl.java b/common/src/main/java/foundry/veil/impl/client/render/AdvancedFboImpl.java index b0066b67..cfdcfe35 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/AdvancedFboImpl.java +++ b/common/src/main/java/foundry/veil/impl/client/render/AdvancedFboImpl.java @@ -276,9 +276,8 @@ public void createBuffers(int width, int height, boolean onMac) { this.fbo.width = width; this.fbo.height = height; - AdvancedFboAttachment attachment = this.fbo.hasColorAttachment(0) ? this.fbo.getColorAttachment(0) : null; - this.width = attachment == null ? this.viewWidth : attachment.getWidth(); - this.height = attachment == null ? this.viewHeight : attachment.getHeight(); + this.width = width; + this.height = height; } @Override diff --git a/common/src/main/java/foundry/veil/impl/client/render/pipeline/VeilFirstPersonRenderer.java b/common/src/main/java/foundry/veil/impl/client/render/pipeline/VeilFirstPersonRenderer.java index 62ed0368..ca0c4c6a 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/pipeline/VeilFirstPersonRenderer.java +++ b/common/src/main/java/foundry/veil/impl/client/render/pipeline/VeilFirstPersonRenderer.java @@ -32,7 +32,7 @@ public static void bind() { if (firstPerson == null || firstPerson.getWidth() != w || firstPerson.getHeight() != h) { free(); firstPerson = AdvancedFbo.withSize(w, h) - .addColorTextureWrapper(mainRenderTarget.getColorTextureAttachment(0).getId(), w, h) + .addColorTextureWrapper(mainRenderTarget.getColorTextureAttachment(0).getId()) .setFormat(FramebufferAttachmentDefinition.Format.DEPTH_COMPONENT) .setDepthTextureBuffer() .build(true); diff --git a/common/src/main/java/foundry/veil/impl/client/render/wrapper/VanillaAdvancedFboWrapper.java b/common/src/main/java/foundry/veil/impl/client/render/wrapper/VanillaAdvancedFboWrapper.java index 3f2f7677..e5f4171a 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/wrapper/VanillaAdvancedFboWrapper.java +++ b/common/src/main/java/foundry/veil/impl/client/render/wrapper/VanillaAdvancedFboWrapper.java @@ -166,16 +166,6 @@ public int getId() { return this.id.getAsInt(); } - @Override - public int getWidth() { - return this.parent.getWidth(); - } - - @Override - public int getHeight() { - return this.parent.getHeight(); - } - @Override public @NotNull AdvancedFboTextureAttachment clone() { return new VanillaAdvancedFboWrapper.AttachmentWrapper(this.parent, this.id, this.getAttachmentType()); From d38479cebbdc3c2c7d63ba9e43ce488cfee58377 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Sat, 2 Nov 2024 13:05:27 -0600 Subject: [PATCH 26/47] Fixed server resources loading on client --- .../resource/VeilResourceManagerImpl.java | 26 ++++++++++--------- .../resource/ModNioResourcePackMixin.java | 5 ++-- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/common/src/main/java/foundry/veil/impl/resource/VeilResourceManagerImpl.java b/common/src/main/java/foundry/veil/impl/resource/VeilResourceManagerImpl.java index 9648348e..b91cc6ff 100644 --- a/common/src/main/java/foundry/veil/impl/resource/VeilResourceManagerImpl.java +++ b/common/src/main/java/foundry/veil/impl/resource/VeilResourceManagerImpl.java @@ -71,10 +71,14 @@ public void addLoader(VeilResourceLoader loader) { this.loaders.add(loader); } - private void loadPack(ResourceManager resourceManager, VeilPackResources resources, Object2ObjectMap watchers, PackResources packResources) { + private void loadPack(ResourceManager resourceManager, VeilPackResources resources, Object2ObjectMap watchers, PackType type, PackResources packResources) { if (packResources instanceof PackResourcesExtension ext) { try { ext.veil$listResources((packType, loc, packPath, path, modResourcePath) -> { + if (packType != type) { + return; + } + try { VeilResource resource = this.visitResource(packType, resourceManager, loc, path, modResourcePath); resources.add(packType, loc, resource); @@ -99,16 +103,14 @@ private void loadPack(ResourceManager resourceManager, VeilPackResources resourc } } - for (PackType packType : PackType.values()) { - for (String namespace : packResources.getNamespaces(PackType.CLIENT_RESOURCES)) { - packResources.listResources(packType, namespace, "", (loc, inputStreamIoSupplier) -> { - try { - resources.add(packType, loc, this.visitResource(packType, resourceManager, loc, null, null)); - } catch (Exception e) { - Veil.LOGGER.error("Error loading resource: {}", loc, e); - } - }); - } + for (String namespace : packResources.getNamespaces(type)) { + packResources.listResources(type, namespace, "", (loc, inputStreamIoSupplier) -> { + try { + resources.add(type, loc, this.visitResource(type, resourceManager, loc, null, null)); + } catch (Exception e) { + Veil.LOGGER.error("Error loading resource: {}", loc, e); + } + }); } } @@ -153,7 +155,7 @@ private CompletableFuture reloadClient(PreparableReloadListener.Preparatio Object2ObjectMap watchers = new Object2ObjectArrayMap<>(); resourceManager.listPacks().flatMap(pack -> pack instanceof PackResourcesExtension extension ? extension.veil$listPacks() : Stream.of(pack)).forEach(pack -> { VeilPackResources resources = new VeilPackResources(pack.packId()); - this.loadPack(resourceManager, resources, watchers, pack); + this.loadPack(resourceManager, resources, watchers, PackType.CLIENT_RESOURCES, pack); packs.add(resources); if (pack instanceof PackResourcesExtension extension) { diff --git a/fabric/src/main/java/foundry/veil/fabric/mixin/resource/ModNioResourcePackMixin.java b/fabric/src/main/java/foundry/veil/fabric/mixin/resource/ModNioResourcePackMixin.java index 483ddb08..364b448b 100644 --- a/fabric/src/main/java/foundry/veil/fabric/mixin/resource/ModNioResourcePackMixin.java +++ b/fabric/src/main/java/foundry/veil/fabric/mixin/resource/ModNioResourcePackMixin.java @@ -45,8 +45,6 @@ public abstract class ModNioResourcePackMixin implements ModResourcePack, PackRe @Override public void veil$listResources(PackResourceConsumer consumer) { - String packId = this.packId(); - for (Path basePath : this.basePaths) { String separator = basePath.getFileSystem().getSeparator(); @@ -55,6 +53,9 @@ public abstract class ModNioResourcePackMixin implements ModResourcePack, PackRe for (String namespace : entry.getValue()) { Path nsPath = basePath.resolve(type.getDirectory()).resolve(namespace); + if (!Files.exists(nsPath)) { + continue; + } try { Files.walkFileTree(nsPath, new SimpleFileVisitor<>() { From cf1475d87808d6424adab17a232975c6d5e495e8 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Sat, 2 Nov 2024 13:36:59 -0600 Subject: [PATCH 27/47] Fixed only layered textures being supported --- .../render/framebuffer/AdvancedFbo.java | 4 +-- .../AdvancedFboMutableTextureAttachment.java | 26 ++++++++++++++----- fabric/build.gradle | 2 -- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java index ddb514ac..224a1337 100644 --- a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java +++ b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java @@ -331,7 +331,7 @@ default AdvancedFboTextureAttachment getColorTextureAttachment(int attachment) { * slot, or it is not an {@link AdvancedFboMutableTextureAttachment} */ default void setColorAttachmentTexture(int attachment, int textureId) { - this.setColorAttachmentTexture(attachment, GL_TEXTURE_2D, textureId); + this.setColorAttachmentTexture(attachment, textureId, -1); } /** @@ -424,7 +424,7 @@ default AdvancedFboTextureAttachment getDepthTextureAttachment() { * slot, or it is not an {@link AdvancedFboMutableTextureAttachment} */ default void setDepthAttachmentTexture(int textureId) { - this.setDepthAttachmentTexture(GL_TEXTURE_2D, textureId); + this.setDepthAttachmentTexture(textureId, -1); } /** diff --git a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java index afc1a5f3..0bc673ed 100644 --- a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java +++ b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java @@ -1,8 +1,10 @@ package foundry.veil.api.client.render.framebuffer; +import com.mojang.blaze3d.platform.GlStateManager; import org.apache.commons.lang3.Validate; import org.jetbrains.annotations.ApiStatus; +import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER; import static org.lwjgl.opengl.GL30.glFramebufferTextureLayer; import static org.lwjgl.opengl.GL30C.GL_DEPTH_ATTACHMENT; @@ -22,13 +24,23 @@ public AdvancedFboMutableTextureAttachment(int attachmentType, int textureId, in public void attach(int attachment) { int attachmentType = this.getAttachmentType(); Validate.isTrue(attachmentType < GL_DEPTH_ATTACHMENT || attachment == 0, "Only one depth buffer attachment is supported."); - glFramebufferTextureLayer( - GL_FRAMEBUFFER, - attachmentType + attachment, - this.textureId, - 0, - this.layer - ); + if (this.layer == -1) { + GlStateManager._glFramebufferTexture2D( + GL_FRAMEBUFFER, + attachmentType + attachment, + GL_TEXTURE_2D, + this.textureId, + 0 + ); + } else { + glFramebufferTextureLayer( + GL_FRAMEBUFFER, + attachmentType + attachment, + this.textureId, + 0, + this.layer + ); + } } @Override diff --git a/fabric/build.gradle b/fabric/build.gradle index 44f70d27..1eb8f7a4 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -58,8 +58,6 @@ dependencies { implementation 'org.jetbrains:annotations:24.0.1' implementation project(path: ":common", configuration: "namedElements") - modRuntimeOnly "maven.modrinth:modmenu:7.2.2" - modCompileOnly "maven.modrinth:sodium:mc1.20.1-0.5.3" modCompileOnly "maven.modrinth:iris:1.6.11+1.20.1" modCompileOnly "maven.modrinth:replaymod:1.20.1-2.6.15" From 56ee1f38d7381baba1f6d2568a14776c47de4ce0 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Sat, 2 Nov 2024 13:38:38 -0600 Subject: [PATCH 28/47] Fixed stack overflow errors with fabric yarn mappings. Fixes #15 #42 --- .../foundry/veil/api/client/render/MatrixStack.java | 8 ++++---- .../veil/mixin/client/pipeline/PoseStackMixin.java | 13 ++----------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/common/src/main/java/foundry/veil/api/client/render/MatrixStack.java b/common/src/main/java/foundry/veil/api/client/render/MatrixStack.java index d739cd4f..de0e041a 100644 --- a/common/src/main/java/foundry/veil/api/client/render/MatrixStack.java +++ b/common/src/main/java/foundry/veil/api/client/render/MatrixStack.java @@ -223,16 +223,16 @@ default void setIdentity() { boolean isEmpty(); /** - * Saves the current position and normal transformation for restoring later wit {@link #popMatrix()}. + * Saves the current position and normal transformation for restoring later with {@link #matrixPop()}. */ - void push(); + void matrixPush(); /** - * Restores a previous position and normal set with {@link #pushMatrix()}. + * Restores a previous position and normal set with {@link #matrixPush()}. * * @throws IllegalStateException If there are no more matrix transformations to pop */ - void pop(); + void matrixPop(); /** * @return The last pose in the stack diff --git a/common/src/main/java/foundry/veil/mixin/client/pipeline/PoseStackMixin.java b/common/src/main/java/foundry/veil/mixin/client/pipeline/PoseStackMixin.java index 80d577d9..84e126f9 100644 --- a/common/src/main/java/foundry/veil/mixin/client/pipeline/PoseStackMixin.java +++ b/common/src/main/java/foundry/veil/mixin/client/pipeline/PoseStackMixin.java @@ -36,15 +36,6 @@ public abstract class PoseStackMixin implements MatrixStack { @Shadow public abstract void shadow$popPose(); - @Shadow - public abstract boolean shadow$clear(); - - @Shadow - public abstract void shadow$setIdentity(); - - @Shadow - public abstract PoseStack.Pose shadow$last(); - @Shadow @Final private Deque poseStack; @@ -116,12 +107,12 @@ public boolean isEmpty() { } @Override - public void push() { + public void matrixPush() { this.shadow$pushPose(); } @Override - public void pop() { + public void matrixPop() { this.shadow$popPose(); } From d88b624b17d637884c7d89fb523d889ae7eb0c81 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Sun, 3 Nov 2024 17:09:09 -0700 Subject: [PATCH 29/47] Updated docs --- .../client/render/framebuffer/AdvancedFbo.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java index 224a1337..3aa1316d 100644 --- a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java +++ b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java @@ -335,9 +335,11 @@ default void setColorAttachmentTexture(int attachment, int textureId) { } /** - * Updates the texture attachment reference for the specified slot. - * If the attachment is not known to be an {@link AdvancedFboMutableTextureAttachment}, - * use {@link #isMutableColorTextureAttachment(int)} before calling this. + *

Updates the texture attachment reference for the specified slot. + * if the attachment is not known to be an {@link AdvancedFboMutableTextureAttachment}, + * use {@link #isMutableColorTextureAttachment(int)} before calling this.

+ * + *

The framebuffer must be bound before calling this

* * @param attachment The attachment to modify * @param textureId The id of the texture to draw into @@ -350,9 +352,7 @@ default void setColorAttachmentTexture(int attachment, int textureId, int layer) Validate.isTrue(this.isMutableColorTextureAttachment(attachment), "Color attachment " + attachment + " must be a mutable texture attachment to modify texture information."); AdvancedFboMutableTextureAttachment mutableTextureAttachment = (AdvancedFboMutableTextureAttachment) advancedFboAttachment; if (mutableTextureAttachment.setTexture(textureId, layer)) { - this.bind(false); mutableTextureAttachment.attach(attachment); - AdvancedFbo.unbind(); } } @@ -428,9 +428,11 @@ default void setDepthAttachmentTexture(int textureId) { } /** - * Updates the depth texture attachment reference for the specified slot. + *

Updates the depth texture attachment reference for the specified slot. * If the attachment is not known to be an {@link AdvancedFboMutableTextureAttachment}, - * use {@link #isMutableColorTextureAttachment(int)} before calling this. + * use {@link #isMutableColorTextureAttachment(int)} before calling this.

+ * + *

The framebuffer must be bound before calling this

* * @param textureId The id of the texture to draw into * @param layer The texture layer to attach. For cubemaps this is the attachment face @@ -442,9 +444,7 @@ default void setDepthAttachmentTexture(int textureId, int layer) { Validate.isTrue(this.isDepthMutableTextureAttachment(), "Depth attachment must be a mutable texture attachment to modify texture information."); AdvancedFboMutableTextureAttachment mutableTextureAttachment = (AdvancedFboMutableTextureAttachment) advancedFboAttachment; if (mutableTextureAttachment.setTexture(textureId, layer)) { - this.bind(false); mutableTextureAttachment.attach(0); - AdvancedFbo.unbind(); } } From 44dd2226ce4ba047529ea10645e29dac89ee1c0d Mon Sep 17 00:00:00 2001 From: Ocelot Date: Thu, 7 Nov 2024 12:46:08 -0700 Subject: [PATCH 30/47] Rewrote basic glsl parsing logic --- .../foundry/veil/impl/glsl/GlslLexer.java | 559 +++-- .../foundry/veil/impl/glsl/GlslParser.java | 1950 +++++++++++++---- .../veil/impl/glsl/GlslTokenReader.java | 100 + .../grammar/GlslParameterDeclaration.java | 37 + .../impl/glsl/grammar/GlslSpecifiedType.java | 62 + .../glsl/grammar/GlslStructSpecifier.java | 5 + .../veil/impl/glsl/grammar/GlslType.java | 7 + .../impl/glsl/grammar/GlslTypeQualifier.java | 95 + .../impl/glsl/grammar/GlslTypeSpecifier.java | 162 ++ .../glsl/{node => grammar}/GlslVersion.java | 2 +- .../veil/impl/glsl/node/DeclarationNode.java | 24 - .../impl/glsl/node/GlslAssignableNode.java | 20 - .../veil/impl/glsl/node/GlslCompoundNode.java | 13 + .../veil/impl/glsl/node/GlslEmptyNode.java | 11 + .../foundry/veil/impl/glsl/node/GlslNode.java | 24 + .../foundry/veil/impl/glsl/node/GlslTree.java | 20 +- .../foundry/veil/impl/glsl/node/GlslType.java | 23 - .../veil/impl/glsl/node/GlslVisitor.java | 4 - .../glsl/node/branch/GlslCaseLabelNode.java | 17 + .../glsl/node/branch/GlslSelectionNode.java | 21 + .../impl/glsl/node/branch/GlslSwitchNode.java | 21 + .../glsl/node/expression/GlslAndNode.java | 20 + .../node/expression/GlslAssignmentNode.java | 53 + .../glsl/node/expression/GlslCompareNode.java | 26 + .../node/expression/GlslConditionalNode.java | 21 + .../node/expression/GlslExclusiveOrNode.java | 20 + .../node/expression/GlslInclusiveOrNode.java | 20 + .../node/expression/GlslLogicalAndNode.java | 20 + .../node/expression/GlslLogicalOrNode.java | 20 + .../node/expression/GlslLogicalXorNode.java | 20 + .../node/expression/GlslOperationNode.java | 34 + .../GlslUnaryNode.java} | 8 +- .../glsl/node/expression/PrecisionNode.java | 38 + .../impl/glsl/node/function/GlslFunction.java | 41 + .../node/function/GlslFunctionHeader.java | 60 + .../node/function/GlslInvokeFunctionNode.java | 41 + .../glsl/node/postfix/GlslFunctionNode.java | 13 - .../glsl/node/postfix/GlslGetArrayNode.java | 26 - .../glsl/node/postfix/GlslGetFieldNode.java | 26 - .../glsl/node/postfix/GlslGetVarNode.java | 21 - .../node/postfix/GlslInitializerNode.java | 22 - .../impl/glsl/node/postfix/GlslNewNode.java | 21 - .../glsl/node/postfix/GlslSetArrayNode.java | 24 - .../glsl/node/postfix/GlslSetFieldNode.java | 24 - .../glsl/node/postfix/GlslSetVarNode.java | 23 - .../node/primary/GlslBoolConstantNode.java | 3 +- .../node/primary/GlslDoubleConstantNode.java | 3 +- .../glsl/node/primary/GlslExpressionNode.java | 12 - .../node/primary/GlslFloatConstantNode.java | 3 +- .../node/primary/GlslIntConstantNode.java | 3 +- .../node/primary/GlslUIntConstantNode.java | 3 +- .../glsl/node/variable/GlslArrayNode.java | 19 + .../glsl/node/variable/GlslFieldNode.java | 19 + .../impl/glsl/node/variable/GlslNewNode.java | 22 + .../glsl/node/variable/GlslVariableNode.java | 12 + .../impl/glsl/type/GlslSpecifiedType.java | 11 - .../impl/glsl/type/GlslTypeQualifier.java | 77 - .../veil/impl/glsl/type/StructSpecifier.java | 4 - .../veil/impl/glsl/type/TypeSpecifier.java | 30 - .../veil/impl/glsl/visitor/GlslVisitor.java | 4 + .../client/shader/GameRendererMixin.java | 2 +- .../foundry/veil/platform/VeilPlatform.java | 2 +- .../registry/RegistrationProvider.java | 14 +- .../platform/registry/RegistryObject.java | 4 +- .../veil/pinwheel/shaders/program/fog.fsh | 3 +- .../pinwheel/shaders/program/light/area.vsh | 2 +- .../src/test/java/GlslGrammarGenerator.java | 700 ++++++ common/src/test/java/GlslTest.java | 69 +- .../FabricVeilRegisterBlockLayerEvent.java | 2 +- .../FabricVeilRegisterFixedBuffersEvent.java | 2 +- .../ForgeVeilRegisterBlockLayerEvent.java | 2 +- .../ForgeVeilRegisterFixedBuffersEvent.java | 6 +- 72 files changed, 3813 insertions(+), 1039 deletions(-) create mode 100644 common/src/main/java/foundry/veil/impl/glsl/GlslTokenReader.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/grammar/GlslParameterDeclaration.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/grammar/GlslSpecifiedType.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructSpecifier.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/grammar/GlslType.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeQualifier.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeSpecifier.java rename common/src/main/java/foundry/veil/impl/glsl/{node => grammar}/GlslVersion.java (87%) delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/DeclarationNode.java delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/GlslAssignableNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/GlslCompoundNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/GlslEmptyNode.java delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/GlslType.java delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/GlslVisitor.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslCaseLabelNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSelectionNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSwitchNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAndNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAssignmentNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslCompareNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslConditionalNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslExclusiveOrNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslInclusiveOrNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalAndNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalOrNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalXorNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslOperationNode.java rename common/src/main/java/foundry/veil/impl/glsl/node/{postfix/GlslUnaryExpressionNode.java => expression/GlslUnaryNode.java} (64%) create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/expression/PrecisionNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunction.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionHeader.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/function/GlslInvokeFunctionNode.java delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslFunctionNode.java delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetArrayNode.java delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetFieldNode.java delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetVarNode.java delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslInitializerNode.java delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslNewNode.java delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetArrayNode.java delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetFieldNode.java delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetVarNode.java delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslExpressionNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslArrayNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslFieldNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslNewNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslVariableNode.java delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/type/GlslSpecifiedType.java delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/type/GlslTypeQualifier.java delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/type/StructSpecifier.java delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/type/TypeSpecifier.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/visitor/GlslVisitor.java create mode 100644 common/src/test/java/GlslGrammarGenerator.java diff --git a/common/src/main/java/foundry/veil/impl/glsl/GlslLexer.java b/common/src/main/java/foundry/veil/impl/glsl/GlslLexer.java index cc88268d..24667743 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/GlslLexer.java +++ b/common/src/main/java/foundry/veil/impl/glsl/GlslLexer.java @@ -1,6 +1,10 @@ package foundry.veil.impl.glsl; import com.mojang.brigadier.StringReader; +import foundry.veil.impl.glsl.grammar.GlslTypeQualifier; +import foundry.veil.impl.glsl.grammar.GlslTypeSpecifier; +import foundry.veil.impl.glsl.node.expression.GlslAssignmentNode; +import foundry.veil.impl.glsl.node.expression.GlslUnaryNode; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -23,7 +27,9 @@ public static Token[] createTokens(String input) throws GlslSyntaxException { while (reader.canRead()) { Token token = getToken(reader); if (token != null) { - tokens.add(token); + if (token.type != TokenType.COMMENT && token.type != TokenType.MULTI_COMMENT) { + tokens.add(token); + } reader.skipWhitespace(); continue; } @@ -36,24 +42,21 @@ public static Token[] createTokens(String input) throws GlslSyntaxException { private static @Nullable Token getToken(StringReader reader) { String word = reader.getRemaining(); + Token longest = null; + int length = 0; for (TokenType type : TokenType.values()) { Matcher matcher = type.pattern.matcher(word); - if (matcher.find() && matcher.start() == 0) { - reader.setCursor(reader.getCursor() + matcher.end()); - return new Token(type, word.substring(0, matcher.end())); + if (matcher.find() && matcher.start() == 0 && matcher.end() > length) { + length = matcher.end(); + longest = new Token(type, word.substring(0, length)); } } - return null; - } - - private static @Nullable Token getToken(StringReader reader, TokenType type) { - String word = reader.getRemaining(); - Matcher matcher = type.pattern.matcher(word); - if (matcher.find() && matcher.start() == 0) { - reader.setCursor(reader.getCursor() + matcher.end()); - return new Token(type, word.substring(0, matcher.end())); + if (longest != null) { + reader.setCursor(reader.getCursor() + length); + return longest; } + return null; } @@ -64,166 +67,161 @@ public String toString() { } } - private static final int FLAG_TYPE = 1; - private static final int FLAG_STORAGE_QUALIFIER = 2; - private static final int FLAG_CONSTANT_EXPRESSION = 4; - private static final int FLAG_ASSIGNMENT_OP = 8; - public enum TokenType { DIRECTIVE("#.*"), GLSL_MACRO("__LINE__|__FILE__|__VERSION__"), COMMENT("\\/\\/.*"), MULTI_COMMENT("\\/\\*(?:.|[\\n\\r])*\\*\\/|\\/\\/(?:.*\\\\[\\n\\r]?)+[\\n\\r]?(?:.*)"), - CONST("const", FLAG_STORAGE_QUALIFIER), - BOOL("bool", FLAG_TYPE), - FLOAT("float", FLAG_TYPE), - INT("int", FLAG_TYPE), - UINT("uint", FLAG_TYPE), - DOUBLE("double", FLAG_TYPE), - - BVEC2("bvec2", FLAG_TYPE), - BVEC3("bvec3", FLAG_TYPE), - BVEC4("bvec4", FLAG_TYPE), - IVEC2("ivec2", FLAG_TYPE), - IVEC3("ivec3", FLAG_TYPE), - IVEC4("ivec4", FLAG_TYPE), - UVEC2("uvec2", FLAG_TYPE), - UVEC3("uvec3", FLAG_TYPE), - UVEC4("uvec4", FLAG_TYPE), - VEC2("vec2", FLAG_TYPE), - VEC3("vec3", FLAG_TYPE), - VEC4("vec4", FLAG_TYPE), - - MAT2("mat2", FLAG_TYPE), - MAT3("mat3", FLAG_TYPE), - MAT4("mat4", FLAG_TYPE), - MAT2X2("mat2x2", FLAG_TYPE), - MAT2X3("mat2x3", FLAG_TYPE), - MAT2X4("mat2x4", FLAG_TYPE), - MAT3X2("mat3x2", FLAG_TYPE), - MAT3X3("mat3x3", FLAG_TYPE), - MAT3X4("mat3x4", FLAG_TYPE), - MAT4X2("mat4x2", FLAG_TYPE), - MAT4X3("mat4x3", FLAG_TYPE), - MAT4X4("mat4x4", FLAG_TYPE), - - DVEC2("dvec2", FLAG_TYPE), - DVEC3("dvec3", FLAG_TYPE), - DVEC4("dvec4", FLAG_TYPE), - DMAT2("dmat2", FLAG_TYPE), - DMAT3("dmat3", FLAG_TYPE), - DMAT4("dmat4", FLAG_TYPE), - DMAT2X2("dmat2x2", FLAG_TYPE), - DMAT2X3("dmat2x3", FLAG_TYPE), - DMAT2X4("dmat2x4", FLAG_TYPE), - DMAT3X2("dmat3x2", FLAG_TYPE), - DMAT3X3("dmat3x3", FLAG_TYPE), - DMAT3X4("dmat3x4", FLAG_TYPE), - DMAT4X2("dmat4x2", FLAG_TYPE), - DMAT4X3("dmat4x3", FLAG_TYPE), - DMAT4X4("dmat4x4", FLAG_TYPE), - - CENTROID("centroid", FLAG_STORAGE_QUALIFIER), - IN("in", FLAG_STORAGE_QUALIFIER), - OUT("out", FLAG_STORAGE_QUALIFIER), - INOUT("inout", FLAG_STORAGE_QUALIFIER), - UNIFORM("uniform", FLAG_STORAGE_QUALIFIER), - PATCH("patch", FLAG_STORAGE_QUALIFIER), - SAMPLE("sample", FLAG_STORAGE_QUALIFIER), - BUFFER("buffer", FLAG_STORAGE_QUALIFIER), - SHARED("shared", FLAG_STORAGE_QUALIFIER), - COHERENT("cohent", FLAG_STORAGE_QUALIFIER), - VOLATILE("volatile", FLAG_STORAGE_QUALIFIER), - RESTRICT("restrict", FLAG_STORAGE_QUALIFIER), - READONLY("readonly", FLAG_STORAGE_QUALIFIER), - WRITEONLY("writeonly", FLAG_STORAGE_QUALIFIER), + CONST("const"), + BOOL("bool"), + FLOAT("float"), + INT("int"), + UINT("uint"), + DOUBLE("double"), + + BVEC2("bvec2"), + BVEC3("bvec3"), + BVEC4("bvec4"), + IVEC2("ivec2"), + IVEC3("ivec3"), + IVEC4("ivec4"), + UVEC2("uvec2"), + UVEC3("uvec3"), + UVEC4("uvec4"), + VEC2("vec2"), + VEC3("vec3"), + VEC4("vec4"), + + MAT2("mat2"), + MAT3("mat3"), + MAT4("mat4"), + MAT2X2("mat2x2"), + MAT2X3("mat2x3"), + MAT2X4("mat2x4"), + MAT3X2("mat3x2"), + MAT3X3("mat3x3"), + MAT3X4("mat3x4"), + MAT4X2("mat4x2"), + MAT4X3("mat4x3"), + MAT4X4("mat4x4"), + + DVEC2("dvec2"), + DVEC3("dvec3"), + DVEC4("dvec4"), + DMAT2("dmat2"), + DMAT3("dmat3"), + DMAT4("dmat4"), + DMAT2X2("dmat2x2"), + DMAT2X3("dmat2x3"), + DMAT2X4("dmat2x4"), + DMAT3X2("dmat3x2"), + DMAT3X3("dmat3x3"), + DMAT3X4("dmat3x4"), + DMAT4X2("dmat4x2"), + DMAT4X3("dmat4x3"), + DMAT4X4("dmat4x4"), + + CENTROID("centroid"), + IN("in"), + OUT("out"), + INOUT("inout"), + UNIFORM("uniform"), + PATCH("patch"), + SAMPLE("sample"), + BUFFER("buffer"), + SHARED("shared"), + COHERENT("cohent"), + VOLATILE("volatile"), + RESTRICT("restrict"), + READONLY("readonly"), + WRITEONLY("writeonly"), NOPERSPECTIVE("noperspective"), FLAT("flat"), SMOOTH("smooth"), LAYOUT("layout"), - ATOMIC_UINT("atomic_uint", FLAG_TYPE), - - SAMPLER2D("sampler2D", FLAG_TYPE), - SAMPLER3D("sampler3D", FLAG_TYPE), - SAMPLERCUBE("samplerCube", FLAG_TYPE), - SAMPLER2DSHADOW("sampler2DShadow", FLAG_TYPE), - SAMPLERCUBESHADOW("samplerCubeShadow", FLAG_TYPE), - SAMPLER2DARRAY("sampler2DArray", FLAG_TYPE), - SAMPLER2DARRAYSHADOW("sampler2DArrayShadow", FLAG_TYPE), - ISAMPLER2D("isampler2D", FLAG_TYPE), - ISAMPLER3D("isampler3D", FLAG_TYPE), - ISAMPLERCUBE("isamplerCube", FLAG_TYPE), - ISAMPLER2DARRAY("isampler2DArray", FLAG_TYPE), - USAMPLER2D("usampler2D", FLAG_TYPE), - USAMPLER3D("usampler3D", FLAG_TYPE), - USAMPLERCUBE("usamplerCube", FLAG_TYPE), - USAMPLER2DARRAY("uSampler2DArray", FLAG_TYPE), - - SAMPLER1D("sampler1D", FLAG_TYPE), - SAMPLER1DSHADOW("sampler1DShadow", FLAG_TYPE), - SAMPLER1DARRAY("sampler1DArray", FLAG_TYPE), - SAMPLER1DARRAYSHADOW("sampler1DArrayShadow", FLAG_TYPE), - ISAMPLER1D("isampler1D", FLAG_TYPE), - ISAMPLER1DARRAY("isampler1DArray", FLAG_TYPE), - USAMPLER1D("usampler1D", FLAG_TYPE), - USAMPLER1DARRAY("usampler1DArray", FLAG_TYPE), - SAMPLER2DRECT("sampler2DRect", FLAG_TYPE), - SAMPLER2DRECTSHADOW("sampler2DRectShadow", FLAG_TYPE), - ISAMPLER2DRECT("isampler2DRect", FLAG_TYPE), - USAMPLER2DRECT("usampler2DRect", FLAG_TYPE), - - SAMPLERBUFFER("samplerBuffer", FLAG_TYPE), - ISAMPLERBUFFER("isamplerBuffer", FLAG_TYPE), - USAMPLERBUFFER("usamplerBuffer", FLAG_TYPE), - SAMPLERCUBEARRAY("samplerCubeArray", FLAG_TYPE), - SAMPLERCUBEARRAYSHADOW("samplerCubeArrayShadow", FLAG_TYPE), - ISAMPLERCUBEARRAY("isamplerCubeArray", FLAG_TYPE), - USAMPLERCUBEARRAY("usamplerCubeArray", FLAG_TYPE), - SAMPLER2DMS("sampler2Dms", FLAG_TYPE), - ISAMPLER2DMS("isampler2Dms", FLAG_TYPE), - USAMPLER2DMS("usampler2Dms", FLAG_TYPE), - SAMPLER2DMSARRAY("sampler2DMSArray", FLAG_TYPE), - ISAMPLER2DMSARRAY("isampler2DMSArray", FLAG_TYPE), - USAMPLER2DMSARRAY("usampler2DMSArray", FLAG_TYPE), - IMAGE2D("image2D", FLAG_TYPE), - IIMAGE2D("iimage2D", FLAG_TYPE), - UIMAGE2D("uimage2D", FLAG_TYPE), - IMAGE3D("image3D", FLAG_TYPE), - IIMAGE3D("iimage3D", FLAG_TYPE), - UIMAGE3D("uimage3D", FLAG_TYPE), - IMAGECUBE("imagecube", FLAG_TYPE), - IIMAGECUBE("iimageCube", FLAG_TYPE), - UIMAGECUBE("uimageCube", FLAG_TYPE), - IMAGEBUFFER("imageBuffer", FLAG_TYPE), - IIMAGEBUFFER("iimageBuffer", FLAG_TYPE), - UIMAGEBUFFER("uimageBuffer", FLAG_TYPE), - IMAGE2DARRAY("image2DArray", FLAG_TYPE), - IIMAGE2DARRAY("iimage2DArray", FLAG_TYPE), - UIMAGE2DARRAY("uimage2DArray", FLAG_TYPE), - IMAGECUBEARRAY("imagecubeArray", FLAG_TYPE), - IIMAGECUBEARRAY("iimageCubeArray", FLAG_TYPE), - UIMAGECUBEARRAY("uimageCubeArray", FLAG_TYPE), - - IMAGE1D("image1D", FLAG_TYPE), - IIMAGE1D("iimage1D", FLAG_TYPE), - UIMAGE1D("uimage1D", FLAG_TYPE), - IMAGE1DARRAY("image1DArray", FLAG_TYPE), - IIMAGE1DARRAY("iimage1DArray", FLAG_TYPE), - UIMAGE1DARRAY("uimage1DArray", FLAG_TYPE), - IMAGE2DRECT("image2DRect", FLAG_TYPE), - IIMAGE2DRECT("iimage2DRect", FLAG_TYPE), - UIMAGE2DRECT("uimage2DRect", FLAG_TYPE), - IMAGE2DMS("image2Dms", FLAG_TYPE), - IIMAGE2DMS("iimage2DMS", FLAG_TYPE), - UIMAGE2DMS("uimage2DMS", FLAG_TYPE), - IMAGE2DMSARRAY("image2DMSArray", FLAG_TYPE), - IIMAGE2DMSARRAY("iimage2DMSArray", FLAG_TYPE), - UIMAGE2DMSARRAY("uimage2DMSArray", FLAG_TYPE), + ATOMIC_UINT("atomic_uint"), + + SAMPLER2D("sampler2D"), + SAMPLER3D("sampler3D"), + SAMPLERCUBE("samplerCube"), + SAMPLER2DSHADOW("sampler2DShadow"), + SAMPLERCUBESHADOW("samplerCubeShadow"), + SAMPLER2DARRAY("sampler2DArray"), + SAMPLER2DARRAYSHADOW("sampler2DArrayShadow"), + ISAMPLER2D("isampler2D"), + ISAMPLER3D("isampler3D"), + ISAMPLERCUBE("isamplerCube"), + ISAMPLER2DARRAY("isampler2DArray"), + USAMPLER2D("usampler2D"), + USAMPLER3D("usampler3D"), + USAMPLERCUBE("usamplerCube"), + USAMPLER2DARRAY("uSampler2DArray"), + + SAMPLER1D("sampler1D"), + SAMPLER1DSHADOW("sampler1DShadow"), + SAMPLER1DARRAY("sampler1DArray"), + SAMPLER1DARRAYSHADOW("sampler1DArrayShadow"), + ISAMPLER1D("isampler1D"), + ISAMPLER1DARRAY("isampler1DArray"), + USAMPLER1D("usampler1D"), + USAMPLER1DARRAY("usampler1DArray"), + SAMPLER2DRECT("sampler2DRect"), + SAMPLER2DRECTSHADOW("sampler2DRectShadow"), + ISAMPLER2DRECT("isampler2DRect"), + USAMPLER2DRECT("usampler2DRect"), + + SAMPLERBUFFER("samplerBuffer"), + ISAMPLERBUFFER("isamplerBuffer"), + USAMPLERBUFFER("usamplerBuffer"), + SAMPLERCUBEARRAY("samplerCubeArray"), + SAMPLERCUBEARRAYSHADOW("samplerCubeArrayShadow"), + ISAMPLERCUBEARRAY("isamplerCubeArray"), + USAMPLERCUBEARRAY("usamplerCubeArray"), + SAMPLER2DMS("sampler2Dms"), + ISAMPLER2DMS("isampler2Dms"), + USAMPLER2DMS("usampler2Dms"), + SAMPLER2DMSARRAY("sampler2DMSArray"), + ISAMPLER2DMSARRAY("isampler2DMSArray"), + USAMPLER2DMSARRAY("usampler2DMSArray"), + IMAGE2D("image2D"), + IIMAGE2D("iimage2D"), + UIMAGE2D("uimage2D"), + IMAGE3D("image3D"), + IIMAGE3D("iimage3D"), + UIMAGE3D("uimage3D"), + IMAGECUBE("imagecube"), + IIMAGECUBE("iimageCube"), + UIMAGECUBE("uimageCube"), + IMAGEBUFFER("imageBuffer"), + IIMAGEBUFFER("iimageBuffer"), + UIMAGEBUFFER("uimageBuffer"), + IMAGE2DARRAY("image2DArray"), + IIMAGE2DARRAY("iimage2DArray"), + UIMAGE2DARRAY("uimage2DArray"), + IMAGECUBEARRAY("imagecubeArray"), + IIMAGECUBEARRAY("iimageCubeArray"), + UIMAGECUBEARRAY("uimageCubeArray"), + + IMAGE1D("image1D"), + IIMAGE1D("iimage1D"), + UIMAGE1D("uimage1D"), + IMAGE1DARRAY("image1DArray"), + IIMAGE1DARRAY("iimage1DArray"), + UIMAGE1DARRAY("uimage1DArray"), + IMAGE2DRECT("image2DRect"), + IIMAGE2DRECT("iimage2DRect"), + UIMAGE2DRECT("uimage2DRect"), + IMAGE2DMS("image2Dms"), + IIMAGE2DMS("iimage2DMS"), + UIMAGE2DMS("uimage2DMS"), + IMAGE2DMSARRAY("image2DMSArray"), + IIMAGE2DMSARRAY("iimage2DMSArray"), + UIMAGE2DMSARRAY("uimage2DMSArray"), STRUCT("struct"), - VOID("void", FLAG_TYPE), + VOID("void"), WHILE("while"), BREAK("break"), @@ -237,17 +235,17 @@ public enum TokenType { SWITCH("switch"), CASE("case"), DEFAULT("default"), - SUBROUTINE("subroutine", FLAG_STORAGE_QUALIFIER), + SUBROUTINE("subroutine"), // TYPE_NAME ?? - FLOATING_CONSTANT("(?:(?:\\d+\\.\\d+|\\d+\\.|\\.\\d+)(?:[eE][+-]?\\d+)?(?:f|F|lf|LF)?)|(?:\\d+)(?:\\.|[eE][+-]?\\d+)(?:f|F|lf|LF)?", FLAG_CONSTANT_EXPRESSION), - UINTEGER_HEXADECIMAL_CONSTANT("0[xX][0-9a-fA-F]*[uU]?", FLAG_CONSTANT_EXPRESSION), - UINTEGER_OCTAL_CONSTANT("0[0-7]*[uU]?", FLAG_CONSTANT_EXPRESSION), - UINTEGER_DECIMAL_CONSTANT("[1-9][\\d]*[uU]?", FLAG_CONSTANT_EXPRESSION), - INTEGER_HEXADECIMAL_CONSTANT("0[xX][0-9a-fA-F]*", FLAG_CONSTANT_EXPRESSION), - INTEGER_OCTAL_CONSTANT("0[0-7]*", FLAG_CONSTANT_EXPRESSION), - INTEGER_DECIMAL_CONSTANT("[1-9][\\d]*", FLAG_CONSTANT_EXPRESSION), - BOOL_CONSTANT("true|false", FLAG_CONSTANT_EXPRESSION), + FLOATING_CONSTANT("(?:(?:\\d+\\.\\d+|\\d+\\.|\\.\\d+)(?:[eE][+-]?\\d+)?(?:f|F|lf|LF)?)|(?:\\d+)(?:\\.|[eE][+-]?\\d+)(?:f|F|lf|LF)?"), + UINTEGER_HEXADECIMAL_CONSTANT("0[xX][0-9a-fA-F]*[uU]?"), + UINTEGER_OCTAL_CONSTANT("0[0-7]*[uU]?"), + UINTEGER_DECIMAL_CONSTANT("[1-9][\\d]*[uU]?"), + INTEGER_HEXADECIMAL_CONSTANT("0[xX][0-9a-fA-F]*"), + INTEGER_OCTAL_CONSTANT("0[0-7]*"), + INTEGER_DECIMAL_CONSTANT("[1-9][\\d]*"), + BOOL_CONSTANT("true|false"), // FIELD_SELECTION LEFT_OP("<<"), @@ -306,64 +304,201 @@ public enum TokenType { IDENTIFIER("[_a-zA-Z][\\d_a-zA-Z]*"); private final Pattern pattern; - private final int flags; TokenType(String regex) { - this(regex, 0); - } - - TokenType(String regex, int flags) { this.pattern = Pattern.compile(regex); - this.flags = flags; - } - - public boolean isType() { - return (this.flags & FLAG_TYPE) != 0; } - public boolean isStorageQualifier() { - return (this.flags & FLAG_STORAGE_QUALIFIER) != 0; + public @Nullable GlslTypeSpecifier.BuiltinType asBuiltinType() { + return switch (this) { + case VOID -> GlslTypeSpecifier.BuiltinType.VOID; + case FLOAT -> GlslTypeSpecifier.BuiltinType.FLOAT; + case DOUBLE -> GlslTypeSpecifier.BuiltinType.DOUBLE; + case INT -> GlslTypeSpecifier.BuiltinType.INT; + case UINT -> GlslTypeSpecifier.BuiltinType.UINT; + case BOOL -> GlslTypeSpecifier.BuiltinType.BOOL; + case VEC2 -> GlslTypeSpecifier.BuiltinType.VEC2; + case VEC3 -> GlslTypeSpecifier.BuiltinType.VEC3; + case VEC4 -> GlslTypeSpecifier.BuiltinType.VEC4; + case DVEC2 -> GlslTypeSpecifier.BuiltinType.DVEC2; + case DVEC3 -> GlslTypeSpecifier.BuiltinType.DVEC3; + case DVEC4 -> GlslTypeSpecifier.BuiltinType.DVEC4; + case BVEC2 -> GlslTypeSpecifier.BuiltinType.BVEC2; + case BVEC3 -> GlslTypeSpecifier.BuiltinType.BVEC3; + case BVEC4 -> GlslTypeSpecifier.BuiltinType.BVEC4; + case IVEC2 -> GlslTypeSpecifier.BuiltinType.IVEC2; + case IVEC3 -> GlslTypeSpecifier.BuiltinType.IVEC3; + case IVEC4 -> GlslTypeSpecifier.BuiltinType.IVEC4; + case UVEC2 -> GlslTypeSpecifier.BuiltinType.UVEC2; + case UVEC3 -> GlslTypeSpecifier.BuiltinType.UVEC3; + case UVEC4 -> GlslTypeSpecifier.BuiltinType.UVEC4; + case MAT2 -> GlslTypeSpecifier.BuiltinType.MAT2; + case MAT3 -> GlslTypeSpecifier.BuiltinType.MAT3; + case MAT4 -> GlslTypeSpecifier.BuiltinType.MAT4; + case MAT2X2 -> GlslTypeSpecifier.BuiltinType.MAT2X2; + case MAT2X3 -> GlslTypeSpecifier.BuiltinType.MAT2X3; + case MAT2X4 -> GlslTypeSpecifier.BuiltinType.MAT2X4; + case MAT3X2 -> GlslTypeSpecifier.BuiltinType.MAT3X2; + case MAT3X3 -> GlslTypeSpecifier.BuiltinType.MAT3X3; + case MAT3X4 -> GlslTypeSpecifier.BuiltinType.MAT3X4; + case MAT4X2 -> GlslTypeSpecifier.BuiltinType.MAT4X2; + case MAT4X3 -> GlslTypeSpecifier.BuiltinType.MAT4X3; + case MAT4X4 -> GlslTypeSpecifier.BuiltinType.MAT4X4; + case DMAT2 -> GlslTypeSpecifier.BuiltinType.DMAT2; + case DMAT3 -> GlslTypeSpecifier.BuiltinType.DMAT3; + case DMAT4 -> GlslTypeSpecifier.BuiltinType.DMAT4; + case DMAT2X2 -> GlslTypeSpecifier.BuiltinType.DMAT2X2; + case DMAT2X3 -> GlslTypeSpecifier.BuiltinType.DMAT2X3; + case DMAT2X4 -> GlslTypeSpecifier.BuiltinType.DMAT2X4; + case DMAT3X2 -> GlslTypeSpecifier.BuiltinType.DMAT3X2; + case DMAT3X3 -> GlslTypeSpecifier.BuiltinType.DMAT3X3; + case DMAT3X4 -> GlslTypeSpecifier.BuiltinType.DMAT3X4; + case DMAT4X2 -> GlslTypeSpecifier.BuiltinType.DMAT4X2; + case DMAT4X3 -> GlslTypeSpecifier.BuiltinType.DMAT4X3; + case DMAT4X4 -> GlslTypeSpecifier.BuiltinType.DMAT4X4; + case ATOMIC_UINT -> GlslTypeSpecifier.BuiltinType.ATOMIC_UINT; + case SAMPLER2D -> GlslTypeSpecifier.BuiltinType.SAMPLER2D; + case SAMPLER3D -> GlslTypeSpecifier.BuiltinType.SAMPLER3D; + case SAMPLERCUBE -> GlslTypeSpecifier.BuiltinType.SAMPLERCUBE; + case SAMPLER2DSHADOW -> GlslTypeSpecifier.BuiltinType.SAMPLER2DSHADOW; + case SAMPLERCUBESHADOW -> GlslTypeSpecifier.BuiltinType.SAMPLERCUBESHADOW; + case SAMPLER2DARRAY -> GlslTypeSpecifier.BuiltinType.SAMPLER2DARRAY; + case SAMPLER2DARRAYSHADOW -> GlslTypeSpecifier.BuiltinType.SAMPLER2DARRAYSHADOW; + case SAMPLERCUBEARRAY -> GlslTypeSpecifier.BuiltinType.SAMPLERCUBEARRAY; + case SAMPLERCUBEARRAYSHADOW -> GlslTypeSpecifier.BuiltinType.SAMPLERCUBEARRAYSHADOW; + case ISAMPLER2D -> GlslTypeSpecifier.BuiltinType.ISAMPLER2D; + case ISAMPLER3D -> GlslTypeSpecifier.BuiltinType.ISAMPLER3D; + case ISAMPLERCUBE -> GlslTypeSpecifier.BuiltinType.ISAMPLERCUBE; + case ISAMPLER2DARRAY -> GlslTypeSpecifier.BuiltinType.ISAMPLER2DARRAY; + case ISAMPLERCUBEARRAY -> GlslTypeSpecifier.BuiltinType.ISAMPLERCUBEARRAY; + case USAMPLER2D -> GlslTypeSpecifier.BuiltinType.USAMPLER2D; + case USAMPLER3D -> GlslTypeSpecifier.BuiltinType.USAMPLER3D; + case USAMPLERCUBE -> GlslTypeSpecifier.BuiltinType.USAMPLERCUBE; + case USAMPLER2DARRAY -> GlslTypeSpecifier.BuiltinType.USAMPLER2DARRAY; + case USAMPLERCUBEARRAY -> GlslTypeSpecifier.BuiltinType.USAMPLERCUBEARRAY; + case SAMPLER1D -> GlslTypeSpecifier.BuiltinType.SAMPLER1D; + case SAMPLER1DSHADOW -> GlslTypeSpecifier.BuiltinType.SAMPLER1DSHADOW; + case SAMPLER1DARRAY -> GlslTypeSpecifier.BuiltinType.SAMPLER1DARRAY; + case SAMPLER1DARRAYSHADOW -> GlslTypeSpecifier.BuiltinType.SAMPLER1DARRAYSHADOW; + case ISAMPLER1D -> GlslTypeSpecifier.BuiltinType.ISAMPLER1D; + case ISAMPLER1DARRAY -> GlslTypeSpecifier.BuiltinType.ISAMPLER1DARRAY; + case USAMPLER1D -> GlslTypeSpecifier.BuiltinType.USAMPLER1D; + case USAMPLER1DARRAY -> GlslTypeSpecifier.BuiltinType.USAMPLER1DARRAY; + case SAMPLER2DRECT -> GlslTypeSpecifier.BuiltinType.SAMPLER2DRECT; + case SAMPLER2DRECTSHADOW -> GlslTypeSpecifier.BuiltinType.SAMPLER2DRECTSHADOW; + case ISAMPLER2DRECT -> GlslTypeSpecifier.BuiltinType.ISAMPLER2DRECT; + case USAMPLER2DRECT -> GlslTypeSpecifier.BuiltinType.USAMPLER2DRECT; + case SAMPLERBUFFER -> GlslTypeSpecifier.BuiltinType.SAMPLERBUFFER; + case ISAMPLERBUFFER -> GlslTypeSpecifier.BuiltinType.ISAMPLERBUFFER; + case USAMPLERBUFFER -> GlslTypeSpecifier.BuiltinType.USAMPLERBUFFER; + case SAMPLER2DMS -> GlslTypeSpecifier.BuiltinType.SAMPLER2DMS; + case ISAMPLER2DMS -> GlslTypeSpecifier.BuiltinType.ISAMPLER2DMS; + case USAMPLER2DMS -> GlslTypeSpecifier.BuiltinType.USAMPLER2DMS; + case SAMPLER2DMSARRAY -> GlslTypeSpecifier.BuiltinType.SAMPLER2DMSARRAY; + case ISAMPLER2DMSARRAY -> GlslTypeSpecifier.BuiltinType.ISAMPLER2DMSARRAY; + case USAMPLER2DMSARRAY -> GlslTypeSpecifier.BuiltinType.USAMPLER2DMSARRAY; + case IMAGE2D -> GlslTypeSpecifier.BuiltinType.IMAGE2D; + case IIMAGE2D -> GlslTypeSpecifier.BuiltinType.IIMAGE2D; + case UIMAGE2D -> GlslTypeSpecifier.BuiltinType.UIMAGE2D; + case IMAGE3D -> GlslTypeSpecifier.BuiltinType.IMAGE3D; + case IIMAGE3D -> GlslTypeSpecifier.BuiltinType.IIMAGE3D; + case UIMAGE3D -> GlslTypeSpecifier.BuiltinType.UIMAGE3D; + case IMAGECUBE -> GlslTypeSpecifier.BuiltinType.IMAGECUBE; + case IIMAGECUBE -> GlslTypeSpecifier.BuiltinType.IIMAGECUBE; + case UIMAGECUBE -> GlslTypeSpecifier.BuiltinType.UIMAGECUBE; + case IMAGEBUFFER -> GlslTypeSpecifier.BuiltinType.IMAGEBUFFER; + case IIMAGEBUFFER -> GlslTypeSpecifier.BuiltinType.IIMAGEBUFFER; + case UIMAGEBUFFER -> GlslTypeSpecifier.BuiltinType.UIMAGEBUFFER; + case IMAGE1D -> GlslTypeSpecifier.BuiltinType.IMAGE1D; + case IIMAGE1D -> GlslTypeSpecifier.BuiltinType.IIMAGE1D; + case UIMAGE1D -> GlslTypeSpecifier.BuiltinType.UIMAGE1D; + case IMAGE1DARRAY -> GlslTypeSpecifier.BuiltinType.IMAGE1DARRAY; + case IIMAGE1DARRAY -> GlslTypeSpecifier.BuiltinType.IIMAGE1DARRAY; + case UIMAGE1DARRAY -> GlslTypeSpecifier.BuiltinType.UIMAGE1DARRAY; + case IMAGE2DRECT -> GlslTypeSpecifier.BuiltinType.IMAGE2DRECT; + case IIMAGE2DRECT -> GlslTypeSpecifier.BuiltinType.IIMAGE2DRECT; + case UIMAGE2DRECT -> GlslTypeSpecifier.BuiltinType.UIMAGE2DRECT; + case IMAGE2DARRAY -> GlslTypeSpecifier.BuiltinType.IMAGE2DARRAY; + case IIMAGE2DARRAY -> GlslTypeSpecifier.BuiltinType.IIMAGE2DARRAY; + case UIMAGE2DARRAY -> GlslTypeSpecifier.BuiltinType.UIMAGE2DARRAY; + case IMAGECUBEARRAY -> GlslTypeSpecifier.BuiltinType.IMAGECUBEARRAY; + case IIMAGECUBEARRAY -> GlslTypeSpecifier.BuiltinType.IIMAGECUBEARRAY; + case UIMAGECUBEARRAY -> GlslTypeSpecifier.BuiltinType.UIMAGECUBEARRAY; + case IMAGE2DMS -> GlslTypeSpecifier.BuiltinType.IMAGE2DMS; + case IIMAGE2DMS -> GlslTypeSpecifier.BuiltinType.IIMAGE2DMS; + case UIMAGE2DMS -> GlslTypeSpecifier.BuiltinType.UIMAGE2DMS; + case IMAGE2DMSARRAY -> GlslTypeSpecifier.BuiltinType.IMAGE2DMSARRAY; + case IIMAGE2DMSARRAY -> GlslTypeSpecifier.BuiltinType.IIMAGE2DMSARRAY; + case UIMAGE2DMSARRAY -> GlslTypeSpecifier.BuiltinType.UIMAGE2DMSARRAY; + default -> null; + }; } - public boolean isLayoutQualifier() { - return this == LAYOUT; + public @Nullable GlslTypeQualifier.StorageType asStorageQualifier() { + return switch (this) { + case CONST -> GlslTypeQualifier.StorageType.CONST; + case IN -> GlslTypeQualifier.StorageType.IN; + case OUT -> GlslTypeQualifier.StorageType.OUT; + case INOUT -> GlslTypeQualifier.StorageType.INOUT; + case CENTROID -> GlslTypeQualifier.StorageType.CENTROID; + case PATCH -> GlslTypeQualifier.StorageType.PATCH; + case SAMPLE -> GlslTypeQualifier.StorageType.SAMPLE; + case UNIFORM -> GlslTypeQualifier.StorageType.UNIFORM; + case BUFFER -> GlslTypeQualifier.StorageType.BUFFER; + case SHARED -> GlslTypeQualifier.StorageType.SHARED; + case COHERENT -> GlslTypeQualifier.StorageType.COHERENT; + case VOLATILE -> GlslTypeQualifier.StorageType.VOLATILE; + case RESTRICT -> GlslTypeQualifier.StorageType.RESTRICT; + case READONLY -> GlslTypeQualifier.StorageType.READONLY; + case WRITEONLY -> GlslTypeQualifier.StorageType.WRITEONLY; + case SUBROUTINE -> GlslTypeQualifier.StorageType.SUBROUTINE; + default -> null; + }; } - public boolean isPrecisionQualifier() { - return this == HIGH_PRECISION || this == MEDIUM_PRECISION || this == LOW_PRECISION; + public @Nullable GlslTypeQualifier.Precision asPrecisionQualifier() { + return switch (this) { + case HIGH_PRECISION -> GlslTypeQualifier.Precision.HIGH_PRECISION; + case MEDIUM_PRECISION -> GlslTypeQualifier.Precision.MEDIUM_PRECISION; + case LOW_PRECISION -> GlslTypeQualifier.Precision.LOW_PRECISION; + default -> null; + }; } - public boolean isInterpolationQualifier() { - return this == SMOOTH || this == FLAT || this == NOPERSPECTIVE; + public @Nullable GlslTypeQualifier.Interpolation asInterpolationQualifier() { + return switch (this) { + case SMOOTH -> GlslTypeQualifier.Interpolation.SMOOTH; + case FLAT -> GlslTypeQualifier.Interpolation.FLAT; + case NOPERSPECTIVE -> GlslTypeQualifier.Interpolation.NOPERSPECTIVE; + default -> null; + }; } - public boolean isInvariantQualifier() { - return this == INVARIANT; + public @Nullable GlslAssignmentNode.Operand asAssignmentOperator() { + return switch (this) { + case EQUAL -> GlslAssignmentNode.Operand.EQUAL; + case MUL_ASSIGN -> GlslAssignmentNode.Operand.MUL_ASSIGN; + case DIV_ASSIGN -> GlslAssignmentNode.Operand.DIV_ASSIGN; + case MOD_ASSIGN -> GlslAssignmentNode.Operand.MOD_ASSIGN; + case ADD_ASSIGN -> GlslAssignmentNode.Operand.ADD_ASSIGN; + case SUB_ASSIGN -> GlslAssignmentNode.Operand.SUB_ASSIGN; + case LEFT_ASSIGN -> GlslAssignmentNode.Operand.LEFT_ASSIGN; + case RIGHT_ASSIGN -> GlslAssignmentNode.Operand.RIGHT_ASSIGN; + case AND_ASSIGN -> GlslAssignmentNode.Operand.AND_ASSIGN; + case XOR_ASSIGN -> GlslAssignmentNode.Operand.XOR_ASSIGN; + case OR_ASSIGN -> GlslAssignmentNode.Operand.OR_ASSIGN; + default -> null; + }; } - public boolean isPreciseQualifier() { - return this == PRECISE; - } - - public boolean isAssignmentOperator() { - return (this.flags & FLAG_ASSIGNMENT_OP) != 0; - } - - public boolean isUnaryOperator() { - return this == PLUS || this == DASH || this == BANG || this == TILDE; - } - - public boolean isUnaryExpression() { - if(this == INC_OP || this == DEC_OP || this.isUnaryOperator()) { - return true; - } - - // Primary Expression - if(this == IDENTIFIER || (this.flags & FLAG_CONSTANT_EXPRESSION) != 0 || this == LEFT_PAREN) { - return true; - } - - return this.isType(); + public @Nullable GlslUnaryNode.Operand asUnaryOperator() { + return switch (this) { + case PLUS -> GlslUnaryNode.Operand.PLUS; + case DASH -> GlslUnaryNode.Operand.DASH; + case BANG -> GlslUnaryNode.Operand.BANG; + case TILDE -> GlslUnaryNode.Operand.TILDE; + default -> null; + }; } } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java b/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java index 5122f768..cfc127db 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java +++ b/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java @@ -1,26 +1,118 @@ package foundry.veil.impl.glsl; -import foundry.veil.impl.glsl.node.GlslAssignableNode; -import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.node.GlslTree; -import foundry.veil.impl.glsl.node.GlslVersion; -import foundry.veil.impl.glsl.node.postfix.*; +import foundry.veil.impl.glsl.grammar.*; +import foundry.veil.impl.glsl.node.*; +import foundry.veil.impl.glsl.node.branch.GlslCaseLabelNode; +import foundry.veil.impl.glsl.node.branch.GlslSelectionNode; +import foundry.veil.impl.glsl.node.branch.GlslSwitchNode; +import foundry.veil.impl.glsl.node.expression.*; +import foundry.veil.impl.glsl.node.function.GlslFunction; +import foundry.veil.impl.glsl.node.function.GlslFunctionHeader; +import foundry.veil.impl.glsl.node.function.GlslInvokeFunctionNode; +import foundry.veil.impl.glsl.node.variable.GlslArrayNode; import foundry.veil.impl.glsl.node.primary.*; -import foundry.veil.impl.glsl.type.GlslSpecifiedType; -import foundry.veil.impl.glsl.type.GlslTypeQualifier; -import foundry.veil.impl.glsl.type.TypeSpecifier; +import foundry.veil.impl.glsl.node.variable.GlslFieldNode; +import foundry.veil.impl.glsl.node.variable.GlslNewNode; +import foundry.veil.impl.glsl.node.variable.GlslVariableNode; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Objects; +import java.util.function.Function; public final class GlslParser { - private GlslParser() { - } + private static final String GRAMMAR = """ + variable_identifier : IDENTIFIER + primary_expression : variable_identifier | INTCONSTANT | UINTCONSTANT | FLOATCONSTANT | BOOLCONSTANT | DOUBLECONSTANT | LEFT_PAREN expression RIGHT_PAREN + postfix_expression : primary_expression | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET | function_call | postfix_expression DOT FIELD_SELECTION | postfix_expression INC_OP | postfix_expression DEC_OP + integer_expression : expression + function_call : function_call_or_method + function_call_or_method : function_call_generic + function_call_generic : function_call_header_with_parameters RIGHT_PAREN | function_call_header_no_parameters RIGHT_PAREN + function_call_header_no_parameters : function_call_header VOID | function_call_header + function_call_header_with_parameters : function_call_header assignment_expression | function_call_header_with_parameters COMMA assignment_expression + function_call_header : function_identifier LEFT_PAREN + function_identifier : type_specifier | postfix_expression + unary_expression : postfix_expression | INC_OP unary_expression | DEC_OP unary_expression | unary_operator unary_expression + unary_operator : PLUS | DASH | BANG | TILDE + multiplicative_expression : unary_expression | multiplicative_expression STAR unary_expression | multiplicative_expression SLASH unary_expression | multiplicative_expression PERCENT unary_expression + additive_expression : multiplicative_expression | additive_expression PLUS multiplicative_expression | additive_expression DASH multiplicative_expression + shift_expression : additive_expression | shift_expression LEFT_OP additive_expression | shift_expression RIGHT_OP additive_expression + relational_expression : shift_expression | relational_expression LEFT_ANGLE shift_expression | relational_expression RIGHT_ANGLE shift_expression | relational_expression LE_OP shift_expression | relational_expression GE_OP shift_expression + equality_expression : relational_expression | equality_expression EQ_OP relational_expression | equality_expression NE_OP relational_expression + and_expression : equality_expression | and_expression AMPERSAND equality_expression + exclusive_or_expression : and_expression | exclusive_or_expression CARET and_expression + inclusive_or_expression : exclusive_or_expression | inclusive_or_expression VERTICAL_BAR exclusive_or_expression + logical_and_expression : inclusive_or_expression | logical_and_expression AND_OP inclusive_or_expression + logical_xor_expression : logical_and_expression | logical_xor_expression XOR_OP logical_and_expression + logical_or_expression : logical_xor_expression | logical_or_expression OR_OP logical_xor_expression + conditional_expression : logical_or_expression | logical_or_expression QUESTION expression COLON assignment_expression + assignment_expression : conditional_expression | unary_expression assignment_operator assignment_expression + assignment_operator : EQUAL | MUL_ASSIGN | DIV_ASSIGN | MOD_ASSIGN | ADD_ASSIGN | SUB_ASSIGN | LEFT_ASSIGN | RIGHT_ASSIGN | AND_ASSIGN | XOR_ASSIGN | OR_ASSIGN + expression : assignment_expression | expression COMMA assignment_expression + constant_expression : conditional_expression + declaration : function_prototype SEMICOLON | init_declarator_list SEMICOLON | PRECISION precision_qualifier type_specifier SEMICOLON | type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE SEMICOLON | type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON | type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER array_specifier SEMICOLON | type_qualifier SEMICOLON | type_qualifier IDENTIFIER SEMICOLON | type_qualifier IDENTIFIER identifier_list SEMICOLON + identifier_list : COMMA IDENTIFIER | identifier_list COMMA IDENTIFIER + function_prototype : function_declarator RIGHT_PAREN + function_declarator : function_header | function_header_with_parameters + function_header_with_parameters : function_header parameter_declaration | function_header_with_parameters COMMA parameter_declaration + function_header : fully_specified_type IDENTIFIER LEFT_PAREN + parameter_declarator : type_specifier IDENTIFIER | type_specifier IDENTIFIER array_specifier + parameter_declaration : type_qualifier parameter_declarator | parameter_declarator | type_qualifier parameter_type_specifier | parameter_type_specifier + parameter_type_specifier : type_specifier + init_declarator_list : single_declaration | init_declarator_list COMMA IDENTIFIER | init_declarator_list COMMA IDENTIFIER array_specifier | init_declarator_list COMMA IDENTIFIER array_specifier EQUAL initializer | init_declarator_list COMMA IDENTIFIER EQUAL initializer + single_declaration : fully_specified_type | fully_specified_type IDENTIFIER | fully_specified_type IDENTIFIER array_specifier | fully_specified_type IDENTIFIER array_specifier EQUAL initializer | fully_specified_type IDENTIFIER EQUAL initializer + fully_specified_type : type_specifier | type_qualifier type_specifier + invariant_qualifier : INVARIANT + interpolation_qualifier : SMOOTH | FLAT | NOPERSPECTIVE + layout_qualifier : LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN + layout_qualifier_id_list : layout_qualifier_id | layout_qualifier_id_list COMMA layout_qualifier_id + layout_qualifier_id : IDENTIFIER | IDENTIFIER EQUAL constant_expression | SHARED + precise_qualifier : PRECISE + type_qualifier : single_type_qualifier | type_qualifier single_type_qualifier + single_type_qualifier : storage_qualifier | layout_qualifier | precision_qualifier | interpolation_qualifier | invariant_qualifier | precise_qualifier + storage_qualifier : CONST | IN | OUT | INOUT | CENTROID | PATCH | SAMPLE | UNIFORM | BUFFER | SHARED | COHERENT | VOLATILE | RESTRICT | READONLY | WRITEONLY | SUBROUTINE | SUBROUTINE LEFT_PAREN type_name_list RIGHT_PAREN + type_name_list : TYPE_NAME | type_name_list COMMA TYPE_NAME + type_specifier : type_specifier_nonarray | type_specifier_nonarray array_specifier + array_specifier : LEFT_BRACKET RIGHT_BRACKET | LEFT_BRACKET conditional_expression RIGHT_BRACKET | array_specifier LEFT_BRACKET RIGHT_BRACKET | array_specifier LEFT_BRACKET conditional_expression RIGHT_BRACKET + type_specifier_nonarray : VOID | FLOAT | DOUBLE | INT | UINT | BOOL | VEC2 | VEC3 | VEC4 | DVEC2 | DVEC3 | DVEC4 | BVEC2 | BVEC3 | BVEC4 | IVEC2 | IVEC3 | IVEC4 | UVEC2 | UVEC3 | UVEC4 | MAT2 | MAT3 | MAT4 | MAT2X2 | MAT2X3 | MAT2X4 | MAT3X2 | MAT3X3 | MAT3X4 | MAT4X2 | MAT4X3 | MAT4X4 | DMAT2 | DMAT3 | DMAT4 | DMAT2X2 | DMAT2X3 | DMAT2X4 | DMAT3X2 | DMAT3X3 | DMAT3X4 | DMAT4X2 | DMAT4X3 | DMAT4X4 | ATOMIC_UINT | SAMPLER2D | SAMPLER3D | SAMPLERCUBE | SAMPLER2DSHADOW | SAMPLERCUBESHADOW | SAMPLER2DARRAY | SAMPLER2DARRAYSHADOW | SAMPLERCUBEARRAY | SAMPLERCUBEARRAYSHADOW | ISAMPLER2D | ISAMPLER3D | ISAMPLERCUBE | ISAMPLER2DARRAY | ISAMPLERCUBEARRAY | USAMPLER2D | USAMPLER3D | USAMPLERCUBE | USAMPLER2DARRAY | USAMPLERCUBEARRAY | SAMPLER1D | SAMPLER1DSHADOW | SAMPLER1DARRAY | SAMPLER1DARRAYSHADOW | ISAMPLER1D | ISAMPLER1DARRAY | USAMPLER1D | USAMPLER1DARRAY | SAMPLER2DRECT | SAMPLER2DRECTSHADOW | ISAMPLER2DRECT | USAMPLER2DRECT | SAMPLERBUFFER | ISAMPLERBUFFER | USAMPLERBUFFER | SAMPLER2DMS | ISAMPLER2DMS | USAMPLER2DMS | SAMPLER2DMSARRAY | ISAMPLER2DMSARRAY | USAMPLER2DMSARRAY | IMAGE2D | IIMAGE2D | UIMAGE2D | IMAGE3D | IIMAGE3D | UIMAGE3D | IMAGECUBE | IIMAGECUBE | UIMAGECUBE | IMAGEBUFFER | IIMAGEBUFFER | UIMAGEBUFFER | IMAGE1D | IIMAGE1D | UIMAGE1D | IMAGE1DARRAY | IIMAGE1DARRAY | UIMAGE1DARRAY | IMAGE2DRECT | IIMAGE2DRECT | UIMAGE2DRECT | IMAGE2DARRAY | IIMAGE2DARRAY | UIMAGE2DARRAY | IMAGECUBEARRAY | IIMAGECUBEARRAY | UIMAGECUBEARRAY | IMAGE2DMS | IIMAGE2DMS | UIMAGE2DMS | IMAGE2DMSARRAY | IIMAGE2DMSARRAY | UIMAGE2DMSARRAY | struct_specifier | TYPE_NAME + precision_qualifier : HIGH_PRECISION | MEDIUM_PRECISION | LOW_PRECISION + struct_specifier : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE | STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE + struct_declaration_list : struct_declaration | struct_declaration_list struct_declaration + struct_declaration : type_specifier struct_declarator_list SEMICOLON | type_qualifier type_specifier struct_declarator_list SEMICOLON + struct_declarator_list : struct_declarator | struct_declarator_list COMMA struct_declarator + struct_declarator : IDENTIFIER | IDENTIFIER array_specifier + initializer : assignment_expression | LEFT_BRACE initializer_list RIGHT_BRACE | LEFT_BRACE initializer_list COMMA RIGHT_BRACE + initializer_list : initializer | initializer_list COMMA initializer + declaration_statement : declaration + statement : compound_statement | simple_statement + simple_statement : declaration_statement | expression_statement | selection_statement | switch_statement | case_label | iteration_statement | jump_statement + compound_statement : LEFT_BRACE RIGHT_BRACE | LEFT_BRACE statement_list RIGHT_BRACE + statement_no_new_scope : compound_statement_no_new_scope | simple_statement + compound_statement_no_new_scope : LEFT_BRACE RIGHT_BRACE | LEFT_BRACE statement_list RIGHT_BRACE + statement_list : statement | statement_list statement + expression_statement : SEMICOLON | expression SEMICOLON + selection_statement : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement + selection_rest_statement : statement ELSE statement | statement + condition : expression | fully_specified_type IDENTIFIER EQUAL initializer + switch_statement : SWITCH LEFT_PAREN expression RIGHT_PAREN LEFT_BRACE switch_statement_list | RIGHT_BRACE + switch_statement_list : statement_list + case_label : CASE expression COLON | DEFAULT COLON + iteration_statement : WHILE LEFT_PAREN condition RIGHT_PAREN statement_no_new_scope | DO statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope + for_init_statement : expression_statement | declaration_statement + conditionopt : condition + for_rest_statement : conditionopt SEMICOLON | conditionopt SEMICOLON expression + jump_statement : CONTINUE SEMICOLON | BREAK SEMICOLON | RETURN SEMICOLON | RETURN expression SEMICOLON | DISCARD SEMICOLON + translation_unit : external_declaration | translation_unit external_declaration + external_declaration : function_definition | declaration | SEMICOLON + function_definition : function_prototype compound_statement_no_new_scope + """; public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxException { - TokenReader reader = new TokenReader(tokens); + GlslTokenReader reader = new GlslTokenReader(tokens); GlslVersion version = new GlslVersion(110, true); @@ -38,479 +130,1591 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio } } - reader.skipWhitespace(); + List body = new ArrayList<>(); while (reader.canRead()) { - GlslNode node = parseCondition(reader); - System.out.println(node); - reader.skipWhitespace(); + GlslNode functionDefinition = parseFunctionDefinition(reader); + if (functionDefinition != null) { + body.add(functionDefinition); + continue; + } + + GlslNode declaration = parseDeclaration(reader); + if (declaration != null) { + body.add(declaration); + continue; + } + + if (reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { + continue; + } + + throw reader.error("Failed"); } - return new GlslTree(version); + return new GlslTree(version, body); } - private static @Nullable GlslNode parseCondition(TokenReader reader) throws GlslSyntaxException { - if (!reader.canRead()) { - return null; + private static @Nullable GlslNode parsePrimaryExpression(GlslTokenReader reader) { + // IDENTIFIER + // INTCONSTANT + // UINTCONSTANT + // FLOATCONSTANT + // BOOLCONSTANT + // DOUBLECONSTANT + // LEFT_PAREN condition RIGHT_PAREN + + if (reader.tryConsume(GlslLexer.TokenType.IDENTIFIER)) { + String variableName = reader.peek(-1).value(); + return new GlslVariableNode(variableName); + } + if (reader.tryConsume(GlslLexer.TokenType.INTEGER_DECIMAL_CONSTANT)) { + return new GlslIntConstantNode(GlslIntFormat.DECIMAL, Integer.parseUnsignedInt(reader.peek(-1).value(), 10)); + } + if (reader.tryConsume(GlslLexer.TokenType.INTEGER_HEXADECIMAL_CONSTANT)) { + return new GlslIntConstantNode(GlslIntFormat.HEXADECIMAL, Integer.parseUnsignedInt(reader.peek(-1).value(), 16)); + } + if (reader.tryConsume(GlslLexer.TokenType.INTEGER_OCTAL_CONSTANT)) { + return new GlslIntConstantNode(GlslIntFormat.OCTAL, Integer.parseUnsignedInt(reader.peek(-1).value(), 8)); + } + if (reader.tryConsume(GlslLexer.TokenType.UINTEGER_DECIMAL_CONSTANT)) { + return new GlslUIntConstantNode(GlslIntFormat.DECIMAL, Integer.parseUnsignedInt(reader.peek(-1).value(), 10)); + } + if (reader.tryConsume(GlslLexer.TokenType.UINTEGER_HEXADECIMAL_CONSTANT)) { + return new GlslUIntConstantNode(GlslIntFormat.HEXADECIMAL, Integer.parseUnsignedInt(reader.peek(-1).value(), 16)); + } + if (reader.tryConsume(GlslLexer.TokenType.UINTEGER_OCTAL_CONSTANT)) { + return new GlslUIntConstantNode(GlslIntFormat.OCTAL, Integer.parseUnsignedInt(reader.peek(-1).value(), 8)); } - if (reader.peek().type().isType()) { - GlslSpecifiedType type = parseFullySpecifiedType(reader); - String name = reader.consume(GlslLexer.TokenType.IDENTIFIER).value(); - reader.consume(GlslLexer.TokenType.EQUAL); - GlslNode value = parseInitializer(reader); - return new GlslNewNode(type, name, value); + if (reader.tryConsume(GlslLexer.TokenType.FLOATING_CONSTANT)) { + return new GlslFloatConstantNode(Float.parseFloat(reader.peek(-1).value())); + } + if (reader.tryConsume(GlslLexer.TokenType.BOOL_CONSTANT)) { + return new GlslBoolConstantNode(Boolean.parseBoolean(reader.peek(-1).value())); + } + + int cursor = reader.getCursor(); + if (reader.tryConsume(GlslLexer.TokenType.LEFT_PAREN)) { + GlslNode condition = parseCondition(reader); + if (condition != null && reader.tryConsume(GlslLexer.TokenType.RIGHT_PAREN)) { + return condition; + } } - return parseExpression(reader); + reader.setCursor(cursor); + return null; } - private static GlslNode parseInitializer(TokenReader reader) throws GlslSyntaxException { - if (!reader.canRead()) { - throw reader.error("Expected initializer"); - } + private static @Nullable GlslNode parsePostfixExpression(boolean allowFunction, GlslTokenReader reader) { + int cursor = reader.getCursor(); - if (reader.peek().type() == GlslLexer.TokenType.LEFT_BRACE) { - reader.skip(); - List expressions = new ArrayList<>(); - expressions.add(parseInitializer(reader)); - while (reader.peek().type() == GlslLexer.TokenType.COMMA) { - reader.skip(); - if (!reader.canRead()) { - throw reader.error("Expected initializer or right brace"); +// primary_expression +// primary_expression LEFT_BRACKET integer_expression RIGHT_BRACKET +// primary_expression DOT FIELD_SELECTION +// primary_expression INC_OP +// primary_expression DEC_OP +// function_call LEFT_BRACKET integer_expression RIGHT_BRACKET +// function_call +// function_call DOT FIELD_SELECTION +// function_call INC_OP +// function_call DEC_OP + + if (allowFunction) { + // function_call + GlslNode functionCall = parseFunctionCallGeneric(reader); + if (functionCall != null) { + // function_call LEFT_BRACKET integer_expression RIGHT_BRACKET + int functionCursor = reader.getCursor(); + if (reader.tryConsume(GlslLexer.TokenType.LEFT_BRACKET)) { + GlslNode integerExpression = parseIntegerExpression(reader); + if (integerExpression != null && reader.tryConsume(GlslLexer.TokenType.RIGHT_BRACKET)) { + return new GlslArrayNode(functionCall, integerExpression); + } + } + reader.setCursor(functionCursor); + + // function_call DOT FIELD_SELECTION + if (reader.tryConsume(GlslLexer.TokenType.DOT, GlslLexer.TokenType.IDENTIFIER)) { + return new GlslFieldNode(functionCall, reader.peek(-1).value()); + } + reader.setCursor(functionCursor); + + // function_call INC_OP + if (reader.tryConsume(GlslLexer.TokenType.INC_OP)) { + return new GlslUnaryNode(functionCall, GlslUnaryNode.Operand.POST_INCREMENT); + } + reader.setCursor(functionCursor); + + // function_call DEC_OP + if (reader.tryConsume(GlslLexer.TokenType.DEC_OP)) { + return new GlslUnaryNode(functionCall, GlslUnaryNode.Operand.POST_DECREMENT); } + reader.setCursor(functionCursor); - if (reader.peek().type() == GlslLexer.TokenType.RIGHT_BRACE) { - break; + return functionCall; + } + reader.setCursor(cursor); + } + + // primary_expression + GlslNode primaryExpression = parsePrimaryExpression(reader); + if (primaryExpression != null) { + // primary_expression LEFT_BRACKET integer_expression RIGHT_BRACKET + int expressionCursor = reader.getCursor(); + if (reader.tryConsume(GlslLexer.TokenType.LEFT_BRACKET)) { + GlslNode integerExpression = parseIntegerExpression(reader); + if (integerExpression != null && reader.tryConsume(GlslLexer.TokenType.RIGHT_BRACKET)) { + return new GlslArrayNode(primaryExpression, integerExpression); } + } + reader.setCursor(expressionCursor); - expressions.add(parseInitializer(reader)); + // primary_expression DOT FIELD_SELECTION + if (reader.tryConsume(GlslLexer.TokenType.DOT, GlslLexer.TokenType.IDENTIFIER)) { + return new GlslFieldNode(primaryExpression, reader.peek(-1).value()); } - reader.consume(GlslLexer.TokenType.RIGHT_BRACE); - return new GlslInitializerNode(expressions.toArray(GlslNode[]::new)); + reader.setCursor(expressionCursor); + // primary_expression INC_OP + if (reader.tryConsume(GlslLexer.TokenType.INC_OP)) { + return new GlslUnaryNode(primaryExpression, GlslUnaryNode.Operand.POST_INCREMENT); + } + reader.setCursor(expressionCursor); + + // primary_expression DEC_OP + if (reader.tryConsume(GlslLexer.TokenType.DEC_OP)) { + return new GlslUnaryNode(primaryExpression, GlslUnaryNode.Operand.POST_DECREMENT); + } + reader.setCursor(expressionCursor); + + return primaryExpression; } - return parseAssignmentExpression(reader); + reader.setCursor(cursor); + return null; } - private static GlslNode parseExpression(TokenReader reader) throws GlslSyntaxException { - return parseAssignmentExpression(reader); + private static @Nullable GlslNode parseIntegerExpression(GlslTokenReader reader) { + return parseCondition(reader); } - private static GlslNode parseAssignmentExpression(TokenReader reader) throws GlslSyntaxException { - if (!reader.canRead()) { - throw reader.error("Expected assignment expression"); - } - - GlslNode expression = parseConditionalExpression(reader); - if (reader.canRead() && reader.peek().type().isAssignmentOperator()) { - if (!(expression instanceof GlslAssignableNode left)) { - throw reader.error("Invalid left-hand operand"); - } - - GlslAssignableNode.Assignment assignment = switch (reader.peek().type()) { - case EQUAL -> GlslAssignableNode.Assignment.EQUAL; - case MUL_ASSIGN -> GlslAssignableNode.Assignment.MUL_ASSIGN; - case DIV_ASSIGN -> GlslAssignableNode.Assignment.DIV_ASSIGN; - case MOD_ASSIGN -> GlslAssignableNode.Assignment.MOD_ASSIGN; - case ADD_ASSIGN -> GlslAssignableNode.Assignment.ADD_ASSIGN; - case SUB_ASSIGN -> GlslAssignableNode.Assignment.SUB_ASSIGN; - case LEFT_ASSIGN -> GlslAssignableNode.Assignment.LEFT_ASSIGN; - case RIGHT_ASSIGN -> GlslAssignableNode.Assignment.RIGHT_ASSIGN; - case AND_ASSIGN -> GlslAssignableNode.Assignment.AND_ASSIGN; - case XOR_ASSIGN -> GlslAssignableNode.Assignment.XOR_ASSIGN; - case OR_ASSIGN -> GlslAssignableNode.Assignment.OR_ASSIGN; - default -> throw reader.error("Expected assignment operator"); - }; - reader.skip(); - GlslNode value = parseAssignmentExpression(reader); - return left.toAssignment(assignment, value); + private static @Nullable GlslNode parseFunctionCallGeneric(GlslTokenReader reader) { + GlslNode functionCallHeader = parseFunctionCallHeader(reader); + if (functionCallHeader == null) { + return null; + } + + int cursor = reader.getCursor(); + + // function_call_header assignment_expression RIGHT_PAREN + // function_call_header_with_parameters COMMA assignment_expression RIGHT_PAREN + int parameterCursor = reader.getCursor(); + List parameters = new ArrayList<>(); + while (reader.canRead()) { + GlslNode parameter = parseAssignmentExpression(reader); + if (parameter == null) { + reader.setCursor(parameterCursor); + break; + } + + parameters.add(parameter); + parameterCursor = reader.getCursor(); + + if (!reader.tryConsume(GlslLexer.TokenType.COMMA)) { + break; + } + } + + if (reader.tryConsume(GlslLexer.TokenType.RIGHT_PAREN)) { + return new GlslInvokeFunctionNode(functionCallHeader, parameters); + } + reader.setCursor(cursor); + + // function_call_header VOID RIGHT_PAREN + if (reader.tryConsume(GlslLexer.TokenType.VOID, GlslLexer.TokenType.RIGHT_PAREN)) { + return new GlslInvokeFunctionNode(functionCallHeader, Collections.emptyList()); + } + reader.setCursor(cursor); + + // function_call_header RIGHT_PAREN + if (reader.tryConsume(GlslLexer.TokenType.RIGHT_PAREN)) { + return new GlslInvokeFunctionNode(functionCallHeader, Collections.emptyList()); } - return expression; + reader.setCursor(cursor); + return null; } - private static GlslNode parseUnaryExpression(TokenReader reader) throws GlslSyntaxException { - if (!reader.canRead()) { - throw reader.error("Expected unary expression"); + private static @Nullable GlslNode parseFunctionCallHeaderNoParameters(GlslTokenReader reader) { + // function_call_header VOID + // function_call_header + return null; // TODO + } + + private static @Nullable GlslNode parseFunctionCallHeaderWithParameters(GlslTokenReader reader) { + // function_call_header assignment_expression + // function_call_header_with_parameters COMMA assignment_expression + return null; // TODO + } + + private static @Nullable GlslNode parseFunctionCallHeader(GlslTokenReader reader) { + // FIXME + // type_specifier LEFT_PAREN + // postfix_expression LEFT_PAREN + + int cursor = reader.getCursor(); + GlslNode expression = parsePostfixExpression(false, reader); + if (expression != null && reader.tryConsume(GlslLexer.TokenType.LEFT_PAREN)) { + return expression; } + reader.setCursor(cursor); + return null; + } - switch (reader.peek().type()) { - case INC_OP -> { - reader.skip(); - return new GlslUnaryExpressionNode(GlslUnaryExpressionNode.Operator.PRE_INCREMENT, parseUnaryExpression(reader)); - } - case DEC_OP -> { - reader.skip(); - return new GlslUnaryExpressionNode(GlslUnaryExpressionNode.Operator.PRE_DECREMENT, parseUnaryExpression(reader)); + private static @Nullable GlslNode parseUnaryExpression(GlslTokenReader reader) { + // unary_operator unary_expression + + GlslNode expression = parsePostfixExpression(true, reader); + if (expression != null) { + return expression; + } + + int cursor = reader.getCursor(); + + // INC_OP unary_expression + if (reader.tryConsume(GlslLexer.TokenType.INC_OP)) { + GlslNode right = parseUnaryExpression(reader); + if (right != null) { + return new GlslUnaryNode(right, GlslUnaryNode.Operand.PRE_INCREMENT); } - case PLUS -> { - reader.skip(); - return new GlslUnaryExpressionNode(GlslUnaryExpressionNode.Operator.PLUS, parseUnaryExpression(reader)); + } + reader.setCursor(cursor); + + // DEC_OP unary_expression + if (reader.tryConsume(GlslLexer.TokenType.DEC_OP)) { + GlslNode right = parseUnaryExpression(reader); + if (right != null) { + return new GlslUnaryNode(right, GlslUnaryNode.Operand.PRE_DECREMENT); } - case DASH -> { - reader.skip(); - return new GlslUnaryExpressionNode(GlslUnaryExpressionNode.Operator.DASH, parseUnaryExpression(reader)); + } + reader.setCursor(cursor); + + // postfix_expression + if (reader.canRead()) { + GlslUnaryNode.Operand operator = reader.peek().type().asUnaryOperator(); + if (operator != null) { + GlslNode right = parseUnaryExpression(reader); + if (right != null) { + return new GlslUnaryNode(right, operator); + } } - case BANG -> { - reader.skip(); - return new GlslUnaryExpressionNode(GlslUnaryExpressionNode.Operator.BANG, parseUnaryExpression(reader)); + } + + reader.setCursor(cursor); + return null; + } + + private static @Nullable GlslNode parseSimpleExpression(GlslTokenReader reader, Function parser, GlslLexer.TokenType operator, Function, GlslNode> join) { + int cursor = reader.getCursor(); + List expressions = new ArrayList<>(); + while (reader.canRead()) { + GlslNode expression = parser.apply(reader); + if (expression == null) { + reader.setCursor(cursor); + break; } - case TILDE -> { - reader.skip(); - return new GlslUnaryExpressionNode(GlslUnaryExpressionNode.Operator.TILDE, parseUnaryExpression(reader)); + + expressions.add(expression); + cursor = reader.getCursor(); + + if (!reader.tryConsume(operator)) { + break; } } - return parsePostfixExpression(reader); + if (expressions.isEmpty()) { + return null; + } + if (expressions.size() == 1) { + return expressions.get(0); + } + return join.apply(expressions); } - private static GlslNode parsePostfixExpression(TokenReader reader) throws GlslSyntaxException { - if (!reader.canRead()) { - throw reader.error("Expected postfix expression"); - } - - TypeSpecifier functionIdentifier; - String varName; - GlslNode postFixExpression; - - GlslLexer.TokenType type = reader.peek().type(); - if (type.isType()) { - functionIdentifier = parseTypeSpecifier(reader); - varName = null; - postFixExpression = null; - } else if (type == GlslLexer.TokenType.IDENTIFIER) { - functionIdentifier = null; - varName = reader.consume(GlslLexer.TokenType.IDENTIFIER).value(); - postFixExpression = null; - } else { - varName = null; - functionIdentifier = null; - postFixExpression = switch (type) { - case UINTEGER_HEXADECIMAL_CONSTANT -> { - try { - int value = Integer.parseUnsignedInt(reader.consume(GlslLexer.TokenType.UINTEGER_HEXADECIMAL_CONSTANT).value(), 16); - yield new GlslUIntConstantNode(GlslIntFormat.HEXADECIMAL, value); - } catch (NumberFormatException e) { - throw reader.error(e.getMessage()); - } - } - case UINTEGER_OCTAL_CONSTANT -> { - try { - int value = Integer.parseUnsignedInt(reader.consume(GlslLexer.TokenType.UINTEGER_OCTAL_CONSTANT).value(), 8); - yield new GlslUIntConstantNode(GlslIntFormat.OCTAL, value); - } catch (NumberFormatException e) { - throw reader.error(e.getMessage()); - } - } - case UINTEGER_DECIMAL_CONSTANT -> { - try { - int value = Integer.parseUnsignedInt(reader.consume(GlslLexer.TokenType.UINTEGER_DECIMAL_CONSTANT).value()); - yield new GlslUIntConstantNode(GlslIntFormat.DECIMAL, value); - } catch (NumberFormatException e) { - throw reader.error(e.getMessage()); - } - } - case INTEGER_HEXADECIMAL_CONSTANT -> { - try { - int value = Integer.parseInt(reader.consume(GlslLexer.TokenType.INTEGER_HEXADECIMAL_CONSTANT).value(), 16); - yield new GlslIntConstantNode(GlslIntFormat.HEXADECIMAL, value); - } catch (NumberFormatException e) { - throw reader.error(e.getMessage()); - } - } - case INTEGER_OCTAL_CONSTANT -> { - try { - int value = Integer.parseInt(reader.consume(GlslLexer.TokenType.INTEGER_OCTAL_CONSTANT).value(), 8); - yield new GlslIntConstantNode(GlslIntFormat.OCTAL, value); - } catch (NumberFormatException e) { - throw reader.error(e.getMessage()); - } + private static @Nullable GlslNode parseMultiplicativeExpression(GlslTokenReader reader) { + // unary_expression + // multiplicative_expression STAR unary_expression + // multiplicative_expression SLASH unary_expression + // multiplicative_expression PERCENT unary_expression + + GlslNode left = parseUnaryExpression(reader); + if (left == null) { + return null; + } + + while (reader.canRead()) { + int cursor = reader.getCursor(); + if (reader.tryConsume(GlslLexer.TokenType.STAR)) { + GlslNode right = parseUnaryExpression(reader); + if (right == null) { + reader.setCursor(cursor); + return left; } - case INTEGER_DECIMAL_CONSTANT -> { - try { - int value = Integer.parseInt(reader.consume(GlslLexer.TokenType.INTEGER_DECIMAL_CONSTANT).value()); - yield new GlslIntConstantNode(GlslIntFormat.DECIMAL, value); - } catch (NumberFormatException e) { - throw reader.error(e.getMessage()); - } + left = new GlslOperationNode(left, right, GlslOperationNode.Operand.MULTIPLY); + continue; + } + if (reader.tryConsume(GlslLexer.TokenType.SLASH)) { + GlslNode right = parseUnaryExpression(reader); + if (right == null) { + reader.setCursor(cursor); + return left; } - case FLOATING_CONSTANT -> { - try { - float value = Float.parseFloat(reader.consume(GlslLexer.TokenType.FLOATING_CONSTANT).value()); - yield new GlslFloatConstantNode(value); - } catch (NumberFormatException e) { - throw reader.error(e.getMessage()); - } + left = new GlslOperationNode(left, right, GlslOperationNode.Operand.DIVIDE); + continue; + } + if (reader.tryConsume(GlslLexer.TokenType.PERCENT)) { + GlslNode right = parseUnaryExpression(reader); + if (right == null) { + reader.setCursor(cursor); + return left; } - case BOOL_CONSTANT -> - new GlslBoolConstantNode("true".equalsIgnoreCase(reader.consume(GlslLexer.TokenType.BOOL_CONSTANT).value())); - case DOUBLE -> { - try { - double value = Double.parseDouble(reader.consume(GlslLexer.TokenType.DOUBLE).value()); - yield new GlslDoubleConstantNode(value); - } catch (NumberFormatException e) { - throw reader.error(e.getMessage()); - } + left = new GlslOperationNode(left, right, GlslOperationNode.Operand.MODULO); + continue; + } + break; + } + + return left; + } + + private static @Nullable GlslNode parseAdditiveExpression(GlslTokenReader reader) { + // multiplicative_expression + // additive_expression PLUS multiplicative_expression + // additive_expression DASH multiplicative_expression + + GlslNode left = parseMultiplicativeExpression(reader); + if (left == null) { + return null; + } + + while (reader.canRead()) { + int cursor = reader.getCursor(); + if (reader.tryConsume(GlslLexer.TokenType.PLUS)) { + GlslNode right = parseMultiplicativeExpression(reader); + if (right == null) { + reader.setCursor(cursor); + return left; } - case LEFT_PAREN -> { - reader.skip(); - GlslNode expression = parseExpression(reader); - reader.consume(GlslLexer.TokenType.RIGHT_PAREN); - yield new GlslExpressionNode(expression); + left = new GlslOperationNode(left, right, GlslOperationNode.Operand.ADD); + continue; + } + if (reader.tryConsume(GlslLexer.TokenType.DASH)) { + GlslNode right = parseMultiplicativeExpression(reader); + if (right == null) { + reader.setCursor(cursor); + return left; } - default -> throw reader.error("Expected postfix expression"); - }; + left = new GlslOperationNode(left, right, GlslOperationNode.Operand.SUBTRACT); + continue; + } + break; } - if (functionIdentifier != null) { - reader.consume(GlslLexer.TokenType.LEFT_PAREN); - reader.skip(); - if (!reader.canRead(2)) { - throw reader.error("Unexpected end of function definition"); - } + return left; + } - if (reader.peek().type() == GlslLexer.TokenType.VOID) { - reader.skip(); - } else if (reader.peek().type() != GlslLexer.TokenType.RIGHT_PAREN) { - List params = new ArrayList<>(); - params.add(parseConditionalExpression(reader)); - while (reader.canRead() && reader.peek().type() == GlslLexer.TokenType.COMMA) { - reader.skip(); - params.add(parseConditionalExpression(reader)); + private static @Nullable GlslNode parseShiftExpression(GlslTokenReader reader) { + // additive_expression + // shift_expression LEFT_OP additive_expression + // shift_expression RIGHT_OP additive_expression + + GlslNode left = parseAdditiveExpression(reader); + if (left == null) { + return null; + } + + while (reader.canRead()) { + int cursor = reader.getCursor(); + if (reader.tryConsume(GlslLexer.TokenType.LEFT_OP)) { + GlslNode right = parseAdditiveExpression(reader); + if (right == null) { + reader.setCursor(cursor); + return left; } - reader.consume(GlslLexer.TokenType.RIGHT_PAREN); - postFixExpression = new GlslFunctionNode(functionIdentifier, params.toArray(GlslNode[]::new)); - } else { - reader.consume(GlslLexer.TokenType.RIGHT_PAREN); - postFixExpression = new GlslFunctionNode(functionIdentifier, new GlslNode[0]); + left = new GlslOperationNode(left, right, GlslOperationNode.Operand.LEFT_SHIFT); + continue; + } + if (reader.tryConsume(GlslLexer.TokenType.RIGHT_OP)) { + GlslNode right = parseAdditiveExpression(reader); + if (right == null) { + reader.setCursor(cursor); + return left; + } + left = new GlslOperationNode(left, right, GlslOperationNode.Operand.RIGHT_SHIFT); + continue; } + break; } - if (varName != null) { - postFixExpression = new GlslGetVarNode(varName); + + return left; + } + + private static @Nullable GlslNode parseRelationalExpression(GlslTokenReader reader) { + // shift_expression + // relational_expression LEFT_ANGLE shift_expression + // relational_expression RIGHT_ANGLE shift_expression + // relational_expression LE_OP shift_expression + // relational_expression GE_OP shift_expression + + GlslNode left = parseShiftExpression(reader); + if (left == null) { + return null; } - if (reader.canRead()) { - GlslLexer.Token token = reader.peek(); - switch (token.type()) { - case LEFT_BRACKET -> { - reader.skip(); - GlslNode index = parseExpression(reader); - reader.consume(GlslLexer.TokenType.RIGHT_BRACKET); - return new GlslGetArrayNode(postFixExpression, index); + while (reader.canRead()) { + int cursor = reader.getCursor(); + if (reader.tryConsume(GlslLexer.TokenType.LEFT_ANGLE)) { + GlslNode right = parseShiftExpression(reader); + if (right == null) { + reader.setCursor(cursor); + return left; } - case DOT -> { - reader.skip(); - String fieldSelection = reader.consume(GlslLexer.TokenType.IDENTIFIER).value(); - return new GlslGetFieldNode(postFixExpression, fieldSelection); + left = new GlslCompareNode(left, right, GlslCompareNode.Type.LESS); + continue; + } + if (reader.tryConsume(GlslLexer.TokenType.RIGHT_ANGLE)) { + GlslNode right = parseShiftExpression(reader); + if (right == null) { + reader.setCursor(cursor); + return left; } - case INC_OP -> { - reader.skip(); - return new GlslUnaryExpressionNode(GlslUnaryExpressionNode.Operator.POST_INCREMENT, postFixExpression); + left = new GlslCompareNode(left, right, GlslCompareNode.Type.GREATER); + continue; + } + if (reader.tryConsume(GlslLexer.TokenType.LE_OP)) { + GlslNode right = parseShiftExpression(reader); + if (right == null) { + reader.setCursor(cursor); + return left; } - case DEC_OP -> { - reader.skip(); - return new GlslUnaryExpressionNode(GlslUnaryExpressionNode.Operator.POST_DECREMENT, postFixExpression); + left = new GlslCompareNode(left, right, GlslCompareNode.Type.LEQUAL); + continue; + } + if (reader.tryConsume(GlslLexer.TokenType.GE_OP)) { + GlslNode right = parseShiftExpression(reader); + if (right == null) { + reader.setCursor(cursor); + return left; } + left = new GlslCompareNode(left, right, GlslCompareNode.Type.GEQUAL); + continue; } + break; } - return postFixExpression; + + return left; } - private static GlslNode parseConditionalExpression(TokenReader reader) throws GlslSyntaxException { - if (!reader.canRead()) { - throw reader.error("Expected expression"); + private static @Nullable GlslNode parseEqualityExpression(GlslTokenReader reader) { + // relational_expression + // equality_expression EQ_OP relational_expression + // equality_expression NE_OP relational_expression + + GlslNode left = parseRelationalExpression(reader); + if (left == null) { + return null; } - GlslNode left = parseUnaryExpression(reader); + while (reader.canRead()) { + int cursor = reader.getCursor(); + if (reader.tryConsume(GlslLexer.TokenType.EQ_OP)) { + GlslNode right = parseRelationalExpression(reader); + if (right == null) { + reader.setCursor(cursor); + return left; + } + left = new GlslCompareNode(left, right, GlslCompareNode.Type.EQUAL); + continue; + } + if (reader.tryConsume(GlslLexer.TokenType.NE_OP)) { + GlslNode right = parseRelationalExpression(reader); + if (right == null) { + reader.setCursor(cursor); + return left; + } + left = new GlslCompareNode(left, right, GlslCompareNode.Type.NOT_EQUAL); + continue; + } + break; + } - return left; // TODO + return left; } - private static GlslNode parseMultiplicativeExpression(TokenReader reader) throws GlslSyntaxException { - if (!reader.canRead()) { - throw reader.error("Expected expression"); - } + private static @Nullable GlslNode parseAndExpression(GlslTokenReader reader) { + // equality_expression + // and_expression AMPERSAND equality_expression + return parseSimpleExpression(reader, GlslParser::parseEqualityExpression, GlslLexer.TokenType.AMPERSAND, GlslAndNode::new); + } - GlslNode left = parseUnaryExpression(reader); + private static @Nullable GlslNode parseExclusiveOrExpression(GlslTokenReader reader) { + // and_expression + // exclusive_or_expression CARET and_expression + return parseSimpleExpression(reader, GlslParser::parseAndExpression, GlslLexer.TokenType.CARET, GlslExclusiveOrNode::new); + } - return left; // TODO + private static @Nullable GlslNode parseInclusiveOrExpression(GlslTokenReader reader) { + // exclusive_or_expression + // inclusive_or_expression VERTICAL_BAR exclusive_or_expression + return parseSimpleExpression(reader, GlslParser::parseExclusiveOrExpression, GlslLexer.TokenType.VERTICAL_BAR, GlslLogicalAndNode::new); } - private static GlslSpecifiedType parseFullySpecifiedType(TokenReader reader) throws GlslSyntaxException { - List typeQualifiers = new ArrayList<>(); - while (reader.canRead() && !reader.peek().type().isType()) { - GlslLexer.Token token = reader.peek(); - GlslLexer.TokenType type = token.type(); - - if (type.isStorageQualifier()) { - if (type == GlslLexer.TokenType.SUBROUTINE) { - GlslLexer.Token next = reader.peek(2); - if (next != null && next.type() == GlslLexer.TokenType.LEFT_PAREN) { - reader.skip(2); - List typeNames = new ArrayList<>(); - typeNames.add(reader.consume(GlslLexer.TokenType.IDENTIFIER).value()); - - while (reader.canRead() && reader.peek().type() == GlslLexer.TokenType.COMMA) { - reader.skip(); - typeNames.add(reader.consume(GlslLexer.TokenType.IDENTIFIER).value()); - } - - reader.consume(GlslLexer.TokenType.RIGHT_PAREN); - GlslTypeQualifier.storage(typeNames.toArray(String[]::new)); - } - } else { - GlslTypeQualifier.storage(new String[0]); - reader.skip(); - } - } else if (type.isLayoutQualifier()) { - reader.skip(); - reader.consume(GlslLexer.TokenType.LEFT_PAREN); + private static @Nullable GlslNode parseLogicalAndExpression(GlslTokenReader reader) { + // inclusive_or_expression + // logical_and_expression AND_OP inclusive_or_expression + return parseSimpleExpression(reader, GlslParser::parseInclusiveOrExpression, GlslLexer.TokenType.AND_OP, GlslLogicalAndNode::new); + } - typeQualifiers.add(parseLayout(reader)); - while (reader.canRead() && reader.peek().type() == GlslLexer.TokenType.COMMA) { - reader.skip(); - typeQualifiers.add(parseLayout(reader)); - } + private static @Nullable GlslNode parseLogicalXorExpression(GlslTokenReader reader) { + // logical_and_expression + // logical_xor_expression XOR_OP logical_and_expression + return parseSimpleExpression(reader, GlslParser::parseLogicalAndExpression, GlslLexer.TokenType.XOR_OP, GlslLogicalXorNode::new); + } - reader.consume(GlslLexer.TokenType.RIGHT_PAREN); - } else if (type.isPrecisionQualifier()) { - GlslTypeQualifier.Precision precision = switch (type) { - case HIGH_PRECISION -> GlslTypeQualifier.Precision.HIGH_PRECISION; - case MEDIUM_PRECISION -> GlslTypeQualifier.Precision.MEDIUM_PRECISION; - case LOW_PRECISION -> GlslTypeQualifier.Precision.LOW_PRECISION; - default -> throw new AssertionError(); - }; - typeQualifiers.add(precision); - reader.skip(); - } else if (type.isInterpolationQualifier()) { - GlslTypeQualifier.Interpolation interpolation = switch (type) { - case SMOOTH -> GlslTypeQualifier.Interpolation.SMOOTH; - case FLAT -> GlslTypeQualifier.Interpolation.FLAT; - case NOPERSPECTIVE -> GlslTypeQualifier.Interpolation.NOPERSPECTIVE; - default -> throw new AssertionError(); - }; - typeQualifiers.add(interpolation); - reader.skip(); - } else if (type.isInvariantQualifier()) { - typeQualifiers.add(GlslTypeQualifier.Invariant.INVARIANT); - reader.skip(); - } else if (type.isPreciseQualifier()) { - typeQualifiers.add(GlslTypeQualifier.Precise.PRECISE); - reader.skip(); - } else { - break; + private static @Nullable GlslNode parseLogicalOrExpression(GlslTokenReader reader) { + // logical_xor_expression + // logical_or_expression OR_OP logical_xor_expression + return parseSimpleExpression(reader, GlslParser::parseLogicalXorExpression, GlslLexer.TokenType.OR_OP, GlslLogicalOrNode::new); + } + + private static @Nullable GlslNode parseConditionalExpression(GlslTokenReader reader) { + // logical_or_expression + GlslNode logicalOr = parseLogicalOrExpression(reader); + if (logicalOr == null) { + return null; + } + + // logical_or_expression QUESTION condition COLON assignment_expression + int cursor = reader.getCursor(); + if (reader.tryConsume(GlslLexer.TokenType.QUESTION)) { + GlslNode first = parseExpression(reader); + if (first != null && reader.tryConsume(GlslLexer.TokenType.COLON)) { + GlslNode branch = parseAssignmentExpression(reader); + return new GlslConditionalNode(logicalOr, first, branch); } } - TypeSpecifier type = parseTypeSpecifier(reader); - return new GlslSpecifiedType(type, typeQualifiers.toArray(GlslTypeQualifier[]::new)); + reader.setCursor(cursor); + return logicalOr; } - private static GlslTypeQualifier parseLayout(TokenReader reader) throws GlslSyntaxException { - if (!reader.canRead()) { - throw reader.error("Expected IDENTIFIER or SHARED"); - } - - GlslLexer.Token token = reader.peek(); - switch (token.type()) { - case IDENTIFIER -> { + private static @Nullable GlslNode parseAssignmentExpression(GlslTokenReader reader) { + // unary_expression assignment_operator assignment_expression + int cursor = reader.getCursor(); + GlslNode unaryExpression = parseUnaryExpression(reader); + if (reader.canRead()) { + GlslAssignmentNode.Operand assignmentOperator = reader.peek().type().asAssignmentOperator(); + if (assignmentOperator != null) { reader.skip(); - String identifier = reader.consume(GlslLexer.TokenType.IDENTIFIER).value(); - if (reader.canConsume(GlslLexer.TokenType.EQUAL)) { - reader.skip(); - GlslNode expression = parseConditionalExpression(reader); - return GlslTypeQualifier.identifierLayout(identifier, expression); - } else { - return GlslTypeQualifier.identifierLayout(identifier, null); - } + GlslNode right = parseAssignmentExpression(reader); + return new GlslAssignmentNode(unaryExpression, right, assignmentOperator); } - case SHARED -> { - return GlslTypeQualifier.sharedLayout(); - } - default -> throw reader.error("Expected IDENTIFIER or SHARED, got: " + token); } + reader.setCursor(cursor); + + // conditional_expression + return parseConditionalExpression(reader); } - private static TypeSpecifier parseTypeSpecifier(TokenReader reader) throws GlslSyntaxException { - if (!reader.canRead()) { - throw reader.error("Expected type specifier"); + private static @Nullable GlslNode parseExpression(GlslTokenReader reader) { + int cursor = reader.getCursor(); + + // assignment_expression + // expression COMMA assignment_expression + List expressions = new ArrayList<>(); + while (reader.canRead()) { + GlslNode expression = parseAssignmentExpression(reader); + if (expression == null) { + reader.setCursor(cursor); + break; + } + + expressions.add(expression); + cursor = reader.getCursor(); + + if (!reader.tryConsume(GlslLexer.TokenType.COMMA)) { + break; + } } - GlslLexer.Token token = reader.peek(); - if (!token.type().isType()) { - throw reader.error("Invalid type specifier: " + token.value()); + + if (expressions.isEmpty()) { + return null; } - reader.skip(); - return TypeSpecifier.simple(token); + + return GlslNode.compound(expressions); } - private static class TokenReader { + private static @Nullable GlslNode parseDeclaration(GlslTokenReader reader) { + // function_prototype SEMICOLON + // init_declarator_list SEMICOLON + // PRECISION precision_qualifier type_specifier SEMICOLON + // type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE SEMICOLON + // type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON + // type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER array_specifier SEMICOLON + // type_qualifier SEMICOLON + // type_qualifier IDENTIFIER SEMICOLON + // type_qualifier IDENTIFIER identifier_list SEMICOLON - private final GlslLexer.Token[] tokens; - private int cursor; + int cursor = reader.getCursor(); - public TokenReader(GlslLexer.Token[] tokens) { - this.tokens = tokens; + // function_prototype SEMICOLON + GlslNode functionPrototype = parseFunctionPrototype(reader); + if (functionPrototype != null) { + if (reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { + return functionPrototype; + } + reader.setCursor(cursor); } - public String getString() { - StringBuilder builder = new StringBuilder(); - for (GlslLexer.Token token : this.tokens) { - builder.append(token.value()); + // init_declarator_list SEMICOLON + GlslNode initDeclaratorList = parseInitDeclaratorList(reader); + if (initDeclaratorList != null) { + if (reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { + return initDeclaratorList; } - return builder.toString(); + reader.setCursor(cursor); } - public boolean canRead(int length) { - return this.cursor + length <= this.tokens.length; + // PRECISION precision_qualifier type_specifier SEMICOLON + if (reader.tryConsume(GlslLexer.TokenType.PRECISION)) { + GlslTypeQualifier.Precision precisionQualifier = parsePrecisionQualifier(reader); + if (precisionQualifier != null) { + GlslTypeSpecifier typeSpecifier = parseTypeSpecifier(reader); + if (typeSpecifier != null && reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { + return new PrecisionNode(precisionQualifier, typeSpecifier); + } + } + reader.setCursor(cursor); } - public boolean canRead() { - return this.canRead(1); + List typeQualifier = parseTypeQualifiers(reader); + if (typeQualifier == null) { + return null; } - public int getCursorOffset() { - int offset = 0; - for (int i = 0; i <= Math.min(this.cursor, this.tokens.length - 1); i++) { - offset += this.tokens[i].value().length(); + // FIXME + cursor = reader.getCursor(); + if (reader.tryConsume(GlslLexer.TokenType.IDENTIFIER, GlslLexer.TokenType.LEFT_BRACE)) { + String identifier = reader.peek(-2).value(); + + GlslStructSpecifier structDeclaration = parseStructDeclaration(reader); + if (structDeclaration != null && reader.tryConsume(GlslLexer.TokenType.RIGHT_BRACE)) { + // type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE SEMICOLON + if (reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { + // SUCCESS + } + + if (reader.tryConsume(GlslLexer.TokenType.IDENTIFIER)) { + String label = reader.peek(-1).value(); + + // type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON + if (reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { + // SUCCESS + } + + // type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER array_specifier SEMICOLON + GlslTypeSpecifier arraySpecifier = parseArraySpecifier(reader, GlslTypeSpecifier.struct(structDeclaration)); + if (arraySpecifier != null && reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { + // SUCCESS + } + } } - return offset; } + reader.setCursor(cursor); - public @Nullable GlslLexer.Token peek() { - return this.peek(0); - } + // type_qualifier SEMICOLON + if(reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { + // FIXME struct declaration + } + + // type_qualifier IDENTIFIER SEMICOLON + // type_qualifier IDENTIFIER identifier_list SEMICOLON + + return null; // FIXME + } - public @Nullable GlslLexer.Token peek(int amount) { - return this.cursor + amount < this.tokens.length ? this.tokens[this.cursor + amount] : null; + private static @Nullable GlslNode parseIdentifierList(GlslTokenReader reader) { + // COMMA IDENTIFIER + // identifier_list COMMA IDENTIFIER + return null; // TODO + } + + private static @Nullable GlslFunctionHeader parseFunctionPrototype(GlslTokenReader reader) { + int cursor = reader.getCursor(); + + // fully_specified_type IDENTIFIER LEFT_PAREN RIGHT_PAREN + GlslSpecifiedType fullySpecifiedType = parseFullySpecifiedType(reader); + if (fullySpecifiedType != null && reader.tryConsume(GlslLexer.TokenType.IDENTIFIER, GlslLexer.TokenType.LEFT_PAREN, GlslLexer.TokenType.RIGHT_PAREN)) { + String name = reader.peek(-3).value(); + return new GlslFunctionHeader(name, fullySpecifiedType, new ArrayList<>()); } + reader.setCursor(cursor); - public boolean canConsume(GlslLexer.TokenType token) { - return this.canRead() && this.peek().type() == token; + // function_header_with_parameters RIGHT_PAREN + GlslFunctionHeader functionHeaderWithParameters = parseFunctionHeaderWithParameters(reader); + if (functionHeaderWithParameters != null) { + return functionHeaderWithParameters; } - public GlslLexer.Token consume(GlslLexer.TokenType token) throws GlslSyntaxException { - if (!this.canRead() || this.peek().type() != token) { - throw this.error("Expected " + token); + // fully_specified_type IDENTIFIER LEFT_PAREN parameter_declaration + fullySpecifiedType = parseFullySpecifiedType(reader); + if (fullySpecifiedType != null && reader.tryConsume(GlslLexer.TokenType.IDENTIFIER, GlslLexer.TokenType.LEFT_PAREN)) { + String name = reader.peek(-2).value(); + GlslParameterDeclaration parameterDeclaration = parseParameterDeclaration(reader); + if (parameterDeclaration != null && reader.tryConsume(GlslLexer.TokenType.RIGHT_PAREN)) { + return new GlslFunctionHeader(name, fullySpecifiedType, Collections.singletonList(parameterDeclaration)); } - this.cursor++; - return this.peek(-1); } + reader.setCursor(cursor); - public GlslSyntaxException error(String error) { - return new GlslSyntaxException(error, this.getString(), this.getCursorOffset()); + // function_header_with_parameters COMMA parameter_declaration + functionHeaderWithParameters = parseFunctionHeaderWithParameters(reader); + if (functionHeaderWithParameters != null && reader.tryConsume(GlslLexer.TokenType.COMMA)) { + GlslParameterDeclaration parameterDeclaration = parseParameterDeclaration(reader); + if (parameterDeclaration != null && reader.tryConsume(GlslLexer.TokenType.RIGHT_PAREN)) { + List parameters = functionHeaderWithParameters.getParameters(); + parameters.add(parameterDeclaration); + return functionHeaderWithParameters; + } } + reader.setCursor(cursor); + return null; + } - public void skip() { - this.cursor++; - } +// private static @Nullable GlslNode parseFunctionDeclarator(GlslTokenReader reader) { +// // function_header +// // function_header_with_parameters +// return null; // TODO +// } + + private static List parseParameterList(GlslTokenReader reader) { + List parameters = new ArrayList<>(); + int cursor = reader.getCursor(); + while (reader.canRead()) { + GlslParameterDeclaration parameterDeclaration = parseParameterDeclaration(reader); + if (parameterDeclaration == null) { + reader.setCursor(cursor); + break; + } - public void skip(int amount) { - this.cursor += amount; + cursor = reader.getCursor(); + if (!reader.tryConsume(GlslLexer.TokenType.COMMA)) { + break; + } } - public void skipWhitespace() { - while (this.canRead() && this.peek().type() == GlslLexer.TokenType.COMMENT) { - this.skip(); + return parameters; + } + + private static @Nullable GlslFunctionHeader parseFunctionHeaderWithParameters(GlslTokenReader reader) { + // fully_specified_type IDENTIFIER LEFT_PAREN parameter_declaration + // function_header_with_parameters COMMA parameter_declaration + + int cursor = reader.getCursor(); + GlslSpecifiedType fullySpecifiedType = parseFullySpecifiedType(reader); + if (fullySpecifiedType != null && reader.tryConsume(GlslLexer.TokenType.IDENTIFIER, GlslLexer.TokenType.LEFT_PAREN)) { + String name = reader.peek(-2).value(); + List parameters = parseParameterList(reader); + if (reader.tryConsume(GlslLexer.TokenType.LEFT_PAREN)) { + return new GlslFunctionHeader(name, fullySpecifiedType, parameters); } } + + reader.setCursor(cursor); + return null; + } + + private static @Nullable GlslParameterDeclaration parseParameterDeclarator(GlslTokenReader reader) { + // type_specifier IDENTIFIER + // type_specifier IDENTIFIER array_specifier + + int cursor = reader.getCursor(); + GlslTypeSpecifier typeSpecifier = parseTypeSpecifier(reader); + if (typeSpecifier == null) { + return null; + } + + if (!reader.tryConsume(GlslLexer.TokenType.IDENTIFIER)) { + reader.setCursor(cursor); + return null; + } + + String name = reader.peek(-1).value(); + GlslTypeSpecifier arraySpecifier = parseArraySpecifier(reader, typeSpecifier); + return new GlslParameterDeclaration(name, new GlslSpecifiedType(Objects.requireNonNullElse(arraySpecifier, typeSpecifier))); + + } + + private static @Nullable GlslParameterDeclaration parseParameterDeclaration(GlslTokenReader reader) { + int cursor = reader.getCursor(); + + // type_qualifier + List typeQualifiers = parseTypeQualifiers(reader); + if (typeQualifiers != null) { + // type_qualifier parameter_declarator + GlslParameterDeclaration parameterDeclarator = parseParameterDeclarator(reader); + if (parameterDeclarator != null) { + return parameterDeclarator.setQualifiers(typeQualifiers); + } + + // type_qualifier parameter_type_specifier + GlslTypeSpecifier parameterTypeSpecifier = parseTypeSpecifier(reader); + if (parameterTypeSpecifier != null) { + return new GlslParameterDeclaration(null, new GlslSpecifiedType(parameterTypeSpecifier, typeQualifiers)); + } + } + reader.setCursor(cursor); + + // parameter_declarator + GlslParameterDeclaration parameterDeclarator = parseParameterDeclarator(reader); + if (parameterDeclarator != null) { + return parameterDeclarator; + } + + // parameter_type_specifier + GlslTypeSpecifier parameterTypeSpecifier = parseTypeSpecifier(reader); + if (parameterTypeSpecifier != null) { + return new GlslParameterDeclaration(null, new GlslSpecifiedType(parameterTypeSpecifier)); + } + + return null; + } + + private static @Nullable GlslNode parseInitDeclaratorList(GlslTokenReader reader) { + // single_declaration + // init_declarator_list COMMA IDENTIFIER + // init_declarator_list COMMA IDENTIFIER array_specifier + // init_declarator_list COMMA IDENTIFIER array_specifier EQUAL initializer + // init_declarator_list COMMA IDENTIFIER EQUAL initializer + + List initDeclaratorList = new ArrayList<>(); + while (reader.canRead()) { + GlslNode singleDeclaration = parseSingleDeclaration(reader); + if (singleDeclaration == null) { + break; + } + + initDeclaratorList.add(singleDeclaration); + } + + if (initDeclaratorList.isEmpty()) { + return null; + } + return GlslNode.compound(initDeclaratorList); + } + + private static @Nullable GlslNode parseSingleDeclaration(GlslTokenReader reader) { + // fully_specified_type + // fully_specified_type IDENTIFIER + // fully_specified_type IDENTIFIER array_specifier + // fully_specified_type IDENTIFIER array_specifier EQUAL initializer + // fully_specified_type IDENTIFIER EQUAL initializer + + int cursor = reader.getCursor(); + GlslSpecifiedType fullySpecifiedType = parseFullySpecifiedType(reader); + if (fullySpecifiedType == null) { + return null; // TODO + } + + if (!reader.tryConsume(GlslLexer.TokenType.IDENTIFIER)) { + reader.setCursor(cursor); + return null; // TODO + } + + cursor = reader.getCursor(); + String name = reader.peek(-1).value(); + + GlslSpecifiedType arraySpecifier = parseArraySpecifier(reader, fullySpecifiedType); + if (arraySpecifier != null) { + if (!reader.tryConsume(GlslLexer.TokenType.EQUAL)) { + // fully_specified_type IDENTIFIER array_specifier + return new GlslNewNode(arraySpecifier, name, null); + } + + GlslNode initializer = parseInitializer(reader); + if (initializer != null) { + // fully_specified_type IDENTIFIER array_specifier EQUAL initializer + return new GlslNewNode(arraySpecifier, name, initializer); + } + } + reader.setCursor(cursor); + + if (reader.tryConsume(GlslLexer.TokenType.EQUAL)) { + GlslNode initializer = parseInitializer(reader); + if (initializer != null) { + // fully_specified_type IDENTIFIER EQUAL initializer + return new GlslNewNode(fullySpecifiedType, name, initializer); + } + } + + // fully_specified_type IDENTIFIER + reader.setCursor(cursor); + return new GlslNewNode(fullySpecifiedType, name, null); + } + + private static @Nullable GlslSpecifiedType parseFullySpecifiedType(GlslTokenReader reader) { + // type_specifier + // type_qualifier type_specifier + + // type_specifier + GlslTypeSpecifier typeSpecifier = parseTypeSpecifier(reader); + if (typeSpecifier != null) { + return new GlslSpecifiedType(typeSpecifier); + } + + // type_qualifier type_specifier + int cursor = reader.getCursor(); + List typeQualifiers = parseTypeQualifiers(reader); + if (typeQualifiers != null) { + typeSpecifier = parseTypeSpecifier(reader); + if (typeSpecifier != null) { + return new GlslSpecifiedType(typeSpecifier, typeQualifiers); + } + } + + reader.setCursor(cursor); + return null; + } + + private static @Nullable GlslNode parseInvariantQualifier(GlslTokenReader reader) { + // INVARIANT + return null; // TODO + } + + private static @Nullable GlslTypeQualifier.Interpolation parseInterpolationQualifier(GlslTokenReader reader) { + // SMOOTH + // FLAT + // NOPERSPECTIVE + + GlslLexer.TokenType type = reader.peekType(0); + GlslTypeQualifier.Interpolation interpolationQualifier = type != null ? type.asInterpolationQualifier() : null; + if (interpolationQualifier != null) { + reader.skip(); + return interpolationQualifier; + } + return null; + } + + private static @Nullable GlslTypeQualifier parseLayoutQualifier(GlslTokenReader reader) { + // LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN + if (!reader.tryConsume(GlslLexer.TokenType.LAYOUT, GlslLexer.TokenType.LEFT_PAREN)) { + return null; + } + + // layout_qualifier_id_list + int layoutCursor = reader.getCursor(); + List layoutQualifierIds = new ArrayList<>(); + while (reader.canRead()) { + GlslTypeQualifier.LayoutId qualifier = null; + if (reader.tryConsume(GlslLexer.TokenType.IDENTIFIER)) { + String identifier = reader.peek(-1).value(); + GlslNode expression = null; + + int cursor = reader.getCursor(); + if (reader.tryConsume(GlslLexer.TokenType.EQUAL)) { + expression = parseConditionalExpression(reader); + if (expression == null) { + reader.setCursor(cursor); + } + } + + qualifier = GlslTypeQualifier.identifierLayoutId(identifier, expression); + } + + if (qualifier != null && reader.tryConsume(GlslLexer.TokenType.SHARED)) { + qualifier = GlslTypeQualifier.sharedLayoutId(); + } + + if (qualifier == null) { + break; + } + + layoutQualifierIds.add(qualifier); + if (!reader.tryConsume(GlslLexer.TokenType.COMMA)) { + break; + } + } + + // RIGHT_PAREN + if (!reader.tryConsume(GlslLexer.TokenType.RIGHT_PAREN)) { + reader.setCursor(layoutCursor); + return null; + } + + return GlslTypeQualifier.layout(layoutQualifierIds.toArray(GlslTypeQualifier.LayoutId[]::new)); + } + + private static @Nullable List parseTypeQualifiers(GlslTokenReader reader) { + // single_type_qualifier + // type_qualifier single_type_qualifier + + List typeQualifiers = new ArrayList<>(); + while (reader.canRead()) { + // storage_qualifier + GlslTypeQualifier storageQualifier = parseStorageQualifier(reader); + if (storageQualifier != null) { + typeQualifiers.add(storageQualifier); + continue; + } + + // layout_qualifier + GlslTypeQualifier layoutQualifier = parseLayoutQualifier(reader); + if (layoutQualifier != null) { + typeQualifiers.add(layoutQualifier); + continue; + } + + // precision_qualifier + GlslTypeQualifier precisionQualifier = parsePrecisionQualifier(reader); + if (precisionQualifier != null) { + typeQualifiers.add(precisionQualifier); + continue; + } + + // interpolation_qualifier + GlslTypeQualifier interpolationQualifier = parseInterpolationQualifier(reader); + if (interpolationQualifier != null) { + typeQualifiers.add(interpolationQualifier); + continue; + } + + // invariant_qualifier + if (reader.tryConsume(GlslLexer.TokenType.INVARIANT)) { + typeQualifiers.add(GlslTypeQualifier.Invariant.INVARIANT); + continue; + } + + // precise_qualifier + if (reader.tryConsume(GlslLexer.TokenType.PRECISE)) { + typeQualifiers.add(GlslTypeQualifier.Precise.PRECISE); + continue; + } + + break; + } + + return typeQualifiers.isEmpty() ? null : typeQualifiers; + } + + private static @Nullable GlslTypeQualifier parseStorageQualifier(GlslTokenReader reader) { + GlslTypeQualifier.StorageType storageQualifier = reader.peek().type().asStorageQualifier(); + if (storageQualifier == null) { + return null; + } + reader.skip(); + + // SUBROUTINE LEFT_PAREN type_name_list RIGHT_PAREN + if (storageQualifier == GlslTypeQualifier.StorageType.SUBROUTINE) { + if (reader.tryConsume(GlslLexer.TokenType.LEFT_PAREN)) { + List typeNames = new ArrayList<>(); + while (reader.canRead()) { + if (!reader.tryConsume(GlslLexer.TokenType.IDENTIFIER)) { + break; + } + + typeNames.add(reader.peek(-1).value()); + if (!reader.tryConsume(GlslLexer.TokenType.COMMA)) { + break; + } + } + return GlslTypeQualifier.storage(typeNames.toArray(String[]::new)); + } + return GlslTypeQualifier.storage(new String[0]); + } + + return GlslTypeQualifier.storage(storageQualifier); + } + + private static @Nullable GlslNode parseTypeNameList(GlslTokenReader reader) { + // TYPE_NAME + // type_name_list COMMA TYPE_NAME + return null; // TODO + } + + private static @Nullable GlslTypeSpecifier parseTypeSpecifier(GlslTokenReader reader) { + // type_specifier_nonarray + // type_specifier_nonarray array_specifier + + if (!reader.canRead()) { + return null; + } + + // type_specifier_nonarray : VOID | FLOAT | DOUBLE | INT | UINT | BOOL | VEC2 | VEC3 | VEC4 | DVEC2 | DVEC3 | DVEC4 | BVEC2 | BVEC3 | BVEC4 | IVEC2 | IVEC3 | IVEC4 | UVEC2 | UVEC3 | UVEC4 | MAT2 | MAT3 | MAT4 | MAT2X2 | MAT2X3 | MAT2X4 | MAT3X2 | MAT3X3 | MAT3X4 | MAT4X2 | MAT4X3 | MAT4X4 | DMAT2 | DMAT3 | DMAT4 | DMAT2X2 | DMAT2X3 | DMAT2X4 | DMAT3X2 | DMAT3X3 | DMAT3X4 | DMAT4X2 | DMAT4X3 | DMAT4X4 | ATOMIC_UINT | SAMPLER2D | SAMPLER3D | SAMPLERCUBE | SAMPLER2DSHADOW | SAMPLERCUBESHADOW | SAMPLER2DARRAY | SAMPLER2DARRAYSHADOW | SAMPLERCUBEARRAY | SAMPLERCUBEARRAYSHADOW | ISAMPLER2D | ISAMPLER3D | ISAMPLERCUBE | ISAMPLER2DARRAY | ISAMPLERCUBEARRAY | USAMPLER2D | USAMPLER3D | USAMPLERCUBE | USAMPLER2DARRAY | USAMPLERCUBEARRAY | SAMPLER1D | SAMPLER1DSHADOW | SAMPLER1DARRAY | SAMPLER1DARRAYSHADOW | ISAMPLER1D | ISAMPLER1DARRAY | USAMPLER1D | USAMPLER1DARRAY | SAMPLER2DRECT | SAMPLER2DRECTSHADOW | ISAMPLER2DRECT | USAMPLER2DRECT | SAMPLERBUFFER | ISAMPLERBUFFER | USAMPLERBUFFER | SAMPLER2DMS | ISAMPLER2DMS | USAMPLER2DMS | SAMPLER2DMSARRAY | ISAMPLER2DMSARRAY | USAMPLER2DMSARRAY | IMAGE2D | IIMAGE2D | UIMAGE2D | IMAGE3D | IIMAGE3D | UIMAGE3D | IMAGECUBE | IIMAGECUBE | UIMAGECUBE | IMAGEBUFFER | IIMAGEBUFFER | UIMAGEBUFFER | IMAGE1D | IIMAGE1D | UIMAGE1D | IMAGE1DARRAY | IIMAGE1DARRAY | UIMAGE1DARRAY | IMAGE2DRECT | IIMAGE2DRECT | UIMAGE2DRECT | IMAGE2DARRAY | IIMAGE2DARRAY | UIMAGE2DARRAY | IMAGECUBEARRAY | IIMAGECUBEARRAY | UIMAGECUBEARRAY | IMAGE2DMS | IIMAGE2DMS | UIMAGE2DMS | IMAGE2DMSARRAY | IIMAGE2DMSARRAY | UIMAGE2DMSARRAY | struct_specifier | TYPE_NAME + GlslTypeSpecifier typeSpecifier; + GlslLexer.Token token = reader.peek(); + GlslTypeSpecifier.BuiltinType type = token.type().asBuiltinType(); + if (type != null) { + typeSpecifier = GlslTypeSpecifier.simple(type); + reader.skip(); + } else { + GlslStructSpecifier structSpecifier = parseStructSpecifier(reader); + if (structSpecifier != null) { + typeSpecifier = GlslTypeSpecifier.struct(structSpecifier); + } else { + if (token.type() == GlslLexer.TokenType.IDENTIFIER) { + reader.skip(); + typeSpecifier = GlslTypeSpecifier.named(token.value()); + } else { + return null; + } + } + } + + // type_specifier_nonarray array_specifier + GlslTypeSpecifier arraySpecifier = parseArraySpecifier(reader, typeSpecifier); + if (arraySpecifier != null) { + return arraySpecifier; + } + + return typeSpecifier; + } + + private static @Nullable GlslSpecifiedType parseArraySpecifier(GlslTokenReader reader, GlslSpecifiedType type) { + GlslTypeSpecifier arraySpecifier = parseArraySpecifier(reader, type.getType()); + if (arraySpecifier != null) { + return new GlslSpecifiedType(arraySpecifier, type.getQualifiers()); + } + + return null; + } + + private static @Nullable GlslTypeSpecifier parseArraySpecifier(GlslTokenReader reader, GlslTypeSpecifier type) { + int cursor = reader.getCursor(); + + if (reader.tryConsume(GlslLexer.TokenType.LEFT_BRACKET)) { + // LEFT_BRACKET RIGHT_BRACKET + if (reader.tryConsume(GlslLexer.TokenType.RIGHT_BRACKET)) { + return GlslTypeSpecifier.array(type, null); + } + + // LEFT_BRACKET conditional_expression RIGHT_BRACKET + GlslNode conditionalExpression = parseConditionalExpression(reader); + if (conditionalExpression != null && reader.tryConsume(GlslLexer.TokenType.RIGHT_BRACKET)) { + return GlslTypeSpecifier.array(type, conditionalExpression); + } + + reader.setCursor(cursor); + } + + // Impossible ??? + // array_specifier LEFT_BRACKET RIGHT_BRACKET + // array_specifier LEFT_BRACKET conditional_expression RIGHT_BRACKET + + return null; + } + + private static @Nullable GlslTypeQualifier.Precision parsePrecisionQualifier(GlslTokenReader reader) { + // HIGH_PRECISION + // MEDIUM_PRECISION + // LOW_PRECISION + + GlslLexer.TokenType type = reader.peekType(0); + GlslTypeQualifier.Precision precisionQualifier = type != null ? type.asPrecisionQualifier() : null; + if (precisionQualifier != null) { + reader.skip(); + return precisionQualifier; + } + return null; + } + + private static @Nullable GlslStructSpecifier parseStructSpecifier(GlslTokenReader reader) { + // STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE + // STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE + return null; // TODO + } + + private static @Nullable GlslNode parseStructDeclarationList(GlslTokenReader reader) { + // struct_declaration + // struct_declaration_list struct_declaration + return null; // TODO + } + + private static @Nullable GlslStructSpecifier parseStructDeclaration(GlslTokenReader reader) { + // type_specifier struct_declarator_list SEMICOLON + // type_qualifier type_specifier struct_declarator_list SEMICOLON + return null; // TODO + } + + private static @Nullable GlslNode parseStructDeclaratorList(GlslTokenReader reader) { + // struct_declarator + // struct_declarator_list COMMA struct_declarator + return null; // TODO + } + + private static @Nullable GlslNode parseStructDeclarator(GlslTokenReader reader) { + // IDENTIFIER + // IDENTIFIER array_specifier + return null; // TODO + } + + private static @Nullable GlslNode parseInitializer(GlslTokenReader reader) { + // assignment_expression + GlslNode assignmentExpression = parseAssignmentExpression(reader); + if (assignmentExpression != null) { + return assignmentExpression; + } + + // LEFT_BRACE initializer_list RIGHT_BRACE + // LEFT_BRACE initializer_list COMMA RIGHT_BRACE + int cursor = reader.getCursor(); + if (reader.tryConsume(GlslLexer.TokenType.LEFT_BRACE)) { + List initializerList = parseInitializerList(reader); + reader.tryConsume(GlslLexer.TokenType.COMMA); + if (reader.tryConsume(GlslLexer.TokenType.RIGHT_BRACE)) { + return GlslNode.compound(initializerList); + } + } + + reader.setCursor(cursor); + return null; + } + + private static List parseInitializerList(GlslTokenReader reader) { + // initializer + // initializer_list COMMA initializer + + int cursor = reader.getCursor(); + List initializers = new ArrayList<>(); + while (reader.canRead()) { + GlslNode statement = parseStatement(reader); + if (statement == null) { + reader.setCursor(cursor); + break; + } + + initializers.add(statement); + cursor = reader.getCursor(); + + if (!reader.tryConsume(GlslLexer.TokenType.COMMA)) { + break; + } + } + + return initializers; + } + + private static @Nullable GlslNode parseStatement(GlslTokenReader reader) { + // compound_statement + // simple_statement + + int cursor = reader.getCursor(); + + // compound_statement + GlslNode compoundStatement = parseCompoundStatement(reader); + if (compoundStatement != null) { + return compoundStatement; + } + reader.setCursor(cursor); + + // simple_statement + GlslNode simpleStatement = parseSimpleStatement(reader); + if (simpleStatement != null) { + return simpleStatement; + } + reader.setCursor(cursor); + + return null; + } + + private static @Nullable GlslNode parseSimpleStatement(GlslTokenReader reader) { + // declaration_statement + // expression_statement + // selection_statement + // switch_statement + // case_label + // iteration_statement + // jump_statement + + int cursor = reader.getCursor(); + GlslNode statement; + + // declaration_statement -> declaration + statement = parseDeclaration(reader); + if (statement != null) { + return statement; + } + reader.setCursor(cursor); + + // expression_statement + statement = parseExpressionStatement(reader); + if (statement != null) { + return statement; + } + reader.setCursor(cursor); + + // selection_statement + statement = parseSelectionStatement(reader); + if (statement != null) { + return statement; + } + reader.setCursor(cursor); + + statement = parseSwitchStatement(reader); + if (statement != null) { + return statement; + } + reader.setCursor(cursor); + + statement = parseCaseLabel(reader); + if (statement != null) { + return statement; + } + reader.setCursor(cursor); + + statement = parseIterationStatement(reader); + if (statement != null) { + return statement; + } + reader.setCursor(cursor); + + statement = parseJumpStatement(reader); + if (statement != null) { + return statement; + } + reader.setCursor(cursor); + + return null; + } + + private static @Nullable GlslNode parseCompoundStatement(GlslTokenReader reader) { + // LEFT_BRACE RIGHT_BRACE + // LEFT_BRACE statement_list RIGHT_BRACE + + int cursor = reader.getCursor(); + if (!reader.tryConsume(GlslLexer.TokenType.LEFT_BRACE)) { + reader.setCursor(cursor); + return null; + } + + if (reader.tryConsume(GlslLexer.TokenType.RIGHT_BRACE)) { + return GlslEmptyNode.INSTANCE; + } + + // statement_list + List statements = parseStatementList(reader); + + if (!reader.tryConsume(GlslLexer.TokenType.RIGHT_BRACE)) { + reader.setCursor(cursor); + return null; + } + + return GlslNode.compound(statements); + } + + private static @Nullable GlslNode parseStatementNoNewScope(GlslTokenReader reader) { + // compound_statement_no_new_scope + GlslNode statementNoNewScope = parseCompoundStatementNoNewScope(reader); + if (statementNoNewScope != null) { + return statementNoNewScope; + } + + // simple_statement + return parseSimpleStatement(reader); + } + + private static @Nullable GlslNode parseCompoundStatementNoNewScope(GlslTokenReader reader) { + // LEFT_BRACE RIGHT_BRACE + // LEFT_BRACE statement_list RIGHT_BRACE + + int cursor = reader.getCursor(); + if (!reader.tryConsume(GlslLexer.TokenType.LEFT_BRACE)) { + return null; + } + + List statements = parseStatementList(reader); + if (!reader.tryConsume(GlslLexer.TokenType.RIGHT_BRACE)) { + reader.setCursor(cursor); + return null; + } + + return GlslNode.compound(statements); + } + + private static List parseStatementList(GlslTokenReader reader) { + List statements = new ArrayList<>(); + while (reader.canRead()) { + GlslNode statement = parseStatement(reader); + if (statement == null) { + break; + } + + statements.add(statement); + } + + return statements; + } + + private static @Nullable GlslNode parseExpressionStatement(GlslTokenReader reader) { + if (reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { + return GlslEmptyNode.INSTANCE; + } + + int cursor = reader.getCursor(); + GlslNode condition = parseCondition(reader); + if (condition != null && reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { + return condition; + } + reader.setCursor(cursor); + return null; + } + + private static @Nullable GlslNode parseSelectionStatement(GlslTokenReader reader) { + // IF LEFT_PAREN condition RIGHT_PAREN statement ELSE statement + // IF LEFT_PAREN condition RIGHT_PAREN statement + + int cursor = reader.getCursor(); + if (!reader.tryConsume(GlslLexer.TokenType.IF, GlslLexer.TokenType.LEFT_PAREN)) { + reader.setCursor(cursor); + return null; + } + + GlslNode expression = parseExpressionStatement(reader); + if (expression == null) { + reader.setCursor(cursor); + return null; + } + + if (!reader.tryConsume(GlslLexer.TokenType.RIGHT_PAREN)) { + reader.setCursor(cursor); + return null; + } + + // selection_rest_statement + GlslNode statement = parseStatement(reader); + if (statement == null) { + reader.setCursor(cursor); + return null; + } + + cursor = reader.getCursor(); + // statement ELSE statement + + if (reader.tryConsume(GlslLexer.TokenType.ELSE)) { + GlslNode otherStatement = parseStatement(reader); + if (otherStatement != null) { + return new GlslSelectionNode(expression, statement, otherStatement); + } + + reader.setCursor(cursor); + return null; + } + + reader.setCursor(cursor); + return new GlslSelectionNode(expression, statement, null); + } + + private static @Nullable GlslNode parseCondition(GlslTokenReader reader) { + // expression + GlslNode expression = parseExpression(reader); + if (expression != null) { + return expression; + } + + // fully_specified_type IDENTIFIER EQUAL initializer + int cursor = reader.getCursor(); + GlslSpecifiedType type = parseFullySpecifiedType(reader); + if (type != null && reader.tryConsume(GlslLexer.TokenType.IDENTIFIER, GlslLexer.TokenType.EQUAL)) { + String name = reader.peek(-2).value(); + GlslNode initializer = parseInitializer(reader); + if (initializer != null) { + return new GlslNewNode(type, name, initializer); + } + } + + reader.setCursor(cursor); + return null; + } + + private static @Nullable GlslNode parseSwitchStatement(GlslTokenReader reader) { + // SWITCH LEFT_PAREN condition RIGHT_PAREN LEFT_BRACE switch_statement_list RIGHT_BRACE + int cursor = reader.getCursor(); + if (reader.tryConsume(GlslLexer.TokenType.SWITCH, GlslLexer.TokenType.LEFT_PAREN)) { + GlslNode condition = parseCondition(reader); + if (condition != null && reader.tryConsume(GlslLexer.TokenType.RIGHT_PAREN, GlslLexer.TokenType.LEFT_BRACE)) { + List statements = parseStatementList(reader); + if (reader.tryConsume(GlslLexer.TokenType.RIGHT_BRACE)) { + return new GlslSwitchNode(condition, statements); + } + } + } + reader.setCursor(cursor); + return null; + } + + private static @Nullable GlslCaseLabelNode parseCaseLabel(GlslTokenReader reader) { + int cursor = reader.getCursor(); + + // CASE condition COLON + if (reader.tryConsume(GlslLexer.TokenType.CASE)) { + GlslNode condition = parseCondition(reader); + if (condition != null && reader.tryConsume(GlslLexer.TokenType.COLON)) { + return new GlslCaseLabelNode(condition); + } + } + reader.setCursor(cursor); + + if (reader.tryConsume(GlslLexer.TokenType.DEFAULT, GlslLexer.TokenType.COLON)) { + return new GlslCaseLabelNode(null); + } + return null; + } + + private static @Nullable GlslNode parseIterationStatement(GlslTokenReader reader) { + // WHILE LEFT_PAREN condition RIGHT_PAREN statement_no_new_scope + // DO statement WHILE LEFT_PAREN condition RIGHT_PAREN SEMICOLON + // FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope + return null; // TODO + } + + private static @Nullable GlslNode parseForInitStatement(GlslTokenReader reader) { + // expression_statement + // declaration_statement + return null; // TODO + } + + private static @Nullable GlslNode parseConditionopt(GlslTokenReader reader) { + // condition + return null; // TODO + } + + private static @Nullable GlslNode parseForRestStatement(GlslTokenReader reader) { + // conditionopt SEMICOLON + // conditionopt SEMICOLON condition + return null; // TODO + } + + private static @Nullable GlslNode parseJumpStatement(GlslTokenReader reader) { + // CONTINUE SEMICOLON + // BREAK SEMICOLON + // RETURN SEMICOLON + // RETURN condition SEMICOLON + // DISCARD SEMICOLON + return null; // TODO + } + + private static @Nullable GlslFunction parseFunctionDefinition(GlslTokenReader reader) { + int cursor = reader.getCursor(); + + GlslFunctionHeader functionPrototype = parseFunctionPrototype(reader); + if (functionPrototype == null) { + return null; + } + + GlslNode statement = parseCompoundStatementNoNewScope(reader); + if (statement == null) { + reader.setCursor(cursor); + return null; + } + + // function_prototype compound_statement_no_new_scope + return new GlslFunction(functionPrototype, statement); } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/GlslTokenReader.java b/common/src/main/java/foundry/veil/impl/glsl/GlslTokenReader.java new file mode 100644 index 00000000..fe8c2175 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/GlslTokenReader.java @@ -0,0 +1,100 @@ +package foundry.veil.impl.glsl; + +import org.jetbrains.annotations.Nullable; + +public class GlslTokenReader { + + private final GlslLexer.Token[] tokens; + private int cursor; + + public GlslTokenReader(GlslLexer.Token[] tokens) { + this.tokens = tokens; + } + + private int getCursorOffset() { + int offset = -1; + for (int i = 0; i <= Math.min(this.cursor, this.tokens.length - 1); i++) { + offset += this.tokens[i].value().length() + 1; + } + return offset; + } + + public String getString() { + StringBuilder builder = new StringBuilder(); + for (GlslLexer.Token token : this.tokens) { + builder.append(token.value()).append(' '); + } + return builder.toString().trim(); + } + + public boolean canRead(int length) { + return this.cursor + length <= this.tokens.length; + } + + public boolean canRead() { + return this.canRead(1); + } + + public @Nullable GlslLexer.Token peek() { + return this.peek(0); + } + + public @Nullable GlslLexer.Token peek(int amount) { + return this.cursor + amount < this.tokens.length ? this.tokens[this.cursor + amount] : null; + } + + public @Nullable GlslLexer.TokenType peekType(int amount) { + return this.cursor + amount < this.tokens.length ? this.tokens[this.cursor + amount].type() : null; + } + + public boolean canConsume(GlslLexer.TokenType token) { + return this.canRead() && this.peek().type() == token; + } + + public GlslLexer.Token consume(GlslLexer.TokenType token) throws GlslSyntaxException { + if (!this.canRead() || this.peek().type() != token) { + throw this.error("Expected " + token); + } + this.cursor++; + return this.peek(-1); + } + + public boolean tryConsume(GlslLexer.TokenType... tokens) { + if (!this.canRead(tokens.length)) { + return false; + } + + for (int i = 0; i < tokens.length; i++) { + if (this.peek(i).type() != tokens[i]) { + return false; + } + } + this.cursor += tokens.length; + return true; + } + + public GlslSyntaxException error(String error) { + return new GlslSyntaxException(error, this.getString(), this.getCursorOffset()); + } + + public void skip() { + this.cursor++; + } + + public void skip(int amount) { + this.cursor += amount; + } + + public int getCursor() { + return this.cursor; + } + + public void setCursor(int cursor) { + this.cursor = cursor; + } + + @Override + public String toString() { + return "GlslTokenReader{cursor=" + this.cursor + ", token=" + this.peek() + "}"; + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslParameterDeclaration.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslParameterDeclaration.java new file mode 100644 index 00000000..49a9e091 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslParameterDeclaration.java @@ -0,0 +1,37 @@ +package foundry.veil.impl.glsl.grammar; + +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +public class GlslParameterDeclaration { + + private String name; + private GlslSpecifiedType type; + + public GlslParameterDeclaration(@Nullable String name, GlslSpecifiedType type) { + this.name = name; + this.type = type; + } + + public String getName() { + return this.name; + } + + public GlslSpecifiedType getType() { + return this.type; + } + + public void setName(@Nullable String name) { + this.name = name; + } + + public void setType(GlslSpecifiedType type) { + this.type = type; + } + + public GlslParameterDeclaration setQualifiers(Collection qualifiers) { + this.type.setQualifiers(qualifiers); + return this; + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslSpecifiedType.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslSpecifiedType.java new file mode 100644 index 00000000..ea001a75 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslSpecifiedType.java @@ -0,0 +1,62 @@ +package foundry.veil.impl.glsl.grammar; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * Specifies the full operand of something in GLSL in addition to all qualifiers. + * + * @param type The operand of the field, method, etc + * @param qualifiers The qualifiers applied to it, for example layout() or flat + */ +public class GlslSpecifiedType implements GlslType { + + private GlslTypeSpecifier type; + private final List qualifiers; + + public GlslSpecifiedType(GlslTypeSpecifier type) { + this.type = type; + this.qualifiers = new ArrayList<>(); + } + + public GlslSpecifiedType(GlslTypeSpecifier type, Collection qualifiers) { + this(type); + this.qualifiers.addAll(qualifiers); + } + + public GlslSpecifiedType(GlslTypeSpecifier type, GlslTypeQualifier... qualifiers) { + this(type); + this.qualifiers.addAll(Arrays.asList(qualifiers)); + } + + public GlslTypeSpecifier getType() { + return this.type; + } + + public List getQualifiers() { + return this.qualifiers; + } + + public GlslSpecifiedType setType(GlslTypeSpecifier type) { + this.type = type; + return this; + } + + public GlslSpecifiedType setQualifiers(Collection qualifiers) { + this.qualifiers.clear(); + this.qualifiers.addAll(qualifiers); + return this; + } + + @Override + public String toString() { + return "GlslSpecifiedType[specifier=" + this.type + ", qualifiers=" + this.qualifiers; + } + + @Override + public GlslSpecifiedType asGlslSpecifiedType() { + return this; + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructSpecifier.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructSpecifier.java new file mode 100644 index 00000000..2a7e7006 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructSpecifier.java @@ -0,0 +1,5 @@ +package foundry.veil.impl.glsl.grammar; + +// TODO +public record GlslStructSpecifier() { +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslType.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslType.java new file mode 100644 index 00000000..8c0e9bbf --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslType.java @@ -0,0 +1,7 @@ +package foundry.veil.impl.glsl.grammar; + +public interface GlslType { + + GlslSpecifiedType asGlslSpecifiedType(); + +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeQualifier.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeQualifier.java new file mode 100644 index 00000000..bf0994ea --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeQualifier.java @@ -0,0 +1,95 @@ +package foundry.veil.impl.glsl.grammar; + +import foundry.veil.impl.glsl.node.GlslNode; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; + +public interface GlslTypeQualifier { + + static GlslTypeQualifier storage(Storage.StorageType storageType) { + if (storageType == StorageType.SUBROUTINE) { + throw new IllegalArgumentException("Subroutine storage must specify operand names"); + } + return new Storage(storageType, null); + } + + static GlslTypeQualifier storage(String[] typeNames) { + return new Storage(Storage.StorageType.SUBROUTINE, typeNames); + } + + static Layout layout(LayoutId... ids) { + return new Layout(ids); + } + + static LayoutId identifierLayoutId(String identifier, @Nullable GlslNode constantExpression) { + return new LayoutId(identifier, constantExpression); + } + + static LayoutId sharedLayoutId() { + return new LayoutId("shared", null); + } + + /** + * A storage qualifier for a operand. + * + * @param storageType The operand of storage qualifier + * @param typeNames The operand names for subroutines. null if {@link #storageType} is not SUBROUTINE + * @author Ocelot + */ + record Storage(StorageType storageType, @Nullable String[] typeNames) implements GlslTypeQualifier { + @Override + public String toString() { + return this.storageType == StorageType.SUBROUTINE ? "Storage[type=SUBROUTINE, typeNames=" + Arrays.toString(this.typeNames) + "]" : "Storage[type=" + this.storageType + ']'; + } + } + + record Layout(LayoutId[] qualifierIds) implements GlslTypeQualifier { + } + + record LayoutId(String identifier, @Nullable GlslNode constantExpression) { + + public boolean shared() { + return "shared".equals(this.identifier); + } + } + + enum StorageType { + CONST, + IN, + OUT, + INOUT, + CENTROID, + PATCH, + SAMPLE, + UNIFORM, + BUFFER, + SHARED, + COHERENT, + VOLATILE, + RESTRICT, + READONLY, + WRITEONLY, + SUBROUTINE + } + + enum Precision implements GlslTypeQualifier { + HIGH_PRECISION, + MEDIUM_PRECISION, + LOW_PRECISION + } + + enum Interpolation implements GlslTypeQualifier { + SMOOTH, + FLAT, + NOPERSPECTIVE + } + + enum Invariant implements GlslTypeQualifier { + INVARIANT + } + + enum Precise implements GlslTypeQualifier { + PRECISE + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeSpecifier.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeSpecifier.java new file mode 100644 index 00000000..7c29d2a7 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeSpecifier.java @@ -0,0 +1,162 @@ +package foundry.veil.impl.glsl.grammar; + +import foundry.veil.impl.glsl.node.GlslNode; +import org.jetbrains.annotations.Nullable; + +public interface GlslTypeSpecifier extends GlslType { + + static GlslTypeSpecifier simple(BuiltinType type) { + return new Simple(type); + } + + static GlslTypeSpecifier struct(GlslStructSpecifier structSpecifier) { + return new Struct(structSpecifier); + } + + static GlslTypeSpecifier named(String name) { + return new Name(name); + } + + static GlslTypeSpecifier array(GlslTypeSpecifier specifier, @Nullable GlslNode size) { + return new Array(specifier, size); + } + + @Override + default GlslSpecifiedType asGlslSpecifiedType() { + return new GlslSpecifiedType(this); + } + + record Simple(BuiltinType type) implements GlslTypeSpecifier { + } + + record Struct(GlslStructSpecifier structSpecifier) implements GlslTypeSpecifier { + } + + record Name(String name) implements GlslTypeSpecifier { + } + + record Array(GlslTypeSpecifier specifier, @Nullable GlslNode size) implements GlslTypeSpecifier { + } + + enum BuiltinType { + VOID, + FLOAT, + DOUBLE, + INT, + UINT, + BOOL, + VEC2, + VEC3, + VEC4, + DVEC2, + DVEC3, + DVEC4, + BVEC2, + BVEC3, + BVEC4, + IVEC2, + IVEC3, + IVEC4, + UVEC2, + UVEC3, + UVEC4, + MAT2, + MAT3, + MAT4, + MAT2X2, + MAT2X3, + MAT2X4, + MAT3X2, + MAT3X3, + MAT3X4, + MAT4X2, + MAT4X3, + MAT4X4, + DMAT2, + DMAT3, + DMAT4, + DMAT2X2, + DMAT2X3, + DMAT2X4, + DMAT3X2, + DMAT3X3, + DMAT3X4, + DMAT4X2, + DMAT4X3, + DMAT4X4, + ATOMIC_UINT, + SAMPLER2D, + SAMPLER3D, + SAMPLERCUBE, + SAMPLER2DSHADOW, + SAMPLERCUBESHADOW, + SAMPLER2DARRAY, + SAMPLER2DARRAYSHADOW, + SAMPLERCUBEARRAY, + SAMPLERCUBEARRAYSHADOW, + ISAMPLER2D, + ISAMPLER3D, + ISAMPLERCUBE, + ISAMPLER2DARRAY, + ISAMPLERCUBEARRAY, + USAMPLER2D, + USAMPLER3D, + USAMPLERCUBE, + USAMPLER2DARRAY, + USAMPLERCUBEARRAY, + SAMPLER1D, + SAMPLER1DSHADOW, + SAMPLER1DARRAY, + SAMPLER1DARRAYSHADOW, + ISAMPLER1D, + ISAMPLER1DARRAY, + USAMPLER1D, + USAMPLER1DARRAY, + SAMPLER2DRECT, + SAMPLER2DRECTSHADOW, + ISAMPLER2DRECT, + USAMPLER2DRECT, + SAMPLERBUFFER, + ISAMPLERBUFFER, + USAMPLERBUFFER, + SAMPLER2DMS, + ISAMPLER2DMS, + USAMPLER2DMS, + SAMPLER2DMSARRAY, + ISAMPLER2DMSARRAY, + USAMPLER2DMSARRAY, + IMAGE2D, + IIMAGE2D, + UIMAGE2D, + IMAGE3D, + IIMAGE3D, + UIMAGE3D, + IMAGECUBE, + IIMAGECUBE, + UIMAGECUBE, + IMAGEBUFFER, + IIMAGEBUFFER, + UIMAGEBUFFER, + IMAGE1D, + IIMAGE1D, + UIMAGE1D, + IMAGE1DARRAY, + IIMAGE1DARRAY, + UIMAGE1DARRAY, + IMAGE2DRECT, + IIMAGE2DRECT, + UIMAGE2DRECT, + IMAGE2DARRAY, + IIMAGE2DARRAY, + UIMAGE2DARRAY, + IMAGECUBEARRAY, + IIMAGECUBEARRAY, + UIMAGECUBEARRAY, + IMAGE2DMS, + IIMAGE2DMS, + UIMAGE2DMS, + IMAGE2DMSARRAY, + IIMAGE2DMSARRAY, + UIMAGE2DMSARRAY + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslVersion.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslVersion.java similarity index 87% rename from common/src/main/java/foundry/veil/impl/glsl/node/GlslVersion.java rename to common/src/main/java/foundry/veil/impl/glsl/grammar/GlslVersion.java index af914d93..b35a077c 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/GlslVersion.java +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslVersion.java @@ -1,4 +1,4 @@ -package foundry.veil.impl.glsl.node; +package foundry.veil.impl.glsl.grammar; public record GlslVersion(int version, boolean core) { diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/DeclarationNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/DeclarationNode.java deleted file mode 100644 index 4062871d..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/node/DeclarationNode.java +++ /dev/null @@ -1,24 +0,0 @@ -package foundry.veil.impl.glsl.node; - -import foundry.veil.impl.glsl.GlslLexer; - -public class DeclarationNode implements GlslNode { - - private final GlslLexer.Token type; - private final String name; - - public DeclarationNode(GlslLexer.Token type, String name) { - this.type = type; - this.name = name; - } - - @Override - public void visit(GlslVisitor visitor) { - - } - - @Override - public String toString() { - return this.type.value() + " " + this.name; - } -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslAssignableNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslAssignableNode.java deleted file mode 100644 index 9262c31c..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/node/GlslAssignableNode.java +++ /dev/null @@ -1,20 +0,0 @@ -package foundry.veil.impl.glsl.node; - -public interface GlslAssignableNode extends GlslNode { - - GlslNode toAssignment(Assignment assignment, GlslNode value); - - enum Assignment { - EQUAL, - MUL_ASSIGN, - DIV_ASSIGN, - MOD_ASSIGN, - ADD_ASSIGN, - SUB_ASSIGN, - LEFT_ASSIGN, - RIGHT_ASSIGN, - AND_ASSIGN, - XOR_ASSIGN, - OR_ASSIGN, - } -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslCompoundNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslCompoundNode.java new file mode 100644 index 00000000..3abf8a02 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslCompoundNode.java @@ -0,0 +1,13 @@ +package foundry.veil.impl.glsl.node; + +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +import java.util.List; + +public record GlslCompoundNode(List children) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslEmptyNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslEmptyNode.java new file mode 100644 index 00000000..8fa4b035 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslEmptyNode.java @@ -0,0 +1,11 @@ +package foundry.veil.impl.glsl.node; + +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +public enum GlslEmptyNode implements GlslNode { + INSTANCE; + + @Override + public void visit(GlslVisitor visitor) { + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslNode.java index 34642360..ccbc5c4e 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/GlslNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslNode.java @@ -1,5 +1,9 @@ package foundry.veil.impl.glsl.node; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -10,4 +14,24 @@ public interface GlslNode { default Collection children() { return Collections.emptySet(); } + + static GlslNode compound(Collection nodes) { + if (nodes.isEmpty()) { + return GlslEmptyNode.INSTANCE; + } + if (nodes.size() == 1) { + return nodes.iterator().next(); + } + return new GlslCompoundNode(new ArrayList<>(nodes)); + } + + static GlslNode compound(GlslNode... nodes) { + if (nodes.length == 0) { + return GlslEmptyNode.INSTANCE; + } + if (nodes.length == 1) { + return nodes[0]; + } + return new GlslCompoundNode(new ArrayList<>(Arrays.asList(nodes))); + } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java index 587dcf8f..f70fc18d 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java @@ -1,11 +1,20 @@ package foundry.veil.impl.glsl.node; +import foundry.veil.impl.glsl.grammar.GlslVersion; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + public class GlslTree { private GlslVersion version; + private final List body; - public GlslTree(GlslVersion version) { + public GlslTree(GlslVersion version, Collection body) { this.version = version; + this.body = new ArrayList<>(body); } public void visit(GlslVisitor visitor) { @@ -16,7 +25,16 @@ public GlslVersion getVersion() { return this.version; } + public List getBody() { + return this.body; + } + public void setVersion(GlslVersion version) { this.version = version; } + + @Override + public String toString() { + return "GlslTree{version=" + this.version + ", body=" + this.body + '}'; + } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslType.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslType.java deleted file mode 100644 index fc0b3ed9..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/node/GlslType.java +++ /dev/null @@ -1,23 +0,0 @@ -package foundry.veil.impl.glsl.node; - -public record GlslType() { - - public enum StorageQualifier { - CONST, - IN, - OUT, - INOUT, - CENTROID, - PATCH, - SAMPLE, - UNIFORM, - BUFFER, - SHARED, - COHERENT, - VOLATILE, - RESTRICT, - READONLY, - WRITEONLY, - SUBROUTINE - } -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslVisitor.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslVisitor.java deleted file mode 100644 index d971205a..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/node/GlslVisitor.java +++ /dev/null @@ -1,4 +0,0 @@ -package foundry.veil.impl.glsl.node; - -public interface GlslVisitor { -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslCaseLabelNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslCaseLabelNode.java new file mode 100644 index 00000000..e3f860f5 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslCaseLabelNode.java @@ -0,0 +1,17 @@ +package foundry.veil.impl.glsl.node.branch; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; +import org.jetbrains.annotations.Nullable; + +public record GlslCaseLabelNode(@Nullable GlslNode condition) implements GlslNode { + + public boolean isDefault() { + return this.condition == null; + } + + @Override + public void visit(GlslVisitor visitor) { + + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSelectionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSelectionNode.java new file mode 100644 index 00000000..44a295af --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSelectionNode.java @@ -0,0 +1,21 @@ +package foundry.veil.impl.glsl.node.branch; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; +import org.jetbrains.annotations.Nullable; + +/** + * if/else + * + * @param expression + * @param first + * @param branch + * @author Ocelot + */ +public record GlslSelectionNode(GlslNode expression, GlslNode first, @Nullable GlslNode branch) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSwitchNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSwitchNode.java new file mode 100644 index 00000000..bb12fd3f --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSwitchNode.java @@ -0,0 +1,21 @@ +package foundry.veil.impl.glsl.node.branch; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +import java.util.List; + +/** + * Switch statement. + * + * @param condition The condition inside the switch switch(condition) {} + * @param branches All code inside the switch, including all labels and code under those labels + * @author Ocelot + */ +public record GlslSwitchNode(GlslNode condition, List branches) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAndNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAndNode.java new file mode 100644 index 00000000..d8f92d03 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAndNode.java @@ -0,0 +1,20 @@ +package foundry.veil.impl.glsl.node.expression; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +import java.util.List; + +/** + * AND; A & B & C + * + * @param expressions + * @author Ocelot + */ +public record GlslAndNode(List expressions) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAssignmentNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAssignmentNode.java new file mode 100644 index 00000000..aa0f91d5 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAssignmentNode.java @@ -0,0 +1,53 @@ +package foundry.veil.impl.glsl.node.expression; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +/** + * Equal; A = B + *
+ * Multiply Assign; A *= B + *
+ * Divide Assign; A /= B + *
+ * Modulo Assign; A %= B + *
+ * Add Assign; A += B + *
+ * Subtract Assign; A -= B + *
+ * Left Assign; A <<= B + *
+ * Right Assign; A >>= B + *
+ * And Assign; A &= B + *
+ * Exclusive Or Assign; A ^= B + *
+ * Or Assign; A |= B + * + * @param left The left operand + * @param right The right operand + * @param operand The operand to perform when setting the left to the right + * @author Ocelot + */ +public record GlslAssignmentNode(GlslNode left, GlslNode right, Operand operand) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + } + + public enum Operand { + EQUAL, + MUL_ASSIGN, + DIV_ASSIGN, + MOD_ASSIGN, + ADD_ASSIGN, + SUB_ASSIGN, + LEFT_ASSIGN, + RIGHT_ASSIGN, + AND_ASSIGN, + XOR_ASSIGN, + OR_ASSIGN + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslCompareNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslCompareNode.java new file mode 100644 index 00000000..d5ba41bf --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslCompareNode.java @@ -0,0 +1,26 @@ +package foundry.veil.impl.glsl.node.expression; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +/** + * Equality; A == B, A != B + *
+ * Relational; A < B, A > B, A <= B, A >= B + * + * @param first The left operand + * @param second The right operand + * @param type The operand of relationship the expressions have + * @author Ocelot + */ +public record GlslCompareNode(GlslNode first, GlslNode second, Type type) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } + + public enum Type { + EQUAL, NOT_EQUAL, LESS, GREATER, LEQUAL, GEQUAL + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslConditionalNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslConditionalNode.java new file mode 100644 index 00000000..0e8d4f9e --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslConditionalNode.java @@ -0,0 +1,21 @@ +package foundry.veil.impl.glsl.node.expression; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; +import org.jetbrains.annotations.Nullable; + +/** + * ?: + * + * @param condition + * @param first + * @param branch + * @author Ocelot + */ +public record GlslConditionalNode(GlslNode condition, GlslNode first, @Nullable GlslNode branch) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslExclusiveOrNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslExclusiveOrNode.java new file mode 100644 index 00000000..ae5bd4f1 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslExclusiveOrNode.java @@ -0,0 +1,20 @@ +package foundry.veil.impl.glsl.node.expression; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +import java.util.List; + +/** + * Exclusive OR; A ^ B ^ C + * + * @param expressions + * @author Ocelot + */ +public record GlslExclusiveOrNode(List expressions) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslInclusiveOrNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslInclusiveOrNode.java new file mode 100644 index 00000000..3d6f9e65 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslInclusiveOrNode.java @@ -0,0 +1,20 @@ +package foundry.veil.impl.glsl.node.expression; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +import java.util.List; + +/** + * Inclusive OR; A | B | C + * + * @param expressions + * @author Ocelot + */ +public record GlslInclusiveOrNode(List expressions) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalAndNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalAndNode.java new file mode 100644 index 00000000..fd046379 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalAndNode.java @@ -0,0 +1,20 @@ +package foundry.veil.impl.glsl.node.expression; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +import java.util.List; + +/** + * Logical AND; A && B && C + * + * @param expressions + * @author Ocelot + */ +public record GlslLogicalAndNode(List expressions) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalOrNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalOrNode.java new file mode 100644 index 00000000..de7e84ca --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalOrNode.java @@ -0,0 +1,20 @@ +package foundry.veil.impl.glsl.node.expression; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +import java.util.List; + +/** + * Logical OR; A || B || C + * + * @param expressions + * @author Ocelot + */ +public record GlslLogicalOrNode(List expressions) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalXorNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalXorNode.java new file mode 100644 index 00000000..ae2d4a28 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalXorNode.java @@ -0,0 +1,20 @@ +package foundry.veil.impl.glsl.node.expression; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +import java.util.List; + +/** + * Logical XOR; A ^^ B ^^ C + * + * @param expressions + * @author Ocelot + */ +public record GlslLogicalXorNode(List expressions) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslOperationNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslOperationNode.java new file mode 100644 index 00000000..8ebc4069 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslOperationNode.java @@ -0,0 +1,34 @@ +package foundry.veil.impl.glsl.node.expression; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +/** + * Shift; A << B, A >> B + *
+ * Add; A + B + *
+ * Subtract; A - B + *
+ * Multiply; A * B + *
+ * Divide; A / B + *
+ * Modulo; A % B + * + * @param first The left operand + * @param second The right operand + * @param operand The operand of relationship the expressions have + * @author Ocelot + */ +public record GlslOperationNode(GlslNode first, GlslNode second, Operand operand) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } + + public enum Operand { + LEFT_SHIFT, RIGHT_SHIFT, ADD, SUBTRACT, MULTIPLY, DIVIDE, MODULO + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslUnaryExpressionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslUnaryNode.java similarity index 64% rename from common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslUnaryExpressionNode.java rename to common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslUnaryNode.java index eed916c9..ed83c300 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslUnaryExpressionNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslUnaryNode.java @@ -1,12 +1,12 @@ -package foundry.veil.impl.glsl.node.postfix; +package foundry.veil.impl.glsl.node.expression; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.node.GlslVisitor; +import foundry.veil.impl.glsl.visitor.GlslVisitor; import java.util.Collection; import java.util.Collections; -public record GlslUnaryExpressionNode(Operator operator, GlslNode expression) implements GlslNode { +public record GlslUnaryNode(GlslNode expression, Operand operand) implements GlslNode { @Override public void visit(GlslVisitor visitor) { @@ -18,7 +18,7 @@ public Collection children() { return Collections.singleton(this.expression); } - public enum Operator { + public enum Operand { PRE_INCREMENT, PRE_DECREMENT, POST_INCREMENT, POST_DECREMENT, PLUS, DASH, BANG, TILDE } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/PrecisionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/PrecisionNode.java new file mode 100644 index 00000000..2887a7eb --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/PrecisionNode.java @@ -0,0 +1,38 @@ +package foundry.veil.impl.glsl.node.expression; + +import foundry.veil.impl.glsl.grammar.GlslTypeQualifier; +import foundry.veil.impl.glsl.grammar.GlslTypeSpecifier; +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +public class PrecisionNode implements GlslNode { + + private GlslTypeQualifier.Precision precision; + private GlslTypeSpecifier typeSpecifier; + + public PrecisionNode(GlslTypeQualifier.Precision precision, GlslTypeSpecifier typeSpecifier) { + this.precision = precision; + this.typeSpecifier = typeSpecifier; + } + + @Override + public void visit(GlslVisitor visitor) { + + } + + public GlslTypeQualifier.Precision getPrecision() { + return this.precision; + } + + public GlslTypeSpecifier getTypeSpecifier() { + return this.typeSpecifier; + } + + public void setPrecision(GlslTypeQualifier.Precision precision) { + this.precision = precision; + } + + public void setTypeSpecifier(GlslTypeSpecifier typeSpecifier) { + this.typeSpecifier = typeSpecifier; + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunction.java b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunction.java new file mode 100644 index 00000000..3d239e4b --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunction.java @@ -0,0 +1,41 @@ +package foundry.veil.impl.glsl.node.function; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +public class GlslFunction implements GlslNode { + + private GlslFunctionHeader header; + private GlslNode body; + + public GlslFunction(GlslFunctionHeader header, GlslNode body) { + this.header = header; + this.body = body; + } + + @Override + public void visit(GlslVisitor visitor) { + + } + + public GlslFunctionHeader getHeader() { + return this.header; + } + + public GlslNode getBody() { + return this.body; + } + + public void setHeader(GlslFunctionHeader header) { + this.header = header; + } + + public void setBody(GlslNode body) { + this.body = body; + } + + @Override + public String toString() { + return "GlslFunction{header=" + this.header + ", body=" + this.body + '}'; + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionHeader.java b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionHeader.java new file mode 100644 index 00000000..094834aa --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionHeader.java @@ -0,0 +1,60 @@ +package foundry.veil.impl.glsl.node.function; + +import foundry.veil.impl.glsl.grammar.GlslSpecifiedType; +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.grammar.GlslParameterDeclaration; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +public class GlslFunctionHeader implements GlslNode { + + private String name; + private GlslSpecifiedType returnType; + private final List parameters; + + public GlslFunctionHeader(String name, GlslSpecifiedType returnType, Collection parameters) { + this.name = name; + this.returnType = returnType; + this.parameters = new ArrayList<>(parameters); + } + + public GlslFunctionHeader withParameters(GlslParameterDeclaration... parameters) { + return new GlslFunctionHeader(this.name, this.returnType, new ArrayList<>(Arrays.asList(parameters))); + } + + public String getName() { + return this.name; + } + + public GlslSpecifiedType getReturnType() { + return this.returnType; + } + + public List getParameters() { + return this.parameters; + } + + public GlslFunctionHeader setName(String name) { + this.name = name; + return this; + } + + public GlslFunctionHeader setReturnType(GlslSpecifiedType returnType) { + this.returnType = returnType; + return this; + } + + @Override + public void visit(GlslVisitor visitor) { + + } + + @Override + public String toString() { + return "GlslFunctionHeader{name='" + this.name + "', returnType=" + this.returnType +", parameters=" + this.parameters + '}'; + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslInvokeFunctionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslInvokeFunctionNode.java new file mode 100644 index 00000000..b5b976da --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslInvokeFunctionNode.java @@ -0,0 +1,41 @@ +package foundry.veil.impl.glsl.node.function; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class GlslInvokeFunctionNode implements GlslNode { + + private GlslNode header; + private final List parameters; + + public GlslInvokeFunctionNode(GlslNode header, Collection parameters) { + this.header = header; + this.parameters = new ArrayList<>(parameters); + } + + @Override + public void visit(GlslVisitor visitor) { + + } + + public GlslNode getHeader() { + return this.header; + } + + public List getParameters() { + return this.parameters; + } + + public void setHeader(GlslNode header) { + this.header = header; + } + + @Override + public String toString() { + return "GlslInvokeFunctionNode{header=" + this.header + ", parameters=" + this.parameters + '}'; + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslFunctionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslFunctionNode.java deleted file mode 100644 index e74e9a5b..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslFunctionNode.java +++ /dev/null @@ -1,13 +0,0 @@ -package foundry.veil.impl.glsl.node.postfix; - -import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.node.GlslVisitor; -import foundry.veil.impl.glsl.type.TypeSpecifier; - -public record GlslFunctionNode(TypeSpecifier typeSpecifier, GlslNode[] params) implements GlslNode { - - @Override - public void visit(GlslVisitor visitor) { - - } -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetArrayNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetArrayNode.java deleted file mode 100644 index 284516cc..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetArrayNode.java +++ /dev/null @@ -1,26 +0,0 @@ -package foundry.veil.impl.glsl.node.postfix; - -import foundry.veil.impl.glsl.node.GlslAssignableNode; -import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.node.GlslVisitor; - -import java.util.Collection; -import java.util.List; - -public record GlslGetArrayNode(GlslNode expression, GlslNode index) implements GlslAssignableNode { - - @Override - public void visit(GlslVisitor visitor) { - - } - - @Override - public Collection children() { - return List.of(this.expression, this.index); - } - - @Override - public GlslNode toAssignment(Assignment assignment, GlslNode value) { - return new GlslSetArrayNode(this.expression, this.index, assignment, value); - } -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetFieldNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetFieldNode.java deleted file mode 100644 index 2b6a2b94..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetFieldNode.java +++ /dev/null @@ -1,26 +0,0 @@ -package foundry.veil.impl.glsl.node.postfix; - -import foundry.veil.impl.glsl.node.GlslAssignableNode; -import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.node.GlslVisitor; - -import java.util.Collection; -import java.util.Collections; - -public record GlslGetFieldNode(GlslNode expression, String fieldSelection) implements GlslAssignableNode { - - @Override - public void visit(GlslVisitor visitor) { - - } - - @Override - public Collection children() { - return Collections.singleton(this.expression); - } - - @Override - public GlslNode toAssignment(Assignment assignment, GlslNode value) { - return new GlslSetFieldNode(this.expression, this.fieldSelection, assignment, value); - } -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetVarNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetVarNode.java deleted file mode 100644 index ed052e3b..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslGetVarNode.java +++ /dev/null @@ -1,21 +0,0 @@ -package foundry.veil.impl.glsl.node.postfix; - -import foundry.veil.impl.glsl.node.GlslAssignableNode; -import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.node.GlslVisitor; - -import java.util.Collection; -import java.util.Collections; - -public record GlslGetVarNode(String name) implements GlslAssignableNode { - - @Override - public void visit(GlslVisitor visitor) { - - } - - @Override - public GlslNode toAssignment(Assignment assignment, GlslNode value) { - return new GlslSetVarNode(this.name, assignment, value); - } -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslInitializerNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslInitializerNode.java deleted file mode 100644 index 76c0fed2..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslInitializerNode.java +++ /dev/null @@ -1,22 +0,0 @@ -package foundry.veil.impl.glsl.node.postfix; - -import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.node.GlslVisitor; -import foundry.veil.impl.glsl.node.primary.GlslExpressionNode; -import foundry.veil.impl.glsl.type.TypeSpecifier; - -import java.util.Arrays; -import java.util.Collection; - -public record GlslInitializerNode(GlslNode[] expressions) implements GlslNode { - - @Override - public void visit(GlslVisitor visitor) { - - } - - @Override - public Collection children() { - return Arrays.asList(this.expressions); - } -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslNewNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslNewNode.java deleted file mode 100644 index 087dc726..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslNewNode.java +++ /dev/null @@ -1,21 +0,0 @@ -package foundry.veil.impl.glsl.node.postfix; - -import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.node.GlslVisitor; -import foundry.veil.impl.glsl.type.GlslSpecifiedType; - -import java.util.Collection; -import java.util.List; - -public record GlslNewNode(GlslSpecifiedType type, String name, GlslNode value) implements GlslNode { - - @Override - public void visit(GlslVisitor visitor) { - - } - - @Override - public Collection children() { - return List.of(this.value); - } -} \ No newline at end of file diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetArrayNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetArrayNode.java deleted file mode 100644 index 42a90ce1..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetArrayNode.java +++ /dev/null @@ -1,24 +0,0 @@ -package foundry.veil.impl.glsl.node.postfix; - -import foundry.veil.impl.glsl.node.GlslAssignableNode; -import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.node.GlslVisitor; - -import java.util.Collection; -import java.util.List; - -public record GlslSetArrayNode(GlslNode expression, - GlslNode index, - GlslAssignableNode.Assignment assignment, - GlslNode values) implements GlslNode { - - @Override - public void visit(GlslVisitor visitor) { - - } - - @Override - public Collection children() { - return List.of(this.expression, this.index, this.values); - } -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetFieldNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetFieldNode.java deleted file mode 100644 index bf536d58..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetFieldNode.java +++ /dev/null @@ -1,24 +0,0 @@ -package foundry.veil.impl.glsl.node.postfix; - -import foundry.veil.impl.glsl.node.GlslAssignableNode; -import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.node.GlslVisitor; - -import java.util.Collection; -import java.util.List; - -public record GlslSetFieldNode(GlslNode expression, - String fieldSelection, - GlslAssignableNode.Assignment assignment, - GlslNode value) implements GlslNode { - - @Override - public void visit(GlslVisitor visitor) { - - } - - @Override - public Collection children() { - return List.of(this.expression, this.value); - } -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetVarNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetVarNode.java deleted file mode 100644 index 57d5ae38..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/node/postfix/GlslSetVarNode.java +++ /dev/null @@ -1,23 +0,0 @@ -package foundry.veil.impl.glsl.node.postfix; - -import foundry.veil.impl.glsl.node.GlslAssignableNode; -import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.node.GlslVisitor; - -import java.util.Collection; -import java.util.Collections; - -public record GlslSetVarNode(String name, - GlslAssignableNode.Assignment assignment, - GlslNode value) implements GlslNode { - - @Override - public void visit(GlslVisitor visitor) { - - } - - @Override - public Collection children() { - return Collections.singleton(this.value); - } -} \ No newline at end of file diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslBoolConstantNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslBoolConstantNode.java index 30dc27a9..296017bc 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslBoolConstantNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslBoolConstantNode.java @@ -1,8 +1,7 @@ package foundry.veil.impl.glsl.node.primary; import foundry.veil.impl.glsl.node.GlslConstantNode; -import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.node.GlslVisitor; +import foundry.veil.impl.glsl.visitor.GlslVisitor; public record GlslBoolConstantNode(boolean value) implements GlslConstantNode { diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslDoubleConstantNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslDoubleConstantNode.java index ecafe140..f0292ef4 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslDoubleConstantNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslDoubleConstantNode.java @@ -1,8 +1,7 @@ package foundry.veil.impl.glsl.node.primary; import foundry.veil.impl.glsl.node.GlslConstantNode; -import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.node.GlslVisitor; +import foundry.veil.impl.glsl.visitor.GlslVisitor; public record GlslDoubleConstantNode(double value) implements GlslConstantNode { diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslExpressionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslExpressionNode.java deleted file mode 100644 index 8627b43f..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslExpressionNode.java +++ /dev/null @@ -1,12 +0,0 @@ -package foundry.veil.impl.glsl.node.primary; - -import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.node.GlslVisitor; - -public record GlslExpressionNode(GlslNode node) implements GlslNode { - - @Override - public void visit(GlslVisitor visitor) { - - } -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslFloatConstantNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslFloatConstantNode.java index b4809093..91ef523f 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslFloatConstantNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslFloatConstantNode.java @@ -1,8 +1,7 @@ package foundry.veil.impl.glsl.node.primary; import foundry.veil.impl.glsl.node.GlslConstantNode; -import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.node.GlslVisitor; +import foundry.veil.impl.glsl.visitor.GlslVisitor; public record GlslFloatConstantNode(float value) implements GlslConstantNode { diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslIntConstantNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslIntConstantNode.java index 8a57cd3a..6076f7a2 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslIntConstantNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslIntConstantNode.java @@ -1,8 +1,7 @@ package foundry.veil.impl.glsl.node.primary; import foundry.veil.impl.glsl.node.GlslConstantNode; -import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.node.GlslVisitor; +import foundry.veil.impl.glsl.visitor.GlslVisitor; public record GlslIntConstantNode(GlslIntFormat format, int value) implements GlslConstantNode { diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslUIntConstantNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslUIntConstantNode.java index 02163013..a18893f7 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslUIntConstantNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslUIntConstantNode.java @@ -1,8 +1,7 @@ package foundry.veil.impl.glsl.node.primary; import foundry.veil.impl.glsl.node.GlslConstantNode; -import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.node.GlslVisitor; +import foundry.veil.impl.glsl.visitor.GlslVisitor; public record GlslUIntConstantNode(GlslIntFormat format, int value) implements GlslConstantNode { diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslArrayNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslArrayNode.java new file mode 100644 index 00000000..645d0cf0 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslArrayNode.java @@ -0,0 +1,19 @@ +package foundry.veil.impl.glsl.node.variable; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +import java.util.Collection; +import java.util.List; + +public record GlslArrayNode(GlslNode expression, GlslNode index) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + } + + @Override + public Collection children() { + return List.of(this.expression, this.index); + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslFieldNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslFieldNode.java new file mode 100644 index 00000000..cc21cf17 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslFieldNode.java @@ -0,0 +1,19 @@ +package foundry.veil.impl.glsl.node.variable; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +import java.util.Collection; +import java.util.Collections; + +public record GlslFieldNode(GlslNode expression, String fieldSelection) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + } + + @Override + public Collection children() { + return Collections.singleton(this.expression); + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslNewNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslNewNode.java new file mode 100644 index 00000000..0b5962b8 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslNewNode.java @@ -0,0 +1,22 @@ +package foundry.veil.impl.glsl.node.variable; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; +import foundry.veil.impl.glsl.grammar.GlslSpecifiedType; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public record GlslNewNode(GlslSpecifiedType type, String name, @Nullable GlslNode initializer) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + } + + @Override + public Collection children() { + return this.initializer != null ? List.of(this.initializer) : Collections.emptyList(); + } +} \ No newline at end of file diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslVariableNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslVariableNode.java new file mode 100644 index 00000000..011ab3ca --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslVariableNode.java @@ -0,0 +1,12 @@ +package foundry.veil.impl.glsl.node.variable; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +public record GlslVariableNode(String name) implements GlslNode { + + @Override + public void visit(GlslVisitor visitor) { + + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/type/GlslSpecifiedType.java b/common/src/main/java/foundry/veil/impl/glsl/type/GlslSpecifiedType.java deleted file mode 100644 index c59a29dc..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/type/GlslSpecifiedType.java +++ /dev/null @@ -1,11 +0,0 @@ -package foundry.veil.impl.glsl.type; - -import java.util.Arrays; - -public record GlslSpecifiedType(TypeSpecifier type, GlslTypeQualifier[] qualifiers) { - - @Override - public String toString() { - return "GlslSpecifiedType[type=" + this.type + ", qualifiers=" + Arrays.toString(this.qualifiers); - } -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/type/GlslTypeQualifier.java b/common/src/main/java/foundry/veil/impl/glsl/type/GlslTypeQualifier.java deleted file mode 100644 index 0b4d1fae..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/type/GlslTypeQualifier.java +++ /dev/null @@ -1,77 +0,0 @@ -package foundry.veil.impl.glsl.type; - -import foundry.veil.impl.glsl.node.GlslNode; -import org.jetbrains.annotations.Nullable; - -public interface GlslTypeQualifier { - - static GlslTypeQualifier storage(Storage.Type type) { - return new Storage(type, new String[0]); - } - - static GlslTypeQualifier storage(String[] typeNames) { - return new Storage(Storage.Type.SUBROUTINE, typeNames); - } - - static GlslTypeQualifier identifierLayout(String identifier, @Nullable GlslNode constantExpression) { - return new Layout(identifier, constantExpression); - } - - static GlslTypeQualifier sharedLayout() { - return new Layout("shared", null); - } - - record Storage(Type type, String[] typeNames) implements GlslTypeQualifier { - - public enum Type { - CONST, - IN, - OUT, - INOUT, - CENTROID, - PATCH, - SAMPLE, - UNIFORM, - BUFFER, - SHARED, - COHERENT, - VOLATILE, - RESTRICT, - READONLY, - WRITEONLY, - SUBROUTINE - } - } - - record Layout(String identifier, @Nullable GlslNode constantExpression) implements GlslTypeQualifier { - - public boolean shared() { - return "shared".equals(this.identifier); - } - - @Override - public @Nullable GlslNode constantExpression() { - return this.shared() ? null : this.constantExpression; - } - } - - enum Precision implements GlslTypeQualifier { - HIGH_PRECISION, - MEDIUM_PRECISION, - LOW_PRECISION - } - - enum Interpolation implements GlslTypeQualifier { - SMOOTH, - FLAT, - NOPERSPECTIVE - } - - enum Invariant implements GlslTypeQualifier { - INVARIANT - } - - enum Precise implements GlslTypeQualifier { - PRECISE - } -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/type/StructSpecifier.java b/common/src/main/java/foundry/veil/impl/glsl/type/StructSpecifier.java deleted file mode 100644 index 981b1f37..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/type/StructSpecifier.java +++ /dev/null @@ -1,4 +0,0 @@ -package foundry.veil.impl.glsl.type; - -public record StructSpecifier() { -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/type/TypeSpecifier.java b/common/src/main/java/foundry/veil/impl/glsl/type/TypeSpecifier.java deleted file mode 100644 index ff4f8b20..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/type/TypeSpecifier.java +++ /dev/null @@ -1,30 +0,0 @@ -package foundry.veil.impl.glsl.type; - -import foundry.veil.impl.glsl.GlslLexer; - -public interface TypeSpecifier { - - static TypeSpecifier simple(GlslLexer.Token token) { - if (!token.type().isType()) { - throw new IllegalArgumentException("Invalid type: " + token); - } - return new Simple(token); - } - - static TypeSpecifier struct(StructSpecifier structSpecifier) { - return new Struct(structSpecifier); - } - - static TypeSpecifier named(String name) { - return new Name(name); - } - - record Simple(GlslLexer.Token type) implements TypeSpecifier { - } - - record Struct(StructSpecifier structSpecifier) implements TypeSpecifier { - } - - record Name(String name) implements TypeSpecifier { - } -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslVisitor.java b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslVisitor.java new file mode 100644 index 00000000..3423d2ea --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslVisitor.java @@ -0,0 +1,4 @@ +package foundry.veil.impl.glsl.visitor; + +public interface GlslVisitor { +} diff --git a/common/src/main/java/foundry/veil/mixin/client/shader/GameRendererMixin.java b/common/src/main/java/foundry/veil/mixin/client/shader/GameRendererMixin.java index b0b53511..3ac1b07e 100644 --- a/common/src/main/java/foundry/veil/mixin/client/shader/GameRendererMixin.java +++ b/common/src/main/java/foundry/veil/mixin/client/shader/GameRendererMixin.java @@ -28,7 +28,7 @@ public class GameRendererMixin { static Logger LOGGER; /** - * This is needed to replace the shader instance value when shader replacement is used + * This is needed to replace the shader instance initializer when shader replacement is used * * @author Ocelot */ diff --git a/common/src/main/java/foundry/veil/platform/VeilPlatform.java b/common/src/main/java/foundry/veil/platform/VeilPlatform.java index 4c95e07e..877361f1 100644 --- a/common/src/main/java/foundry/veil/platform/VeilPlatform.java +++ b/common/src/main/java/foundry/veil/platform/VeilPlatform.java @@ -9,7 +9,7 @@ public interface VeilPlatform { /** - * @return The detected platform type + * @return The detected platform operand */ PlatformType getPlatformType(); diff --git a/common/src/main/java/foundry/veil/platform/registry/RegistrationProvider.java b/common/src/main/java/foundry/veil/platform/registry/RegistrationProvider.java index 9ba5b541..add233a9 100644 --- a/common/src/main/java/foundry/veil/platform/registry/RegistrationProvider.java +++ b/common/src/main/java/foundry/veil/platform/registry/RegistrationProvider.java @@ -21,7 +21,7 @@ * public static void loadClass(){} * } * - * @param the type of the objects that this class registers + * @param the operand of the objects that this class registers */ @ApiStatus.Internal public interface RegistrationProvider { @@ -36,7 +36,7 @@ public interface RegistrationProvider { * * @param resourceKey the {@link ResourceKey} of the registry of the provider * @param modId the mod id that the provider will register objects for - * @param the type of the provider + * @param the operand of the provider * @return the provider */ static RegistrationProvider get(ResourceKey> resourceKey, String modId) { @@ -48,7 +48,7 @@ static RegistrationProvider get(ResourceKey> resour * * @param registry the {@link Registry} of the provider * @param modId the mod id that the provider will register objects for - * @param the type of the provider + * @param the operand of the provider * @return the provider */ static RegistrationProvider get(Registry registry, String modId) { @@ -60,7 +60,7 @@ static RegistrationProvider get(Registry registry, String modId) { * * @param name the name of the object * @param supplier a supplier of the object to register - * @param the type of the object + * @param the operand of the object * @return a wrapper containing the lazy registered object. Calling {@link RegistryObject#get() get} too early * on the wrapper might result in crashes! */ @@ -73,7 +73,7 @@ default RegistryObject register(String name, Supplier the type of the object + * @param the operand of the object * @return a wrapper containing the lazy registered object. Calling {@link RegistryObject#get() get} too early * on the wrapper might result in crashes! */ @@ -106,7 +106,7 @@ interface Factory { * * @param resourceKey the {@link ResourceKey} of the registry to create this provider for * @param modId the mod id for which the provider will register objects - * @param the type of the provider + * @param the operand of the provider * @return the provider */ RegistrationProvider create(ResourceKey> resourceKey, String modId); @@ -116,7 +116,7 @@ interface Factory { * * @param registry the {@link Registry} to create this provider for * @param modId the mod id for which the provider will register objects - * @param the type of the provider + * @param the operand of the provider * @return the provider */ default RegistrationProvider create(Registry registry, String modId) { diff --git a/common/src/main/java/foundry/veil/platform/registry/RegistryObject.java b/common/src/main/java/foundry/veil/platform/registry/RegistryObject.java index 4344d9b9..3dd9b957 100644 --- a/common/src/main/java/foundry/veil/platform/registry/RegistryObject.java +++ b/common/src/main/java/foundry/veil/platform/registry/RegistryObject.java @@ -9,7 +9,7 @@ /** * Represents a lazy wrapper for registry object. * - * @param the type of the object + * @param the operand of the object */ public interface RegistryObject extends Supplier { @@ -28,7 +28,7 @@ public interface RegistryObject extends Supplier { ResourceLocation getId(); /** - * @return If the value has been registered and assigned + * @return If the initializer has been registered and assigned */ boolean isPresent(); diff --git a/common/src/main/resources/assets/veil/pinwheel/shaders/program/fog.fsh b/common/src/main/resources/assets/veil/pinwheel/shaders/program/fog.fsh index 442215c5..95255311 100644 --- a/common/src/main/resources/assets/veil/pinwheel/shaders/program/fog.fsh +++ b/common/src/main/resources/assets/veil/pinwheel/shaders/program/fog.fsh @@ -5,7 +5,7 @@ uniform sampler2D DiffuseSampler0; uniform sampler2D DiffuseDepthSampler; const float FogStart = 0; -const float FogEnd = 60; +const float FogEnd = 100; uniform vec4 FogColor; uniform int FogShape; @@ -21,4 +21,3 @@ void main() { float vertexDistance = fog_distance(pos, FogShape); fragColor = linear_fog(baseColor, vertexDistance, FogStart, FogEnd, FogColor); } - diff --git a/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/shaders/program/light/area.vsh b/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/shaders/program/light/area.vsh index f609a486..e3682e95 100644 --- a/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/shaders/program/light/area.vsh +++ b/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/shaders/program/light/area.vsh @@ -21,7 +21,7 @@ void main() { vertexPos *= vec3(Size.x + angleTerm, Size.y + angleTerm, Distance); // awful fix but not sure why just multiplying the matrix doesnt work? it does what it should in - // all the other calculations. really weird! + // all the branch calculations. really weird! vec3 lightPos = LightMatrix[3].xyz; mat3 rotationMatrix = mat3(LightMatrix); lightPos = inverse(rotationMatrix) * lightPos; diff --git a/common/src/test/java/GlslGrammarGenerator.java b/common/src/test/java/GlslGrammarGenerator.java new file mode 100644 index 00000000..6cc01661 --- /dev/null +++ b/common/src/test/java/GlslGrammarGenerator.java @@ -0,0 +1,700 @@ +import foundry.veil.impl.glsl.GlslTokenReader; +import foundry.veil.impl.glsl.node.GlslNode; +import org.jetbrains.annotations.Nullable; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.*; +import java.util.stream.Collectors; + +public class GlslGrammarGenerator { + + private static final String RAW = """ + variable_identifier : + IDENTIFIER + + primary_expression : + variable_identifier + INTCONSTANT + UINTCONSTANT + FLOATCONSTANT + BOOLCONSTANT + DOUBLECONSTANT + LEFT_PAREN expression RIGHT_PAREN + + postfix_expression : + primary_expression + postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET + function_call + postfix_expression DOT FIELD_SELECTION + postfix_expression INC_OP + postfix_expression DEC_OP + + // FIELD_SELECTION includes members in structures, component selection for vectors and the 'length' identifier for the length() method + + integer_expression : + expression + + function_call : + function_call_or_method + + function_call_or_method : + function_call_generic + + function_call_generic : + function_call_header_with_parameters RIGHT_PAREN + function_call_header_no_parameters RIGHT_PAREN + + function_call_header_no_parameters : + function_call_header VOID + function_call_header + + function_call_header_with_parameters : + function_call_header assignment_expression + function_call_header_with_parameters COMMA assignment_expression + + function_call_header : + function_identifier LEFT_PAREN + + // Methods (.length), subroutine array calls, and identifiers are recognized through postfix_expression. + + function_identifier : + type_specifier + postfix_expression + + unary_expression : + postfix_expression + INC_OP unary_expression + DEC_OP unary_expression + unary_operator unary_expression + + unary_operator : + PLUS + DASH + BANG + TILDE + + multiplicative_expression : + unary_expression + multiplicative_expression STAR unary_expression + multiplicative_expression SLASH unary_expression + multiplicative_expression PERCENT unary_expression + + additive_expression : + multiplicative_expression + additive_expression PLUS multiplicative_expression + additive_expression DASH multiplicative_expression + + shift_expression : + additive_expression + shift_expression LEFT_OP additive_expression + shift_expression RIGHT_OP additive_expression + + relational_expression : + shift_expression + relational_expression LEFT_ANGLE shift_expression + relational_expression RIGHT_ANGLE shift_expression + relational_expression LE_OP shift_expression + relational_expression GE_OP shift_expression + + equality_expression : + relational_expression + equality_expression EQ_OP relational_expression + equality_expression NE_OP relational_expression + + and_expression : + equality_expression + and_expression AMPERSAND equality_expression + + exclusive_or_expression : + and_expression + exclusive_or_expression CARET and_expression + + inclusive_or_expression : + exclusive_or_expression + inclusive_or_expression VERTICAL_BAR exclusive_or_expression + + logical_and_expression : + inclusive_or_expression + logical_and_expression AND_OP inclusive_or_expression + + logical_xor_expression : + logical_and_expression + logical_xor_expression XOR_OP logical_and_expression + + logical_or_expression : + logical_xor_expression + logical_or_expression OR_OP logical_xor_expression + + conditional_expression : + logical_or_expression + logical_or_expression QUESTION expression COLON assignment_expression + + assignment_expression : + conditional_expression + unary_expression assignment_operator assignment_expression + + assignment_operator : + EQUAL + MUL_ASSIGN + DIV_ASSIGN + MOD_ASSIGN + ADD_ASSIGN + SUB_ASSIGN + LEFT_ASSIGN + RIGHT_ASSIGN + AND_ASSIGN + XOR_ASSIGN + OR_ASSIGN + + expression : + assignment_expression + expression COMMA assignment_expression + + constant_expression : + conditional_expression + + declaration : + function_prototype SEMICOLON + init_declarator_list SEMICOLON + PRECISION precision_qualifier type_specifier SEMICOLON + type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE SEMICOLON + type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON + type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER array_specifier SEMICOLON + type_qualifier SEMICOLON + type_qualifier IDENTIFIER SEMICOLON + type_qualifier IDENTIFIER identifier_list SEMICOLON + + identifier_list : + COMMA IDENTIFIER + identifier_list COMMA IDENTIFIER + + function_prototype : + function_declarator RIGHT_PAREN + + function_declarator : + function_header + function_header_with_parameters + + function_header_with_parameters : + function_header parameter_declaration + function_header_with_parameters COMMA parameter_declaration + + function_header : + fully_specified_type IDENTIFIER LEFT_PAREN + + parameter_declarator : + type_specifier IDENTIFIER + type_specifier IDENTIFIER array_specifier + + parameter_declaration : + type_qualifier parameter_declarator + parameter_declarator + type_qualifier parameter_type_specifier + parameter_type_specifier + + parameter_type_specifier : + type_specifier + + init_declarator_list : + single_declaration + init_declarator_list COMMA IDENTIFIER + init_declarator_list COMMA IDENTIFIER array_specifier + init_declarator_list COMMA IDENTIFIER array_specifier EQUAL initializer + init_declarator_list COMMA IDENTIFIER EQUAL initializer + + single_declaration : + fully_specified_type + fully_specified_type IDENTIFIER + fully_specified_type IDENTIFIER array_specifier + fully_specified_type IDENTIFIER array_specifier EQUAL initializer + fully_specified_type IDENTIFIER EQUAL initializer + + fully_specified_type : + type_specifier + type_qualifier type_specifier + + invariant_qualifier : + INVARIANT + + interpolation_qualifier : + SMOOTH + FLAT + NOPERSPECTIVE + + layout_qualifier : + LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN + + layout_qualifier_id_list : + layout_qualifier_id + layout_qualifier_id_list COMMA layout_qualifier_id + + layout_qualifier_id : + IDENTIFIER + IDENTIFIER EQUAL constant_expression + SHARED + + precise_qualifier : + PRECISE + + type_qualifier : + single_type_qualifier + type_qualifier single_type_qualifier + + single_type_qualifier : + storage_qualifier + layout_qualifier + precision_qualifier + interpolation_qualifier + invariant_qualifier + precise_qualifier + + storage_qualifier : + CONST + IN + OUT + INOUT + CENTROID + PATCH + SAMPLE + UNIFORM + BUFFER + SHARED + COHERENT + VOLATILE + RESTRICT + READONLY + WRITEONLY + SUBROUTINE + SUBROUTINE LEFT_PAREN type_name_list RIGHT_PAREN + + type_name_list : + TYPE_NAME + type_name_list COMMA TYPE_NAME + + type_specifier : + type_specifier_nonarray + type_specifier_nonarray array_specifier + + array_specifier : + LEFT_BRACKET RIGHT_BRACKET + LEFT_BRACKET conditional_expression RIGHT_BRACKET + array_specifier LEFT_BRACKET RIGHT_BRACKET + array_specifier LEFT_BRACKET conditional_expression RIGHT_BRACKET + + type_specifier_nonarray : + VOID + FLOAT + DOUBLE + INT + UINT + BOOL + VEC2 + VEC3 + VEC4 + DVEC2 + DVEC3 + DVEC4 + BVEC2 + BVEC3 + BVEC4 + IVEC2 + IVEC3 + IVEC4 + UVEC2 + UVEC3 + UVEC4 + MAT2 + MAT3 + MAT4 + MAT2X2 + MAT2X3 + MAT2X4 + MAT3X2 + MAT3X3 + MAT3X4 + MAT4X2 + MAT4X3 + MAT4X4 + DMAT2 + DMAT3 + DMAT4 + DMAT2X2 + DMAT2X3 + DMAT2X4 + DMAT3X2 + DMAT3X3 + DMAT3X4 + DMAT4X2 + DMAT4X3 + DMAT4X4 + ATOMIC_UINT + SAMPLER2D + SAMPLER3D + SAMPLERCUBE + SAMPLER2DSHADOW + SAMPLERCUBESHADOW + SAMPLER2DARRAY + SAMPLER2DARRAYSHADOW + SAMPLERCUBEARRAY + SAMPLERCUBEARRAYSHADOW + ISAMPLER2D + ISAMPLER3D + ISAMPLERCUBE + ISAMPLER2DARRAY + ISAMPLERCUBEARRAY + USAMPLER2D + USAMPLER3D + USAMPLERCUBE + USAMPLER2DARRAY + USAMPLERCUBEARRAY + SAMPLER1D + SAMPLER1DSHADOW + SAMPLER1DARRAY + SAMPLER1DARRAYSHADOW + ISAMPLER1D + ISAMPLER1DARRAY + USAMPLER1D + USAMPLER1DARRAY + SAMPLER2DRECT + SAMPLER2DRECTSHADOW + ISAMPLER2DRECT + USAMPLER2DRECT + SAMPLERBUFFER + ISAMPLERBUFFER + USAMPLERBUFFER + SAMPLER2DMS + ISAMPLER2DMS + USAMPLER2DMS + SAMPLER2DMSARRAY + ISAMPLER2DMSARRAY + USAMPLER2DMSARRAY + IMAGE2D + IIMAGE2D + UIMAGE2D + IMAGE3D + IIMAGE3D + UIMAGE3D + IMAGECUBE + IIMAGECUBE + UIMAGECUBE + IMAGEBUFFER + IIMAGEBUFFER + UIMAGEBUFFER + IMAGE1D + IIMAGE1D + UIMAGE1D + IMAGE1DARRAY + IIMAGE1DARRAY + UIMAGE1DARRAY + IMAGE2DRECT + IIMAGE2DRECT + UIMAGE2DRECT + IMAGE2DARRAY + IIMAGE2DARRAY + UIMAGE2DARRAY + IMAGECUBEARRAY + IIMAGECUBEARRAY + UIMAGECUBEARRAY + IMAGE2DMS + IIMAGE2DMS + UIMAGE2DMS + IMAGE2DMSARRAY + IIMAGE2DMSARRAY + UIMAGE2DMSARRAY + struct_specifier + TYPE_NAME + + precision_qualifier : + HIGH_PRECISION + MEDIUM_PRECISION + LOW_PRECISION + + struct_specifier : + STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE + STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE + + struct_declaration_list : + struct_declaration + struct_declaration_list struct_declaration + + struct_declaration : + type_specifier struct_declarator_list SEMICOLON + type_qualifier type_specifier struct_declarator_list SEMICOLON + + struct_declarator_list : + struct_declarator + struct_declarator_list COMMA struct_declarator + + struct_declarator : + IDENTIFIER + IDENTIFIER array_specifier + + initializer : + assignment_expression + LEFT_BRACE initializer_list RIGHT_BRACE + LEFT_BRACE initializer_list COMMA RIGHT_BRACE + + initializer_list : + initializer + initializer_list COMMA initializer + + declaration_statement : + declaration + + statement : + compound_statement + simple_statement + + simple_statement : + declaration_statement + expression_statement + selection_statement + switch_statement + case_label + iteration_statement + jump_statement + + compound_statement : + LEFT_BRACE RIGHT_BRACE + LEFT_BRACE statement_list RIGHT_BRACE + + statement_no_new_scope : + compound_statement_no_new_scope + simple_statement + + compound_statement_no_new_scope : + LEFT_BRACE RIGHT_BRACE + LEFT_BRACE statement_list RIGHT_BRACE + + statement_list : + statement + statement_list statement + + expression_statement : + SEMICOLON + expression SEMICOLON + + selection_statement : + IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement + + selection_rest_statement : + statement ELSE statement + statement + + condition : + expression + fully_specified_type IDENTIFIER EQUAL initializer + + switch_statement : + SWITCH LEFT_PAREN expression RIGHT_PAREN LEFT_BRACE switch_statement_list + RIGHT_BRACE + + switch_statement_list : + /* nothing */ + statement_list + + case_label : + CASE expression COLON + DEFAULT COLON + + iteration_statement : + WHILE LEFT_PAREN condition RIGHT_PAREN statement_no_new_scope + DO statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON + FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope + + for_init_statement : + expression_statement + declaration_statement + + conditionopt : + condition + /* empty */ + + for_rest_statement : + conditionopt SEMICOLON + conditionopt SEMICOLON expression + + jump_statement : + CONTINUE SEMICOLON + BREAK SEMICOLON + RETURN SEMICOLON + RETURN expression SEMICOLON + // Fragment shader only. + DISCARD SEMICOLON + + translation_unit : + external_declaration + translation_unit external_declaration + + external_declaration : + function_definition + declaration + SEMICOLON + + function_definition : + function_prototype compound_statement_no_new_scope + """; + + public static void main(String[] args) throws IOException { + Scanner scanner = new Scanner(RAW); + + List declarations = new ArrayList<>(); + + String name = null; + List values = new ArrayList<>(); + while (scanner.hasNextLine()) { + String line = scanner.nextLine().trim(); + if (line.startsWith("//") || line.startsWith("/*")) { + continue; + } + + if (line.endsWith(" :")) { + if (!values.isEmpty()) { + declarations.add(new Declaration(name, values.toArray(String[]::new))); + values.clear(); + } + + name = line.substring(0, line.length() - 2); + continue; + } + + if (!line.isBlank()) { + values.add(line); + } + } + + if (!values.isEmpty()) { + declarations.add(new Declaration(name, values.toArray(String[]::new))); + values.clear(); + } + + try (PrintStream stream = new PrintStream(new FileOutputStream("glsl.txt"))) { + StringBuilder builder = new StringBuilder(); + for (Declaration entry : declarations) { + builder.append(entry.name()).append(" : "); + + String[] strings = entry.values; + for (int i = 0; i < strings.length; i++) { + builder.append(strings[i]); + if (i < strings.length - 1) { + builder.append(" | "); + } + } + builder.append('\n'); + } + stream.print(builder); + } + + try (PrintStream stream = new PrintStream(new FileOutputStream("glsl_code.txt"))) { + StringBuilder builder = new StringBuilder(); + for (Declaration entry : declarations) { + StringBuilder methodName = new StringBuilder(); + char[] chars = entry.name.toCharArray(); + for (int i = 0; i < chars.length; i++) { + if (i == 0) { + methodName.append(Character.toUpperCase(chars[i])); + continue; + } + if (chars[i] == '_') { + i++; + methodName.append(Character.toUpperCase(chars[i])); + continue; + } + methodName.append(chars[i]); + } + + String behavior = Arrays.stream(entry.values).map(a -> " // " + a).collect(Collectors.joining("\n")); + builder.append(""" + private static @Nullable GlslNode parse%s(GlslTokenReader reader) { + %s + return null; // TODO + } + + """.formatted(methodName, behavior)); + } + stream.print(builder); + } + } + + private enum Grammar { + CONST, BOOL, FLOAT, INT, UINT, DOUBLE, + + BVEC2, BVEC3, BVEC4, IVEC2, IVEC3, IVEC4, UVEC2, UVEC3, UVEC4, VEC2, VEC3, VEC4, + + MAT2, MAT3, MAT4, MAT2X2, MAT2X3, MAT2X4, MAT3X2, MAT3X3, MAT3X4, MAT4X2, MAT4X3, MAT4X4, + + DVEC2, DVEC3, DVEC4, DMAT2, DMAT3, DMAT4, DMAT2X2, DMAT2X3, DMAT2X4, DMAT3X2, DMAT3X3, DMAT3X4, DMAT4X2, DMAT4X3, DMAT4X4, + + CENTROID, IN, OUT, INOUT, UNIFORM, PATCH, SAMPLE, BUFFER, SHARED, COHERENT, VOLATILE, RESTRICT, READONLY, WRITEONLY, NOPERSPECTIVE, FLAT, SMOOTH, LAYOUT, + + ATOMIC_UINT, + + SAMPLER2D, SAMPLER3D, SAMPLERCUBE, SAMPLER2DSHADOW, SAMPLERCUBESHADOW, SAMPLER2DARRAY, SAMPLER2DARRAYSHADOW, ISAMPLER2D, ISAMPLER3D, ISAMPLERCUBE, ISAMPLER2DARRAY, USAMPLER2D, USAMPLER3D, USAMPLERCUBE, USAMPLER2DARRAY, + + SAMPLER1D, SAMPLER1DSHADOW, SAMPLER1DARRAY, SAMPLER1DARRAYSHADOW, ISAMPLER1D, ISAMPLER1DARRAY, USAMPLER1D, USAMPLER1DARRAY, SAMPLER2DRECT, SAMPLER2DRECTSHADOW, ISAMPLER2DRECT, USAMPLER2DRECT, + + SAMPLERBUFFER, ISAMPLERBUFFER, USAMPLERBUFFER, SAMPLERCUBEARRAY, SAMPLERCUBEARRAYSHADOW, ISAMPLERCUBEARRAY, USAMPLERCUBEARRAY, SAMPLER2DMS, ISAMPLER2DMS, USAMPLER2DMS, SAMPLER2DMSARRAY, ISAMPLER2DMSARRAY, USAMPLER2DMSARRAY, IMAGE2D, IIMAGE2D, UIMAGE2D, IMAGE3D, IIMAGE3D, UIMAGE3D, IMAGECUBE, IIMAGECUBE, UIMAGECUBE, IMAGEBUFFER, IIMAGEBUFFER, UIMAGEBUFFER, IMAGE2DARRAY, IIMAGE2DARRAY, UIMAGE2DARRAY, IMAGECUBEARRAY, IIMAGECUBEARRAY, UIMAGECUBEARRAY, + + IMAGE1D, IIMAGE1D, UIMAGE1D, IMAGE1DARRAY, IIMAGE1DARRAY, UIMAGE1DARRAY, IMAGE2DRECT, IIMAGE2DRECT, UIMAGE2DRECT, IMAGE2DMS, IIMAGE2DMS, UIMAGE2DMS, IMAGE2DMSARRAY, IIMAGE2DMSARRAY, UIMAGE2DMSARRAY, + + STRUCT, VOID, + + WHILE, BREAK, CONTINUE, DO, ELSE, FOR, IF, DISCARD, RETURN, SWITCH, CASE, DEFAULT, SUBROUTINE, + + IDENTIFIER, TYPE_NAME, FLOATCONSTANT, INTCONSTANT, UINTCONSTANT, BOOLCONSTANT, DOUBLECONSTANT, FIELD_SELECTION, + + LEFT_OP, RIGHT_OP, INC_OP, DEC_OP, LE_OP, GE_OP, EQ_OP, NE_OP, AND_OP, OR_OP, XOR_OP, MUL_ASSIGN, DIV_ASSIGN, ADD_ASSIGN, MOD_ASSIGN, LEFT_ASSIGN, RIGHT_ASSIGN, AND_ASSIGN, XOR_ASSIGN, OR_ASSIGN, SUB_ASSIGN, LEFT_PAREN, RIGHT_PAREN, LEFT_BRACKET, RIGHT_BRACKET, LEFT_BRACE, RIGHT_BRACE, DOT, COMMA, COLON, EQUAL, SEMICOLON, BANG, DASH, TILDE, PLUS, STAR, SLASH, PERCENT, LEFT_ANGLE, RIGHT_ANGLE, VERTICAL_BAR, CARET, AMPERSAND, QUESTION, + + INVARIANT, PRECISE, HIGH_PRECISION, MEDIUM_PRECISION, LOW_PRECISION, PRECISION; + + private static final Set NAMES = Arrays.stream(values()).map(Grammar::name).collect(Collectors.toSet()); + } + + private record Declaration(String name, String... values) { + } + + private interface GrammarElement { + + static GrammarElement token(Grammar grammar) { + return new EnumGrammarElement(grammar); + } + + static GrammarElement recursive(String name) { + return new RecursiveGrammarElement(name); + } + + static GrammarElement of(String name, GrammarElement... elements) { + if (elements.length == 0) { + throw new IllegalArgumentException("Grammar elements cannot be empty"); + } + if (elements.length == 1) { + return elements[0]; + } + + return new CompoundGrammarElement(name, elements); + } + + record EnumGrammarElement(Grammar grammar) implements GrammarElement { + @Override + public String toString() { + return this.grammar.toString(); + } + } + + record RecursiveGrammarElement(String name) implements GrammarElement { + @Override + public String toString() { + return this.name; + } + } + + record CompoundGrammarElement(String name, GrammarElement[] elements) implements GrammarElement { + @Override + public String toString() { + return "CompoundGrammarElement[name=" + this.name + ", elements=" + Arrays.toString(this.elements) + ']'; + } + } + } +} \ No newline at end of file diff --git a/common/src/test/java/GlslTest.java b/common/src/test/java/GlslTest.java index 9c14318b..34d81f6e 100644 --- a/common/src/test/java/GlslTest.java +++ b/common/src/test/java/GlslTest.java @@ -2,7 +2,7 @@ import foundry.veil.impl.glsl.GlslParser; import foundry.veil.impl.glsl.GlslSyntaxException; import foundry.veil.impl.glsl.node.GlslTree; -import foundry.veil.impl.glsl.node.GlslVersion; +import foundry.veil.impl.glsl.grammar.GlslVersion; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -29,25 +29,68 @@ private String toString(GlslLexer.Token[] tokens) { @Test void testParser() throws GlslSyntaxException { - GlslLexer.Token[] tokens = GlslLexer.createTokens("#version 330 core\nfloat a = 32.0;"); + GlslLexer.Token[] tokens = GlslLexer.createTokens("#version 330 core\nfloat a = 1.0 + 3.0;"); GlslTree tree = GlslParser.parse(tokens); Assertions.assertEquals(new GlslVersion(330, true), tree.getVersion()); } @Test - void testPrecision() throws GlslSyntaxException { + void testSet() throws GlslSyntaxException { GlslLexer.Token[] tokens = GlslLexer.createTokens(""" - uniform highp float h1; - highp float h2 = 2.3 * 4.7; // operation and result are highp - precision - mediump float m; - m = 3.7 * h1 * h2; // all operations are highp precision - h2 = m * h1; // operation is highp precision - m = h2 - h1; // operation is highp precision - h2 = m + m; // addition and result at mediump precision - void f(highp float p); - f(3.3); // 3.3 will be passed in at highp precision"""); + #version 330 core + + uniform vec4 color; + + void main() { + highp float test; + test = 2.0; + } + """); + GlslTree tree = GlslParser.parse(tokens); + System.out.println(tree); + } + + @Test + void testCall() throws GlslSyntaxException { + GlslLexer.Token[] tokens = GlslLexer.createTokens(""" + void main() { + vec4 baseColor = texture(DiffuseSampler0, texCoord); + } + """); GlslTree tree = GlslParser.parse(tokens); System.out.println(this.toString(tokens)); } + + @Test + void testShader() throws GlslSyntaxException { + long start = System.nanoTime(); + GlslLexer.Token[] tokens = GlslLexer.createTokens(""" + #version 430 core + + uniform sampler2D DiffuseSampler0; + uniform sampler2D DiffuseDepthSampler; + + const float FogStart = 0; + const float FogEnd = 100; + uniform vec4 FogColor; + uniform int FogShape; + + in vec2 texCoord; + + out vec4 fragColor; + + void main() { + vec4 baseColor = texture(DiffuseSampler0, texCoord); + float depthSample = texture(DiffuseDepthSampler, texCoord).r; + vec3 pos = viewPosFromDepthSample(depthSample, texCoord); + + float vertexDistance = fog_distance(pos, FogShape); + fragColor = linear_fog(baseColor, vertexDistance, FogStart, FogEnd, FogColor); + } + """); + long parseStart = System.nanoTime(); + GlslTree tree = GlslParser.parse(tokens); + long end = System.nanoTime(); + System.out.printf("Took %.1fms to tokenize, %.1fms to parse%n", (parseStart - start) / 1_000_000.0F, (end - parseStart) / 1_000_000.0F); + } } diff --git a/fabric/src/main/java/foundry/veil/fabric/event/FabricVeilRegisterBlockLayerEvent.java b/fabric/src/main/java/foundry/veil/fabric/event/FabricVeilRegisterBlockLayerEvent.java index 96df9fee..c64a8480 100644 --- a/fabric/src/main/java/foundry/veil/fabric/event/FabricVeilRegisterBlockLayerEvent.java +++ b/fabric/src/main/java/foundry/veil/fabric/event/FabricVeilRegisterBlockLayerEvent.java @@ -7,7 +7,7 @@ /** *

Fired to register block layers.

- *

Note: This does not add fixed buffers automatically. To do that, also register the render type with {@link VeilRegisterFixedBuffersEvent}

+ *

Note: This does not add fixed buffers automatically. To do that, also register the render operand with {@link VeilRegisterFixedBuffersEvent}

* * @author Ocelot * @see VeilRegisterFixedBuffersEvent diff --git a/fabric/src/main/java/foundry/veil/fabric/event/FabricVeilRegisterFixedBuffersEvent.java b/fabric/src/main/java/foundry/veil/fabric/event/FabricVeilRegisterFixedBuffersEvent.java index 5dcebf61..890d7641 100644 --- a/fabric/src/main/java/foundry/veil/fabric/event/FabricVeilRegisterFixedBuffersEvent.java +++ b/fabric/src/main/java/foundry/veil/fabric/event/FabricVeilRegisterFixedBuffersEvent.java @@ -6,7 +6,7 @@ /** *

Fired to register additional fixed render types

- *

Fixed buffers are batched together and are not drawn until after the specified stage is drawn. This should be used in most cases to defer a specific render type to a specific time.

+ *

Fixed buffers are batched together and are not drawn until after the specified stage is drawn. This should be used in most cases to defer a specific render operand to a specific time.

* * @author Ocelot */ diff --git a/forge/src/main/java/foundry/veil/forge/event/ForgeVeilRegisterBlockLayerEvent.java b/forge/src/main/java/foundry/veil/forge/event/ForgeVeilRegisterBlockLayerEvent.java index ab08c79c..2d9f38b3 100644 --- a/forge/src/main/java/foundry/veil/forge/event/ForgeVeilRegisterBlockLayerEvent.java +++ b/forge/src/main/java/foundry/veil/forge/event/ForgeVeilRegisterBlockLayerEvent.java @@ -8,7 +8,7 @@ /** *

Fired to register block layers.

- *

Note: This does not add fixed buffers automatically. To do that, also register the render type with {@link VeilRegisterFixedBuffersEvent}

+ *

Note: This does not add fixed buffers automatically. To do that, also register the render operand with {@link VeilRegisterFixedBuffersEvent}

* * @author Ocelot * @see VeilRegisterFixedBuffersEvent diff --git a/forge/src/main/java/foundry/veil/forge/event/ForgeVeilRegisterFixedBuffersEvent.java b/forge/src/main/java/foundry/veil/forge/event/ForgeVeilRegisterFixedBuffersEvent.java index 62693e8c..1875e9ad 100644 --- a/forge/src/main/java/foundry/veil/forge/event/ForgeVeilRegisterFixedBuffersEvent.java +++ b/forge/src/main/java/foundry/veil/forge/event/ForgeVeilRegisterFixedBuffersEvent.java @@ -12,7 +12,7 @@ import java.util.function.BiConsumer; /** - *

Registers custom fixed render type buffers.

+ *

Registers custom fixed render operand buffers.

*

Use {@link RenderLevelStageEvent} or {@link VeilEventPlatform#onVeilRenderTypeStageRender(VeilRenderLevelStageEvent)} to listen to level stage render events on Forge.

* * @author Ocelot @@ -27,10 +27,10 @@ public ForgeVeilRegisterFixedBuffersEvent(BiConsumernull to do it manually - * @param renderType The render type to finish + * @param renderType The render operand to finish */ public void register(@Nullable RenderLevelStageEvent.Stage stage, RenderType renderType) { this.registry.accept(stage, renderType); From 5acb71e7a18c3396e3a9595c9bab2f7d521f909b Mon Sep 17 00:00:00 2001 From: Ocelot Date: Thu, 7 Nov 2024 12:46:49 -0700 Subject: [PATCH 31/47] Fixed first-person hand not rendering --- .../veil/api/client/render/framebuffer/AdvancedFbo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java index 3aa1316d..acb5789d 100644 --- a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java +++ b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java @@ -674,7 +674,7 @@ public Builder addColorBuffer(AdvancedFboAttachment attachment) { * @param textureId The id of the texture to add */ public Builder addColorTextureWrapper(int textureId) { - return this.addColorTextureWrapper(textureId, 0); + return this.addColorTextureWrapper(textureId, -1); } /** @@ -773,7 +773,7 @@ public Builder setDepthBuffer(@Nullable AdvancedFboAttachment attachment) { * @param textureId The id of the texture to add */ public Builder setDepthTextureWrapper(int textureId) { - return this.setDepthTextureWrapper(textureId, 0); + return this.setDepthTextureWrapper(textureId, -1); } /** From 2213b35d3691f69f1983f4086ced35ec6372822a Mon Sep 17 00:00:00 2001 From: Ocelot Date: Thu, 7 Nov 2024 16:39:57 -0700 Subject: [PATCH 32/47] Added jump statements --- .../foundry/veil/impl/glsl/GlslParser.java | 163 ++++++++++++------ .../grammar/GlslParameterDeclaration.java | 55 +++++- .../impl/glsl/grammar/GlslSpecifiedType.java | 22 ++- .../glsl/grammar/GlslStructSpecifier.java | 2 +- .../veil/impl/glsl/grammar/GlslType.java | 2 +- .../impl/glsl/grammar/GlslTypeSpecifier.java | 22 +-- .../foundry/veil/impl/glsl/node/GlslTree.java | 4 +- .../impl/glsl/node/branch/ForLoopNode.java | 66 +++++++ .../glsl/node/branch/GlslCaseLabelNode.java | 25 ++- .../veil/impl/glsl/node/branch/JumpNode.java | 14 ++ .../impl/glsl/node/branch/ReturnNode.java | 32 ++++ .../impl/glsl/node/branch/WhileLoopNode.java | 54 ++++++ ...eader.java => GlslFunctionHeaderNode.java} | 17 +- ...lslFunction.java => GlslFunctionNode.java} | 10 +- .../node/function/GlslInvokeFunctionNode.java | 2 +- .../function/PrimitiveConstructorNode.java | 32 ++++ .../impl/glsl/node/variable/GlslNewNode.java | 45 ++++- .../impl/glsl/visitor/GlslFieldVisitor.java | 4 + .../glsl/visitor/GlslFunctionVisitor.java | 4 + .../veil/impl/glsl/visitor/GlslVisitor.java | 14 ++ common/src/test/java/GlslTest.java | 18 ++ 21 files changed, 505 insertions(+), 102 deletions(-) create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/branch/ForLoopNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/branch/JumpNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/branch/ReturnNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/branch/WhileLoopNode.java rename common/src/main/java/foundry/veil/impl/glsl/node/function/{GlslFunctionHeader.java => GlslFunctionHeaderNode.java} (63%) rename common/src/main/java/foundry/veil/impl/glsl/node/function/{GlslFunction.java => GlslFunctionNode.java} (70%) create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/function/PrimitiveConstructorNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/visitor/GlslFieldVisitor.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/visitor/GlslFunctionVisitor.java diff --git a/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java b/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java index cfc127db..1f2b8b92 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java +++ b/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java @@ -2,13 +2,12 @@ import foundry.veil.impl.glsl.grammar.*; import foundry.veil.impl.glsl.node.*; -import foundry.veil.impl.glsl.node.branch.GlslCaseLabelNode; -import foundry.veil.impl.glsl.node.branch.GlslSelectionNode; -import foundry.veil.impl.glsl.node.branch.GlslSwitchNode; +import foundry.veil.impl.glsl.node.branch.*; import foundry.veil.impl.glsl.node.expression.*; -import foundry.veil.impl.glsl.node.function.GlslFunction; -import foundry.veil.impl.glsl.node.function.GlslFunctionHeader; +import foundry.veil.impl.glsl.node.function.GlslFunctionNode; +import foundry.veil.impl.glsl.node.function.GlslFunctionHeaderNode; import foundry.veil.impl.glsl.node.function.GlslInvokeFunctionNode; +import foundry.veil.impl.glsl.node.function.PrimitiveConstructorNode; import foundry.veil.impl.glsl.node.variable.GlslArrayNode; import foundry.veil.impl.glsl.node.primary.*; import foundry.veil.impl.glsl.node.variable.GlslFieldNode; @@ -343,24 +342,16 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio return null; } - private static @Nullable GlslNode parseFunctionCallHeaderNoParameters(GlslTokenReader reader) { - // function_call_header VOID - // function_call_header - return null; // TODO - } - - private static @Nullable GlslNode parseFunctionCallHeaderWithParameters(GlslTokenReader reader) { - // function_call_header assignment_expression - // function_call_header_with_parameters COMMA assignment_expression - return null; // TODO - } - private static @Nullable GlslNode parseFunctionCallHeader(GlslTokenReader reader) { - // FIXME + int cursor = reader.getCursor(); // type_specifier LEFT_PAREN - // postfix_expression LEFT_PAREN + GlslTypeSpecifier typeSpecifier = parseTypeSpecifier(reader); + if (typeSpecifier != null && !typeSpecifier.isNamed() && reader.tryConsume(GlslLexer.TokenType.LEFT_PAREN)) { + return new PrimitiveConstructorNode(typeSpecifier); + } + reader.setCursor(cursor); - int cursor = reader.getCursor(); + // postfix_expression LEFT_PAREN GlslNode expression = parsePostfixExpression(false, reader); if (expression != null && reader.tryConsume(GlslLexer.TokenType.LEFT_PAREN)) { return expression; @@ -821,7 +812,7 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio } // type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER array_specifier SEMICOLON - GlslTypeSpecifier arraySpecifier = parseArraySpecifier(reader, GlslTypeSpecifier.struct(structDeclaration)); + GlslTypeSpecifier arraySpecifier = parseArraySpecifier(reader, structDeclaration); if (arraySpecifier != null && reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { // SUCCESS } @@ -831,9 +822,9 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio reader.setCursor(cursor); // type_qualifier SEMICOLON - if(reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { - // FIXME struct declaration - } + if (reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { + // FIXME struct declaration + } // type_qualifier IDENTIFIER SEMICOLON // type_qualifier IDENTIFIER identifier_list SEMICOLON @@ -841,25 +832,19 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio return null; // FIXME } - private static @Nullable GlslNode parseIdentifierList(GlslTokenReader reader) { - // COMMA IDENTIFIER - // identifier_list COMMA IDENTIFIER - return null; // TODO - } - - private static @Nullable GlslFunctionHeader parseFunctionPrototype(GlslTokenReader reader) { + private static @Nullable GlslFunctionHeaderNode parseFunctionPrototype(GlslTokenReader reader) { int cursor = reader.getCursor(); // fully_specified_type IDENTIFIER LEFT_PAREN RIGHT_PAREN GlslSpecifiedType fullySpecifiedType = parseFullySpecifiedType(reader); if (fullySpecifiedType != null && reader.tryConsume(GlslLexer.TokenType.IDENTIFIER, GlslLexer.TokenType.LEFT_PAREN, GlslLexer.TokenType.RIGHT_PAREN)) { String name = reader.peek(-3).value(); - return new GlslFunctionHeader(name, fullySpecifiedType, new ArrayList<>()); + return new GlslFunctionHeaderNode(name, fullySpecifiedType, new ArrayList<>()); } reader.setCursor(cursor); // function_header_with_parameters RIGHT_PAREN - GlslFunctionHeader functionHeaderWithParameters = parseFunctionHeaderWithParameters(reader); + GlslFunctionHeaderNode functionHeaderWithParameters = parseFunctionHeaderWithParameters(reader); if (functionHeaderWithParameters != null) { return functionHeaderWithParameters; } @@ -870,7 +855,7 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio String name = reader.peek(-2).value(); GlslParameterDeclaration parameterDeclaration = parseParameterDeclaration(reader); if (parameterDeclaration != null && reader.tryConsume(GlslLexer.TokenType.RIGHT_PAREN)) { - return new GlslFunctionHeader(name, fullySpecifiedType, Collections.singletonList(parameterDeclaration)); + return new GlslFunctionHeaderNode(name, fullySpecifiedType, Collections.singletonList(parameterDeclaration)); } } reader.setCursor(cursor); @@ -914,7 +899,7 @@ private static List parseParameterList(GlslTokenReader return parameters; } - private static @Nullable GlslFunctionHeader parseFunctionHeaderWithParameters(GlslTokenReader reader) { + private static @Nullable GlslFunctionHeaderNode parseFunctionHeaderWithParameters(GlslTokenReader reader) { // fully_specified_type IDENTIFIER LEFT_PAREN parameter_declaration // function_header_with_parameters COMMA parameter_declaration @@ -924,7 +909,7 @@ private static List parseParameterList(GlslTokenReader String name = reader.peek(-2).value(); List parameters = parseParameterList(reader); if (reader.tryConsume(GlslLexer.TokenType.LEFT_PAREN)) { - return new GlslFunctionHeader(name, fullySpecifiedType, parameters); + return new GlslFunctionHeaderNode(name, fullySpecifiedType, parameters); } } @@ -949,8 +934,7 @@ private static List parseParameterList(GlslTokenReader String name = reader.peek(-1).value(); GlslTypeSpecifier arraySpecifier = parseArraySpecifier(reader, typeSpecifier); - return new GlslParameterDeclaration(name, new GlslSpecifiedType(Objects.requireNonNullElse(arraySpecifier, typeSpecifier))); - + return new GlslParameterDeclaration(name, Objects.requireNonNullElse(arraySpecifier, typeSpecifier)); } private static @Nullable GlslParameterDeclaration parseParameterDeclaration(GlslTokenReader reader) { @@ -982,7 +966,7 @@ private static List parseParameterList(GlslTokenReader // parameter_type_specifier GlslTypeSpecifier parameterTypeSpecifier = parseTypeSpecifier(reader); if (parameterTypeSpecifier != null) { - return new GlslParameterDeclaration(null, new GlslSpecifiedType(parameterTypeSpecifier)); + return new GlslParameterDeclaration(null, parameterTypeSpecifier); } return null; @@ -1252,12 +1236,12 @@ private static List parseParameterList(GlslTokenReader GlslLexer.Token token = reader.peek(); GlslTypeSpecifier.BuiltinType type = token.type().asBuiltinType(); if (type != null) { - typeSpecifier = GlslTypeSpecifier.simple(type); + typeSpecifier = type; reader.skip(); } else { GlslStructSpecifier structSpecifier = parseStructSpecifier(reader); if (structSpecifier != null) { - typeSpecifier = GlslTypeSpecifier.struct(structSpecifier); + typeSpecifier = structSpecifier; } else { if (token.type() == GlslLexer.TokenType.IDENTIFIER) { reader.skip(); @@ -1668,42 +1652,107 @@ private static List parseStatementList(GlslTokenReader reader) { } private static @Nullable GlslNode parseIterationStatement(GlslTokenReader reader) { + int cursor = reader.getCursor(); + // WHILE LEFT_PAREN condition RIGHT_PAREN statement_no_new_scope + if (reader.tryConsume(GlslLexer.TokenType.WHILE, GlslLexer.TokenType.LEFT_PAREN)) { + GlslNode condition = parseCondition(reader); + if (condition != null && reader.tryConsume(GlslLexer.TokenType.RIGHT_PAREN)) { + GlslNode body = parseStatementNoNewScope(reader); + if (body != null) { + return new WhileLoopNode(condition, body, WhileLoopNode.Type.WHILE); + } + } + } + reader.setCursor(cursor); + // DO statement WHILE LEFT_PAREN condition RIGHT_PAREN SEMICOLON + if (reader.tryConsume(GlslLexer.TokenType.DO)) { + GlslNode body = parseStatement(reader); + if (body != null && reader.tryConsume(GlslLexer.TokenType.WHILE, GlslLexer.TokenType.LEFT_PAREN)) { + GlslNode condition = parseCondition(reader); + if (condition != null && reader.tryConsume(GlslLexer.TokenType.RIGHT_PAREN, GlslLexer.TokenType.SEMICOLON)) { + return new WhileLoopNode(condition, body, WhileLoopNode.Type.DO); + } + } + } + reader.setCursor(cursor); + // FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope - return null; // TODO + if (reader.tryConsume(GlslLexer.TokenType.FOR, GlslLexer.TokenType.LEFT_PAREN)) { + GlslNode init = parseForInitStatement(reader); + if (init != null) { + GlslNode condition = parseConditionopt(reader); + if (condition != null && reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { + GlslNode increment = parseCondition(reader); + if (reader.tryConsume(GlslLexer.TokenType.RIGHT_PAREN)) { + GlslNode body = parseStatementNoNewScope(reader); + if (body != null) { + return new ForLoopNode(init, condition, increment, body); + } + } + } + } + } + reader.setCursor(cursor); + return null; } private static @Nullable GlslNode parseForInitStatement(GlslTokenReader reader) { // expression_statement + GlslNode expressionStatement = parseExpressionStatement(reader); + if (expressionStatement != null) { + return expressionStatement; + } + // declaration_statement - return null; // TODO + return parseDeclaration(reader); } - private static @Nullable GlslNode parseConditionopt(GlslTokenReader reader) { + private static GlslNode parseConditionopt(GlslTokenReader reader) { // condition - return null; // TODO - } - - private static @Nullable GlslNode parseForRestStatement(GlslTokenReader reader) { - // conditionopt SEMICOLON - // conditionopt SEMICOLON condition - return null; // TODO + GlslNode condition = parseCondition(reader); + return condition != null ? condition : GlslEmptyNode.INSTANCE; } private static @Nullable GlslNode parseJumpStatement(GlslTokenReader reader) { // CONTINUE SEMICOLON + if (reader.tryConsume(GlslLexer.TokenType.CONTINUE, GlslLexer.TokenType.SEMICOLON)) { + return JumpNode.CONTINUE; + } + // BREAK SEMICOLON - // RETURN SEMICOLON - // RETURN condition SEMICOLON + if (reader.tryConsume(GlslLexer.TokenType.BREAK, GlslLexer.TokenType.SEMICOLON)) { + return JumpNode.BREAK; + } + + int cursor = reader.getCursor(); + if (reader.tryConsume(GlslLexer.TokenType.RETURN)) { + // RETURN SEMICOLON + if (reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { + return new ReturnNode(null); + } + + // RETURN condition SEMICOLON + GlslNode condition = parseCondition(reader); + if (condition != null && reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { + return new ReturnNode(condition); + } + } + reader.setCursor(cursor); + // DISCARD SEMICOLON - return null; // TODO + if (reader.tryConsume(GlslLexer.TokenType.DISCARD, GlslLexer.TokenType.SEMICOLON)) { + return JumpNode.DISCARD; + } + + return null; } - private static @Nullable GlslFunction parseFunctionDefinition(GlslTokenReader reader) { + private static @Nullable GlslFunctionNode parseFunctionDefinition(GlslTokenReader reader) { int cursor = reader.getCursor(); - GlslFunctionHeader functionPrototype = parseFunctionPrototype(reader); + GlslFunctionHeaderNode functionPrototype = parseFunctionPrototype(reader); if (functionPrototype == null) { return null; } @@ -1715,6 +1764,6 @@ private static List parseStatementList(GlslTokenReader reader) { } // function_prototype compound_statement_no_new_scope - return new GlslFunction(functionPrototype, statement); + return new GlslFunctionNode(functionPrototype, statement); } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslParameterDeclaration.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslParameterDeclaration.java index 49a9e091..90178143 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslParameterDeclaration.java +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslParameterDeclaration.java @@ -4,34 +4,77 @@ import java.util.Collection; +/** + * Represents a single parameter declaration. Includes the name and full data type of the parameter. + * + * @author Ocelot + */ public class GlslParameterDeclaration { private String name; private GlslSpecifiedType type; - public GlslParameterDeclaration(@Nullable String name, GlslSpecifiedType type) { + public GlslParameterDeclaration(@Nullable String name, GlslType type) { this.name = name; - this.type = type; + this.type = type.asSpecifiedType(); } - public String getName() { + /** + * @return The name of the parameter or null if declared like void foo(int) + */ + public @Nullable String getName() { return this.name; } + /** + * @return The parameter data type + */ public GlslSpecifiedType getType() { return this.type; } - public void setName(@Nullable String name) { + /** + * Sets the name of this parameter. + * + * @param name The new name + */ + public GlslParameterDeclaration setName(@Nullable String name) { this.name = name; + return this; + } + + /** + * Sets the data type of this parameter. + * + * @param type The new type + */ + public GlslParameterDeclaration setType(GlslType type) { + this.type = type.asSpecifiedType(); + return this; } - public void setType(GlslSpecifiedType type) { - this.type = type; + /** + * Sets The qualifiers of this parameter type. + * + * @param qualifiers The new qualifiers + */ + public GlslParameterDeclaration setQualifiers(GlslTypeQualifier... qualifiers) { + this.type.setQualifiers(qualifiers); + return this; } + /** + * Sets The qualifiers of this parameter type. + * + * @param qualifiers The new qualifiers + */ public GlslParameterDeclaration setQualifiers(Collection qualifiers) { this.type.setQualifiers(qualifiers); return this; } + + @Override + public String toString() { + return "GlslParameterDeclaration{name='" + this.name + "', type=" + this.type + '}'; + } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslSpecifiedType.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslSpecifiedType.java index ea001a75..ca7dabab 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslSpecifiedType.java +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslSpecifiedType.java @@ -7,9 +7,6 @@ /** * Specifies the full operand of something in GLSL in addition to all qualifiers. - * - * @param type The operand of the field, method, etc - * @param qualifiers The qualifiers applied to it, for example layout() or flat */ public class GlslSpecifiedType implements GlslType { @@ -31,19 +28,36 @@ public GlslSpecifiedType(GlslTypeSpecifier type, GlslTypeQualifier... qualifiers this.qualifiers.addAll(Arrays.asList(qualifiers)); } + /** + * @return The operand of the field, method, etc + */ public GlslTypeSpecifier getType() { return this.type; } + /** + * @return The qualifiers applied to it, for example layout() or flat + */ public List getQualifiers() { return this.qualifiers; } + /** + * Sets the type of this + * @param type + * @return + */ public GlslSpecifiedType setType(GlslTypeSpecifier type) { this.type = type; return this; } + public GlslSpecifiedType setQualifiers(GlslTypeQualifier... qualifiers) { + this.qualifiers.clear(); + this.qualifiers.addAll(Arrays.asList(qualifiers)); + return this; + } + public GlslSpecifiedType setQualifiers(Collection qualifiers) { this.qualifiers.clear(); this.qualifiers.addAll(qualifiers); @@ -56,7 +70,7 @@ public String toString() { } @Override - public GlslSpecifiedType asGlslSpecifiedType() { + public GlslSpecifiedType asSpecifiedType() { return this; } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructSpecifier.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructSpecifier.java index 2a7e7006..842e7e7e 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructSpecifier.java +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructSpecifier.java @@ -1,5 +1,5 @@ package foundry.veil.impl.glsl.grammar; // TODO -public record GlslStructSpecifier() { +public record GlslStructSpecifier() implements GlslTypeSpecifier { } diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslType.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslType.java index 8c0e9bbf..2954768e 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslType.java +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslType.java @@ -2,6 +2,6 @@ public interface GlslType { - GlslSpecifiedType asGlslSpecifiedType(); + GlslSpecifiedType asSpecifiedType(); } diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeSpecifier.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeSpecifier.java index 7c29d2a7..a8d82579 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeSpecifier.java +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeSpecifier.java @@ -5,12 +5,8 @@ public interface GlslTypeSpecifier extends GlslType { - static GlslTypeSpecifier simple(BuiltinType type) { - return new Simple(type); - } - - static GlslTypeSpecifier struct(GlslStructSpecifier structSpecifier) { - return new Struct(structSpecifier); + default boolean isNamed() { + return this instanceof Name; } static GlslTypeSpecifier named(String name) { @@ -22,23 +18,21 @@ static GlslTypeSpecifier array(GlslTypeSpecifier specifier, @Nullable GlslNode s } @Override - default GlslSpecifiedType asGlslSpecifiedType() { + default GlslSpecifiedType asSpecifiedType() { return new GlslSpecifiedType(this); } - record Simple(BuiltinType type) implements GlslTypeSpecifier { - } - - record Struct(GlslStructSpecifier structSpecifier) implements GlslTypeSpecifier { - } - record Name(String name) implements GlslTypeSpecifier { } record Array(GlslTypeSpecifier specifier, @Nullable GlslNode size) implements GlslTypeSpecifier { + @Override + public boolean isNamed() { + return this.specifier.isNamed(); + } } - enum BuiltinType { + enum BuiltinType implements GlslTypeSpecifier { VOID, FLOAT, DOUBLE, diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java index f70fc18d..7aaaa5e3 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java @@ -18,7 +18,9 @@ public GlslTree(GlslVersion version, Collection body) { } public void visit(GlslVisitor visitor) { - + for (GlslNode node : this.body) { + node.visit(visitor); + } } public GlslVersion getVersion() { diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/ForLoopNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/ForLoopNode.java new file mode 100644 index 00000000..91a52c91 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/ForLoopNode.java @@ -0,0 +1,66 @@ +package foundry.veil.impl.glsl.node.branch; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; +import org.jetbrains.annotations.Nullable; + +/** + * Represents for loops. + * + * @author Ocelot + */ +public class ForLoopNode implements GlslNode { + + private GlslNode init; + private GlslNode condition; + private GlslNode increment; + private GlslNode body; + + public ForLoopNode(GlslNode init, GlslNode condition, @Nullable GlslNode increment, GlslNode body) { + this.init = init; + this.condition = condition; + this.increment = increment; + this.body = body; + } + + @Override + public void visit(GlslVisitor visitor) { + } + + public GlslNode getInit() { + return this.init; + } + + public GlslNode getCondition() { + return this.condition; + } + + public @Nullable GlslNode getIncrement() { + return this.increment; + } + + public GlslNode getBody() { + return this.body; + } + + public void setInit(GlslNode init) { + this.init = init; + } + + public void setCondition(GlslNode condition) { + this.condition = condition; + } + + public void setIncrement(GlslNode increment) { + this.increment = increment; + } + + public void setBody(GlslNode body) { + this.body = body; + } + + @Override + public String toString() { + return "ForLoopNode{init=" + this.init + ", condition=" + this.condition + ", increment=" + this.increment + ", body=" + this.body + '}'; + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslCaseLabelNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslCaseLabelNode.java index e3f860f5..c0c3e16f 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslCaseLabelNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslCaseLabelNode.java @@ -4,14 +4,33 @@ import foundry.veil.impl.glsl.visitor.GlslVisitor; import org.jetbrains.annotations.Nullable; -public record GlslCaseLabelNode(@Nullable GlslNode condition) implements GlslNode { +public class GlslCaseLabelNode implements GlslNode { - public boolean isDefault() { - return this.condition == null; + private GlslNode condition; + + public GlslCaseLabelNode(@Nullable GlslNode condition) { + this.condition = condition; } @Override public void visit(GlslVisitor visitor) { + visitor.visitCaseLabel(this); + } + public boolean isDefault() { + return this.condition == null; + } + + public GlslNode getCondition() { + return this.condition; + } + + public void setCondition(@Nullable GlslNode condition) { + this.condition = condition; + } + + @Override + public String toString() { + return "GlslCaseLabelNode{condition=" + (this.condition == null ? "default" : this.condition) + '}'; } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/JumpNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/JumpNode.java new file mode 100644 index 00000000..0fec3a0d --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/JumpNode.java @@ -0,0 +1,14 @@ +package foundry.veil.impl.glsl.node.branch; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +public enum JumpNode implements GlslNode { + + CONTINUE, BREAK, DISCARD; + + @Override + public void visit(GlslVisitor visitor) { + + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/ReturnNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/ReturnNode.java new file mode 100644 index 00000000..54152e62 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/ReturnNode.java @@ -0,0 +1,32 @@ +package foundry.veil.impl.glsl.node.branch; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; +import org.jetbrains.annotations.Nullable; + +public class ReturnNode implements GlslNode { + + private GlslNode value; + + public ReturnNode(@Nullable GlslNode value) { + this.value = value; + } + + @Override + public void visit(GlslVisitor visitor) { + + } + + public @Nullable GlslNode getValue() { + return this.value; + } + + public void setValue(@Nullable GlslNode value) { + this.value = value; + } + + @Override + public String toString() { + return "ReturnNode{value=" + this.value + '}'; + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/WhileLoopNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/WhileLoopNode.java new file mode 100644 index 00000000..1cbcd122 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/WhileLoopNode.java @@ -0,0 +1,54 @@ +package foundry.veil.impl.glsl.node.branch; + +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +/** + * Represents both while and do/while loops. + * + * @author Ocelot + */ +public class WhileLoopNode implements GlslNode { + + private GlslNode condition; + private GlslNode body; + private Type type; + + public WhileLoopNode(GlslNode condition, GlslNode body, Type type) { + this.condition = condition; + this.body = body; + this.type = type; + } + + @Override + public void visit(GlslVisitor visitor) { + } + + public GlslNode getCondition() { + return this.condition; + } + + public GlslNode getBody() { + return this.body; + } + + public Type getType() { + return this.type; + } + + public void setCondition(GlslNode condition) { + this.condition = condition; + } + + public void setBody(GlslNode body) { + this.body = body; + } + + public void setType(Type type) { + this.type = type; + } + + public enum Type { + WHILE, DO + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionHeader.java b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionHeaderNode.java similarity index 63% rename from common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionHeader.java rename to common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionHeaderNode.java index 094834aa..acca4dde 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionHeader.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionHeaderNode.java @@ -1,6 +1,7 @@ package foundry.veil.impl.glsl.node.function; import foundry.veil.impl.glsl.grammar.GlslSpecifiedType; +import foundry.veil.impl.glsl.grammar.GlslType; import foundry.veil.impl.glsl.node.GlslNode; import foundry.veil.impl.glsl.grammar.GlslParameterDeclaration; import foundry.veil.impl.glsl.visitor.GlslVisitor; @@ -10,20 +11,20 @@ import java.util.Collection; import java.util.List; -public class GlslFunctionHeader implements GlslNode { +public class GlslFunctionHeaderNode implements GlslNode { private String name; private GlslSpecifiedType returnType; private final List parameters; - public GlslFunctionHeader(String name, GlslSpecifiedType returnType, Collection parameters) { + public GlslFunctionHeaderNode(String name, GlslType returnType, Collection parameters) { this.name = name; - this.returnType = returnType; + this.returnType = returnType.asSpecifiedType(); this.parameters = new ArrayList<>(parameters); } - public GlslFunctionHeader withParameters(GlslParameterDeclaration... parameters) { - return new GlslFunctionHeader(this.name, this.returnType, new ArrayList<>(Arrays.asList(parameters))); + public GlslFunctionHeaderNode withParameters(GlslParameterDeclaration... parameters) { + return new GlslFunctionHeaderNode(this.name, this.returnType, new ArrayList<>(Arrays.asList(parameters))); } public String getName() { @@ -38,13 +39,13 @@ public List getParameters() { return this.parameters; } - public GlslFunctionHeader setName(String name) { + public GlslFunctionHeaderNode setName(String name) { this.name = name; return this; } - public GlslFunctionHeader setReturnType(GlslSpecifiedType returnType) { - this.returnType = returnType; + public GlslFunctionHeaderNode setReturnType(GlslType returnType) { + this.returnType = returnType.asSpecifiedType(); return this; } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunction.java b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionNode.java similarity index 70% rename from common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunction.java rename to common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionNode.java index 3d239e4b..566e3efe 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunction.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionNode.java @@ -3,12 +3,12 @@ import foundry.veil.impl.glsl.node.GlslNode; import foundry.veil.impl.glsl.visitor.GlslVisitor; -public class GlslFunction implements GlslNode { +public class GlslFunctionNode implements GlslNode { - private GlslFunctionHeader header; + private GlslFunctionHeaderNode header; private GlslNode body; - public GlslFunction(GlslFunctionHeader header, GlslNode body) { + public GlslFunctionNode(GlslFunctionHeaderNode header, GlslNode body) { this.header = header; this.body = body; } @@ -18,7 +18,7 @@ public void visit(GlslVisitor visitor) { } - public GlslFunctionHeader getHeader() { + public GlslFunctionHeaderNode getHeader() { return this.header; } @@ -26,7 +26,7 @@ public GlslNode getBody() { return this.body; } - public void setHeader(GlslFunctionHeader header) { + public void setHeader(GlslFunctionHeaderNode header) { this.header = header; } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslInvokeFunctionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslInvokeFunctionNode.java index b5b976da..eadc5353 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslInvokeFunctionNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslInvokeFunctionNode.java @@ -36,6 +36,6 @@ public void setHeader(GlslNode header) { @Override public String toString() { - return "GlslInvokeFunctionNode{header=" + this.header + ", parameters=" + this.parameters + '}'; + return "GlslInvokeFunctionNode{name=" + this.header + ", parameters=" + this.parameters + '}'; } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/function/PrimitiveConstructorNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/function/PrimitiveConstructorNode.java new file mode 100644 index 00000000..245f4c99 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/function/PrimitiveConstructorNode.java @@ -0,0 +1,32 @@ +package foundry.veil.impl.glsl.node.function; + +import foundry.veil.impl.glsl.grammar.GlslTypeSpecifier; +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.visitor.GlslVisitor; + +public class PrimitiveConstructorNode implements GlslNode { + + private GlslTypeSpecifier type; + + public PrimitiveConstructorNode(GlslTypeSpecifier type) { + this.type = type; + } + + public GlslTypeSpecifier getType() { + return this.type; + } + + public void setType(GlslTypeSpecifier type) { + this.type = type; + } + + @Override + public void visit(GlslVisitor visitor) { + + } + + @Override + public String toString() { + return "PrimitiveConstructorNode{type=" + this.type + '}'; + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslNewNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslNewNode.java index 0b5962b8..b8dc32e6 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslNewNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslNewNode.java @@ -1,5 +1,6 @@ package foundry.veil.impl.glsl.node.variable; +import foundry.veil.impl.glsl.grammar.GlslType; import foundry.veil.impl.glsl.node.GlslNode; import foundry.veil.impl.glsl.visitor.GlslVisitor; import foundry.veil.impl.glsl.grammar.GlslSpecifiedType; @@ -9,7 +10,17 @@ import java.util.Collections; import java.util.List; -public record GlslNewNode(GlslSpecifiedType type, String name, @Nullable GlslNode initializer) implements GlslNode { +public class GlslNewNode implements GlslNode { + + private GlslSpecifiedType type; + private String name; + private GlslNode initializer; + + public GlslNewNode(GlslType type, String name, @Nullable GlslNode initializer) { + this.type = type.asSpecifiedType(); + this.name = name; + this.initializer = initializer; + } @Override public void visit(GlslVisitor visitor) { @@ -19,4 +30,36 @@ public void visit(GlslVisitor visitor) { public Collection children() { return this.initializer != null ? List.of(this.initializer) : Collections.emptyList(); } + + public GlslSpecifiedType getType() { + return this.type; + } + + public String getName() { + return this.name; + } + + public GlslNode getInitializer() { + return this.initializer; + } + + public GlslNewNode setType(GlslType type) { + this.type = type.asSpecifiedType(); + return this; + } + + public GlslNewNode setName(String name) { + this.name = name; + return this; + } + + public GlslNewNode setInitializer(@Nullable GlslNode initializer) { + this.initializer = initializer; + return this; + } + + @Override + public String toString() { + return "GlslNewNode{type=" + this.type + ", name='" + this.name + "', initializer=" + this.initializer + '}'; + } } \ No newline at end of file diff --git a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslFieldVisitor.java b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslFieldVisitor.java new file mode 100644 index 00000000..05bb761e --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslFieldVisitor.java @@ -0,0 +1,4 @@ +package foundry.veil.impl.glsl.visitor; + +public interface GlslFieldVisitor { +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslFunctionVisitor.java b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslFunctionVisitor.java new file mode 100644 index 00000000..5cf321e2 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslFunctionVisitor.java @@ -0,0 +1,4 @@ +package foundry.veil.impl.glsl.visitor; + +public interface GlslFunctionVisitor { +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslVisitor.java b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslVisitor.java index 3423d2ea..638df832 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslVisitor.java +++ b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslVisitor.java @@ -1,4 +1,18 @@ package foundry.veil.impl.glsl.visitor; +import foundry.veil.impl.glsl.node.branch.ForLoopNode; +import foundry.veil.impl.glsl.node.branch.GlslCaseLabelNode; +import foundry.veil.impl.glsl.node.variable.GlslFieldNode; + public interface GlslVisitor { + + default GlslFieldVisitor visitField(GlslFieldNode node) { + return null; + } + + default void visitForLoop(ForLoopNode node) { + } + + default void visitCaseLabel(GlslCaseLabelNode node) { + } } diff --git a/common/src/test/java/GlslTest.java b/common/src/test/java/GlslTest.java index 34d81f6e..3756b460 100644 --- a/common/src/test/java/GlslTest.java +++ b/common/src/test/java/GlslTest.java @@ -79,6 +79,10 @@ void testShader() throws GlslSyntaxException { out vec4 fragColor; + vec3 test(int) { + return normalize(vec3(7.0, 0.0, 1.0)); + } + void main() { vec4 baseColor = texture(DiffuseSampler0, texCoord); float depthSample = texture(DiffuseDepthSampler, texCoord).r; @@ -92,5 +96,19 @@ void main() { GlslTree tree = GlslParser.parse(tokens); long end = System.nanoTime(); System.out.printf("Took %.1fms to tokenize, %.1fms to parse%n", (parseStart - start) / 1_000_000.0F, (end - parseStart) / 1_000_000.0F); + System.out.println(tree); + } + + @Test + void testReturn() throws GlslSyntaxException { + GlslLexer.Token[] tokens = GlslLexer.createTokens(""" + #version 430 core + + vec3 test(int) { + return normalize(vec3(7.0, 0.0, 1.0)); + } + """); + GlslTree tree = GlslParser.parse(tokens); + System.out.println(tree); } } From f4604e760af1d0d0ab060ec3cb07be07409d0771 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Sun, 10 Nov 2024 18:55:03 -0700 Subject: [PATCH 33/47] Added more trees and source code generation --- .../veil/impl/TickTaskSchedulerImpl.java | 2 +- .../foundry/veil/impl/glsl/GlslParser.java | 68 ++++++------ .../veil/impl/glsl/GlslTokenReader.java | 23 ++++ .../impl/glsl/grammar/GlslFunctionHeader.java | 62 +++++++++++ .../grammar/GlslParameterDeclaration.java | 14 +-- .../impl/glsl/grammar/GlslSpecifiedType.java | 37 ++++--- .../glsl/grammar/GlslStructSpecifier.java | 5 + .../impl/glsl/grammar/GlslTypeQualifier.java | 76 +++++++++++-- .../impl/glsl/grammar/GlslTypeSpecifier.java | 22 +++- .../veil/impl/glsl/grammar/GlslVersion.java | 74 ++++++++++++- .../veil/impl/glsl/node/GlslCompoundNode.java | 53 ++++++++- .../veil/impl/glsl/node/GlslConstantNode.java | 22 +++- .../veil/impl/glsl/node/GlslEmptyNode.java | 17 ++- .../foundry/veil/impl/glsl/node/GlslNode.java | 37 +++++-- .../foundry/veil/impl/glsl/node/GlslTree.java | 32 ++++-- .../impl/glsl/node/branch/ForLoopNode.java | 18 +++- .../glsl/node/branch/GlslCaseLabelNode.java | 12 +-- .../{ReturnNode.java => GlslReturnNode.java} | 15 ++- .../glsl/node/branch/GlslSelectionNode.java | 12 ++- .../impl/glsl/node/branch/GlslSwitchNode.java | 77 ++++++++++++- .../veil/impl/glsl/node/branch/JumpNode.java | 7 +- .../impl/glsl/node/branch/WhileLoopNode.java | 19 ++-- .../glsl/node/expression/GlslAndNode.java | 36 ++++++- .../node/expression/GlslAssignmentNode.java | 102 +++++++++++++++--- .../glsl/node/expression/GlslCompareNode.java | 83 ++++++++++++-- .../node/expression/GlslConditionalNode.java | 54 ++++++++-- .../node/expression/GlslExclusiveOrNode.java | 7 +- .../node/expression/GlslInclusiveOrNode.java | 7 +- .../node/expression/GlslLogicalAndNode.java | 7 +- .../node/expression/GlslLogicalOrNode.java | 7 +- .../node/expression/GlslLogicalXorNode.java | 7 +- .../node/expression/GlslOperationNode.java | 77 +++++++++++-- ...cisionNode.java => GlslPrecisionNode.java} | 21 ++-- .../glsl/node/expression/GlslUnaryNode.java | 67 ++++++++++-- .../node/function/GlslFunctionHeaderNode.java | 61 ----------- .../glsl/node/function/GlslFunctionNode.java | 99 ++++++++++++++--- .../node/function/GlslInvokeFunctionNode.java | 14 +-- ...java => GlslPrimitiveConstructorNode.java} | 13 ++- .../node/primary/GlslBoolConstantNode.java | 22 +++- .../node/primary/GlslDoubleConstantNode.java | 27 ++++- .../node/primary/GlslFloatConstantNode.java | 27 ++++- .../node/primary/GlslIntConstantNode.java | 33 +++++- .../node/primary/GlslUIntConstantNode.java | 17 --- .../glsl/node/variable/GlslArrayNode.java | 39 +++++-- .../glsl/node/variable/GlslFieldNode.java | 39 +++++-- .../impl/glsl/node/variable/GlslNewNode.java | 23 ++-- .../glsl/node/variable/GlslVariableNode.java | 26 ++++- .../glsl/visitor/GlslFunctionVisitor.java | 18 ++++ .../impl/glsl/visitor/GlslNodeVisitor.java | 9 ++ .../impl/glsl/visitor/GlslStringWriter.java | 49 +++++++++ .../impl/glsl/visitor/GlslTreeVisitor.java | 17 +++ .../veil/impl/glsl/visitor/GlslVisitor.java | 18 ---- .../pinwheel/shaders/program/light/area.vsh | 2 +- common/src/test/java/GlslTest.java | 59 ++++++---- 54 files changed, 1386 insertions(+), 405 deletions(-) create mode 100644 common/src/main/java/foundry/veil/impl/glsl/grammar/GlslFunctionHeader.java rename common/src/main/java/foundry/veil/impl/glsl/node/branch/{ReturnNode.java => GlslReturnNode.java} (68%) rename common/src/main/java/foundry/veil/impl/glsl/node/expression/{PrecisionNode.java => GlslPrecisionNode.java} (57%) delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionHeaderNode.java rename common/src/main/java/foundry/veil/impl/glsl/node/function/{PrimitiveConstructorNode.java => GlslPrimitiveConstructorNode.java} (61%) delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslUIntConstantNode.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/visitor/GlslNodeVisitor.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/visitor/GlslStringWriter.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/visitor/GlslTreeVisitor.java delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/visitor/GlslVisitor.java diff --git a/common/src/main/java/foundry/veil/impl/TickTaskSchedulerImpl.java b/common/src/main/java/foundry/veil/impl/TickTaskSchedulerImpl.java index 88a82f36..d8b4b09b 100644 --- a/common/src/main/java/foundry/veil/impl/TickTaskSchedulerImpl.java +++ b/common/src/main/java/foundry/veil/impl/TickTaskSchedulerImpl.java @@ -76,7 +76,7 @@ public void shutdown() { iterator.remove(); } if (!this.tasks.isEmpty()) { - throw new IllegalStateException(this.tasks.size() + " tasks were left over!"); + throw new IllegalStateException(this.tasks.size() + " tasks were first over!"); } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java b/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java index 1f2b8b92..0a351c2a 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java +++ b/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java @@ -5,9 +5,9 @@ import foundry.veil.impl.glsl.node.branch.*; import foundry.veil.impl.glsl.node.expression.*; import foundry.veil.impl.glsl.node.function.GlslFunctionNode; -import foundry.veil.impl.glsl.node.function.GlslFunctionHeaderNode; +import foundry.veil.impl.glsl.grammar.GlslFunctionHeader; import foundry.veil.impl.glsl.node.function.GlslInvokeFunctionNode; -import foundry.veil.impl.glsl.node.function.PrimitiveConstructorNode; +import foundry.veil.impl.glsl.node.function.GlslPrimitiveConstructorNode; import foundry.veil.impl.glsl.node.variable.GlslArrayNode; import foundry.veil.impl.glsl.node.primary.*; import foundry.veil.impl.glsl.node.variable.GlslFieldNode; @@ -123,7 +123,8 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio try { int ver = Integer.parseInt(parts[0]); boolean core = parts.length == 1 || parts[1].equals("core"); - version = new GlslVersion(ver, core); + version.setVersion(ver); + version.setCore(core); } catch (NumberFormatException e) { throw reader.error("Invalid Version: " + token.value() + ". " + e.getMessage()); } @@ -131,7 +132,7 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio List body = new ArrayList<>(); while (reader.canRead()) { - GlslNode functionDefinition = parseFunctionDefinition(reader); + GlslFunctionNode functionDefinition = parseFunctionDefinition(reader); if (functionDefinition != null) { body.add(functionDefinition); continue; @@ -167,22 +168,22 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio return new GlslVariableNode(variableName); } if (reader.tryConsume(GlslLexer.TokenType.INTEGER_DECIMAL_CONSTANT)) { - return new GlslIntConstantNode(GlslIntFormat.DECIMAL, Integer.parseUnsignedInt(reader.peek(-1).value(), 10)); + return new GlslIntConstantNode(GlslIntFormat.DECIMAL, true, Integer.parseUnsignedInt(reader.peek(-1).value(), 10)); } if (reader.tryConsume(GlslLexer.TokenType.INTEGER_HEXADECIMAL_CONSTANT)) { - return new GlslIntConstantNode(GlslIntFormat.HEXADECIMAL, Integer.parseUnsignedInt(reader.peek(-1).value(), 16)); + return new GlslIntConstantNode(GlslIntFormat.HEXADECIMAL, true, Integer.parseUnsignedInt(reader.peek(-1).value(), 16)); } if (reader.tryConsume(GlslLexer.TokenType.INTEGER_OCTAL_CONSTANT)) { - return new GlslIntConstantNode(GlslIntFormat.OCTAL, Integer.parseUnsignedInt(reader.peek(-1).value(), 8)); + return new GlslIntConstantNode(GlslIntFormat.OCTAL, true, Integer.parseUnsignedInt(reader.peek(-1).value(), 8)); } if (reader.tryConsume(GlslLexer.TokenType.UINTEGER_DECIMAL_CONSTANT)) { - return new GlslUIntConstantNode(GlslIntFormat.DECIMAL, Integer.parseUnsignedInt(reader.peek(-1).value(), 10)); + return new GlslIntConstantNode(GlslIntFormat.DECIMAL, false, Integer.parseUnsignedInt(reader.peek(-1).value(), 10)); } if (reader.tryConsume(GlslLexer.TokenType.UINTEGER_HEXADECIMAL_CONSTANT)) { - return new GlslUIntConstantNode(GlslIntFormat.HEXADECIMAL, Integer.parseUnsignedInt(reader.peek(-1).value(), 16)); + return new GlslIntConstantNode(GlslIntFormat.HEXADECIMAL, false, Integer.parseUnsignedInt(reader.peek(-1).value(), 16)); } if (reader.tryConsume(GlslLexer.TokenType.UINTEGER_OCTAL_CONSTANT)) { - return new GlslUIntConstantNode(GlslIntFormat.OCTAL, Integer.parseUnsignedInt(reader.peek(-1).value(), 8)); + return new GlslIntConstantNode(GlslIntFormat.OCTAL, false, Integer.parseUnsignedInt(reader.peek(-1).value(), 8)); } if (reader.tryConsume(GlslLexer.TokenType.FLOATING_CONSTANT)) { return new GlslFloatConstantNode(Float.parseFloat(reader.peek(-1).value())); @@ -347,7 +348,7 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio // type_specifier LEFT_PAREN GlslTypeSpecifier typeSpecifier = parseTypeSpecifier(reader); if (typeSpecifier != null && !typeSpecifier.isNamed() && reader.tryConsume(GlslLexer.TokenType.LEFT_PAREN)) { - return new PrimitiveConstructorNode(typeSpecifier); + return new GlslPrimitiveConstructorNode(typeSpecifier); } reader.setCursor(cursor); @@ -568,7 +569,7 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio reader.setCursor(cursor); return left; } - left = new GlslCompareNode(left, right, GlslCompareNode.Type.LESS); + left = new GlslCompareNode(left, right, GlslCompareNode.Operand.LESS); continue; } if (reader.tryConsume(GlslLexer.TokenType.RIGHT_ANGLE)) { @@ -577,7 +578,7 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio reader.setCursor(cursor); return left; } - left = new GlslCompareNode(left, right, GlslCompareNode.Type.GREATER); + left = new GlslCompareNode(left, right, GlslCompareNode.Operand.GREATER); continue; } if (reader.tryConsume(GlslLexer.TokenType.LE_OP)) { @@ -586,7 +587,7 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio reader.setCursor(cursor); return left; } - left = new GlslCompareNode(left, right, GlslCompareNode.Type.LEQUAL); + left = new GlslCompareNode(left, right, GlslCompareNode.Operand.LEQUAL); continue; } if (reader.tryConsume(GlslLexer.TokenType.GE_OP)) { @@ -595,7 +596,7 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio reader.setCursor(cursor); return left; } - left = new GlslCompareNode(left, right, GlslCompareNode.Type.GEQUAL); + left = new GlslCompareNode(left, right, GlslCompareNode.Operand.GEQUAL); continue; } break; @@ -622,7 +623,7 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio reader.setCursor(cursor); return left; } - left = new GlslCompareNode(left, right, GlslCompareNode.Type.EQUAL); + left = new GlslCompareNode(left, right, GlslCompareNode.Operand.EQUAL); continue; } if (reader.tryConsume(GlslLexer.TokenType.NE_OP)) { @@ -631,7 +632,7 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio reader.setCursor(cursor); return left; } - left = new GlslCompareNode(left, right, GlslCompareNode.Type.NOT_EQUAL); + left = new GlslCompareNode(left, right, GlslCompareNode.Operand.NOT_EQUAL); continue; } break; @@ -689,7 +690,9 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio GlslNode first = parseExpression(reader); if (first != null && reader.tryConsume(GlslLexer.TokenType.COLON)) { GlslNode branch = parseAssignmentExpression(reader); - return new GlslConditionalNode(logicalOr, first, branch); + if (branch != null) { + return new GlslConditionalNode(logicalOr, first, branch); + } } } @@ -757,10 +760,10 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio int cursor = reader.getCursor(); // function_prototype SEMICOLON - GlslNode functionPrototype = parseFunctionPrototype(reader); + GlslFunctionHeader functionPrototype = parseFunctionPrototype(reader); if (functionPrototype != null) { if (reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { - return functionPrototype; + return new GlslFunctionNode(functionPrototype, null); } reader.setCursor(cursor); } @@ -780,7 +783,7 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio if (precisionQualifier != null) { GlslTypeSpecifier typeSpecifier = parseTypeSpecifier(reader); if (typeSpecifier != null && reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { - return new PrecisionNode(precisionQualifier, typeSpecifier); + return new GlslPrecisionNode(precisionQualifier, typeSpecifier); } } reader.setCursor(cursor); @@ -832,19 +835,19 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio return null; // FIXME } - private static @Nullable GlslFunctionHeaderNode parseFunctionPrototype(GlslTokenReader reader) { + private static @Nullable GlslFunctionHeader parseFunctionPrototype(GlslTokenReader reader) { int cursor = reader.getCursor(); // fully_specified_type IDENTIFIER LEFT_PAREN RIGHT_PAREN GlslSpecifiedType fullySpecifiedType = parseFullySpecifiedType(reader); if (fullySpecifiedType != null && reader.tryConsume(GlslLexer.TokenType.IDENTIFIER, GlslLexer.TokenType.LEFT_PAREN, GlslLexer.TokenType.RIGHT_PAREN)) { String name = reader.peek(-3).value(); - return new GlslFunctionHeaderNode(name, fullySpecifiedType, new ArrayList<>()); + return new GlslFunctionHeader(name, fullySpecifiedType, new ArrayList<>()); } reader.setCursor(cursor); // function_header_with_parameters RIGHT_PAREN - GlslFunctionHeaderNode functionHeaderWithParameters = parseFunctionHeaderWithParameters(reader); + GlslFunctionHeader functionHeaderWithParameters = parseFunctionHeaderWithParameters(reader); if (functionHeaderWithParameters != null) { return functionHeaderWithParameters; } @@ -855,7 +858,7 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio String name = reader.peek(-2).value(); GlslParameterDeclaration parameterDeclaration = parseParameterDeclaration(reader); if (parameterDeclaration != null && reader.tryConsume(GlslLexer.TokenType.RIGHT_PAREN)) { - return new GlslFunctionHeaderNode(name, fullySpecifiedType, Collections.singletonList(parameterDeclaration)); + return new GlslFunctionHeader(name, fullySpecifiedType, Collections.singletonList(parameterDeclaration)); } } reader.setCursor(cursor); @@ -890,6 +893,7 @@ private static List parseParameterList(GlslTokenReader break; } + parameters.add(parameterDeclaration); cursor = reader.getCursor(); if (!reader.tryConsume(GlslLexer.TokenType.COMMA)) { break; @@ -899,7 +903,7 @@ private static List parseParameterList(GlslTokenReader return parameters; } - private static @Nullable GlslFunctionHeaderNode parseFunctionHeaderWithParameters(GlslTokenReader reader) { + private static @Nullable GlslFunctionHeader parseFunctionHeaderWithParameters(GlslTokenReader reader) { // fully_specified_type IDENTIFIER LEFT_PAREN parameter_declaration // function_header_with_parameters COMMA parameter_declaration @@ -908,8 +912,8 @@ private static List parseParameterList(GlslTokenReader if (fullySpecifiedType != null && reader.tryConsume(GlslLexer.TokenType.IDENTIFIER, GlslLexer.TokenType.LEFT_PAREN)) { String name = reader.peek(-2).value(); List parameters = parseParameterList(reader); - if (reader.tryConsume(GlslLexer.TokenType.LEFT_PAREN)) { - return new GlslFunctionHeaderNode(name, fullySpecifiedType, parameters); + if (reader.tryConsume(GlslLexer.TokenType.RIGHT_PAREN)) { + return new GlslFunctionHeader(name, fullySpecifiedType, parameters); } } @@ -1262,7 +1266,7 @@ private static List parseParameterList(GlslTokenReader } private static @Nullable GlslSpecifiedType parseArraySpecifier(GlslTokenReader reader, GlslSpecifiedType type) { - GlslTypeSpecifier arraySpecifier = parseArraySpecifier(reader, type.getType()); + GlslTypeSpecifier arraySpecifier = parseArraySpecifier(reader, type.getSpecifier()); if (arraySpecifier != null) { return new GlslSpecifiedType(arraySpecifier, type.getQualifiers()); } @@ -1730,13 +1734,13 @@ private static GlslNode parseConditionopt(GlslTokenReader reader) { if (reader.tryConsume(GlslLexer.TokenType.RETURN)) { // RETURN SEMICOLON if (reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { - return new ReturnNode(null); + return new GlslReturnNode(null); } // RETURN condition SEMICOLON GlslNode condition = parseCondition(reader); if (condition != null && reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { - return new ReturnNode(condition); + return new GlslReturnNode(condition); } } reader.setCursor(cursor); @@ -1752,7 +1756,7 @@ private static GlslNode parseConditionopt(GlslTokenReader reader) { private static @Nullable GlslFunctionNode parseFunctionDefinition(GlslTokenReader reader) { int cursor = reader.getCursor(); - GlslFunctionHeaderNode functionPrototype = parseFunctionPrototype(reader); + GlslFunctionHeader functionPrototype = parseFunctionPrototype(reader); if (functionPrototype == null) { return null; } diff --git a/common/src/main/java/foundry/veil/impl/glsl/GlslTokenReader.java b/common/src/main/java/foundry/veil/impl/glsl/GlslTokenReader.java index fe8c2175..738307c2 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/GlslTokenReader.java +++ b/common/src/main/java/foundry/veil/impl/glsl/GlslTokenReader.java @@ -2,13 +2,22 @@ import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + public class GlslTokenReader { private final GlslLexer.Token[] tokens; private int cursor; + private final List errors; + private final List errorsView; public GlslTokenReader(GlslLexer.Token[] tokens) { this.tokens = tokens; + this.cursor = 0; + this.errors = new ArrayList<>(); + this.errorsView = Collections.unmodifiableList(this.errors); } private int getCursorOffset() { @@ -85,6 +94,17 @@ public void skip(int amount) { this.cursor += amount; } + public void markError(String message) { + this.errors.add(new Error(this.cursor, message)); + } + + /** + * @return All errors marked from reading tokens + */ + public List getErrors() { + return this.errorsView; + } + public int getCursor() { return this.cursor; } @@ -97,4 +117,7 @@ public void setCursor(int cursor) { public String toString() { return "GlslTokenReader{cursor=" + this.cursor + ", token=" + this.peek() + "}"; } + + public record Error(int position, String message) { + } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslFunctionHeader.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslFunctionHeader.java new file mode 100644 index 00000000..6eeef966 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslFunctionHeader.java @@ -0,0 +1,62 @@ +package foundry.veil.impl.glsl.grammar; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +public class GlslFunctionHeader { + + private String name; + private GlslSpecifiedType returnType; + private final List parameters; + + public GlslFunctionHeader(String name, GlslType returnType, Collection parameters) { + this.name = name; + this.returnType = returnType.asSpecifiedType(); + this.parameters = new ArrayList<>(parameters); + } + + public GlslFunctionHeader withParameters(GlslParameterDeclaration... parameters) { + return new GlslFunctionHeader(this.name, this.returnType, new ArrayList<>(Arrays.asList(parameters))); + } + + public String getName() { + return this.name; + } + + public GlslSpecifiedType getReturnType() { + return this.returnType; + } + + public List getParameters() { + return this.parameters; + } + + public GlslFunctionHeader setName(String name) { + this.name = name; + return this; + } + + public GlslFunctionHeader setReturnType(GlslType returnType) { + this.returnType = returnType.asSpecifiedType(); + return this; + } + + @Override + public String toString() { + return "GlslFunctionHeader{name='" + this.name + "', returnType=" + this.returnType + ", parameters=" + this.parameters + '}'; + } + + public String getSourceString() { + return this.returnType.getSourceString() + ' ' + this.name + '(' + + this.parameters.stream().map(parameter -> { + String name = parameter.getName(); + if (name != null) { + return parameter.getType().getSourceString() + " " + name; + } + return parameter.getType().getSourceString(); + }).collect(Collectors.joining(", ")) + ')'; + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslParameterDeclaration.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslParameterDeclaration.java index 90178143..a376fe4a 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslParameterDeclaration.java +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslParameterDeclaration.java @@ -5,7 +5,7 @@ import java.util.Collection; /** - * Represents a single parameter declaration. Includes the name and full data type of the parameter. + * Represents a single parameter declaration. Includes the name and full data operand of the parameter. * * @author Ocelot */ @@ -27,7 +27,7 @@ public GlslParameterDeclaration(@Nullable String name, GlslType type) { } /** - * @return The parameter data type + * @return The parameter data operand */ public GlslSpecifiedType getType() { return this.type; @@ -44,9 +44,9 @@ public GlslParameterDeclaration setName(@Nullable String name) { } /** - * Sets the data type of this parameter. + * Sets the data operand of this parameter. * - * @param type The new type + * @param type The new operand */ public GlslParameterDeclaration setType(GlslType type) { this.type = type.asSpecifiedType(); @@ -54,7 +54,7 @@ public GlslParameterDeclaration setType(GlslType type) { } /** - * Sets The qualifiers of this parameter type. + * Sets The qualifiers of this parameter operand. * * @param qualifiers The new qualifiers */ @@ -64,7 +64,7 @@ public GlslParameterDeclaration setQualifiers(GlslTypeQualifier... qualifiers) { } /** - * Sets The qualifiers of this parameter type. + * Sets The qualifiers of this parameter operand. * * @param qualifiers The new qualifiers */ @@ -75,6 +75,6 @@ public GlslParameterDeclaration setQualifiers(Collection qual @Override public String toString() { - return "GlslParameterDeclaration{name='" + this.name + "', type=" + this.type + '}'; + return "GlslParameterDeclaration{name='" + this.name + "', operand=" + this.type + '}'; } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslSpecifiedType.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslSpecifiedType.java index ca7dabab..a4d26e7f 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslSpecifiedType.java +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslSpecifiedType.java @@ -10,29 +10,29 @@ */ public class GlslSpecifiedType implements GlslType { - private GlslTypeSpecifier type; + private GlslTypeSpecifier specifier; private final List qualifiers; - public GlslSpecifiedType(GlslTypeSpecifier type) { - this.type = type; + public GlslSpecifiedType(GlslTypeSpecifier specifier) { + this.specifier = specifier; this.qualifiers = new ArrayList<>(); } - public GlslSpecifiedType(GlslTypeSpecifier type, Collection qualifiers) { - this(type); + public GlslSpecifiedType(GlslTypeSpecifier specifier, Collection qualifiers) { + this(specifier); this.qualifiers.addAll(qualifiers); } - public GlslSpecifiedType(GlslTypeSpecifier type, GlslTypeQualifier... qualifiers) { - this(type); + public GlslSpecifiedType(GlslTypeSpecifier specifier, GlslTypeQualifier... qualifiers) { + this(specifier); this.qualifiers.addAll(Arrays.asList(qualifiers)); } /** * @return The operand of the field, method, etc */ - public GlslTypeSpecifier getType() { - return this.type; + public GlslTypeSpecifier getSpecifier() { + return this.specifier; } /** @@ -43,12 +43,12 @@ public List getQualifiers() { } /** - * Sets the type of this - * @param type + * Sets the operand of this + * @param specifier * @return */ - public GlslSpecifiedType setType(GlslTypeSpecifier type) { - this.type = type; + public GlslSpecifiedType setSpecifier(GlslTypeSpecifier specifier) { + this.specifier = specifier; return this; } @@ -64,9 +64,18 @@ public GlslSpecifiedType setQualifiers(Collection qualifiers) return this; } + public String getSourceString() { + StringBuilder builder = new StringBuilder(); + for (GlslTypeQualifier qualifier : this.qualifiers) { + builder.append(qualifier.getSourceString()).append(" "); + } + builder.append(this.specifier.getSourceString()); + return builder.toString(); + } + @Override public String toString() { - return "GlslSpecifiedType[specifier=" + this.type + ", qualifiers=" + this.qualifiers; + return "GlslSpecifiedType[specifier=" + this.specifier + ", qualifiers=" + this.qualifiers; } @Override diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructSpecifier.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructSpecifier.java index 842e7e7e..6e63e627 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructSpecifier.java +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructSpecifier.java @@ -2,4 +2,9 @@ // TODO public record GlslStructSpecifier() implements GlslTypeSpecifier { + + @Override + public String getSourceString() { + return "TODO STRUCT"; + } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeQualifier.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeQualifier.java index bf0994ea..25e85979 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeQualifier.java +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeQualifier.java @@ -4,8 +4,11 @@ import org.jetbrains.annotations.Nullable; import java.util.Arrays; +import java.util.Locale; -public interface GlslTypeQualifier { +public sealed interface GlslTypeQualifier { + + String getSourceString(); static GlslTypeQualifier storage(Storage.StorageType storageType) { if (storageType == StorageType.SUBROUTINE) { @@ -40,14 +43,41 @@ static LayoutId sharedLayoutId() { record Storage(StorageType storageType, @Nullable String[] typeNames) implements GlslTypeQualifier { @Override public String toString() { - return this.storageType == StorageType.SUBROUTINE ? "Storage[type=SUBROUTINE, typeNames=" + Arrays.toString(this.typeNames) + "]" : "Storage[type=" + this.storageType + ']'; + return this.storageType == StorageType.SUBROUTINE ? "Storage[operand=SUBROUTINE, typeNames=" + Arrays.toString(this.typeNames) + "]" : "Storage[operand=" + this.storageType + ']'; + } + + @Override + public String getSourceString() { + if (this.typeNames != null && this.typeNames.length > 0) { + return "subroutine(" + String.join(",", this.typeNames) + ")"; + } + + return this.storageType.name().toLowerCase(Locale.ROOT); } } - record Layout(LayoutId[] qualifierIds) implements GlslTypeQualifier { + record Layout(LayoutId[] layoutIds) implements GlslTypeQualifier { + @Override + public String getSourceString() { + StringBuilder builder = new StringBuilder(); + for (GlslTypeQualifier.LayoutId layoutId : this.layoutIds) { + if (layoutId.shared()) { + builder.append("shared "); + } else { + builder.append(layoutId.identifier()); + GlslNode expression = layoutId.expression(); + if (expression != null) { + builder.append('=').append(expression.getSourceString()); + } + builder.append(" "); + } + } + builder.deleteCharAt(builder.length() - 1); + return "layout(" + builder + ")"; + } } - record LayoutId(String identifier, @Nullable GlslNode constantExpression) { + record LayoutId(String identifier, @Nullable GlslNode expression) { public boolean shared() { return "shared".equals(this.identifier); @@ -74,22 +104,48 @@ enum StorageType { } enum Precision implements GlslTypeQualifier { - HIGH_PRECISION, - MEDIUM_PRECISION, - LOW_PRECISION + HIGH_PRECISION("highp"), + MEDIUM_PRECISION("mediump"), + LOW_PRECISION("lowp"); + + private final String sourceName; + + Precision(String sourceName) { + this.sourceName = sourceName; + } + + @Override + public String getSourceString() { + return this.sourceName; + } } enum Interpolation implements GlslTypeQualifier { SMOOTH, FLAT, - NOPERSPECTIVE + NOPERSPECTIVE; + + @Override + public String getSourceString() { + return this.name().toLowerCase(Locale.ROOT); + } } enum Invariant implements GlslTypeQualifier { - INVARIANT + INVARIANT; + + @Override + public String getSourceString() { + return this.name().toLowerCase(Locale.ROOT); + } } enum Precise implements GlslTypeQualifier { - PRECISE + PRECISE; + + @Override + public String getSourceString() { + return this.name().toLowerCase(Locale.ROOT); + } } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeSpecifier.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeSpecifier.java index a8d82579..85ebd09a 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeSpecifier.java +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeSpecifier.java @@ -3,7 +3,11 @@ import foundry.veil.impl.glsl.node.GlslNode; import org.jetbrains.annotations.Nullable; -public interface GlslTypeSpecifier extends GlslType { +import java.util.Locale; + +public sealed interface GlslTypeSpecifier extends GlslType permits GlslStructSpecifier, GlslTypeSpecifier.Array, GlslTypeSpecifier.BuiltinType, GlslTypeSpecifier.Name { + + String getSourceString(); default boolean isNamed() { return this instanceof Name; @@ -23,9 +27,18 @@ default GlslSpecifiedType asSpecifiedType() { } record Name(String name) implements GlslTypeSpecifier { + @Override + public String getSourceString() { + return this.name; + } } record Array(GlslTypeSpecifier specifier, @Nullable GlslNode size) implements GlslTypeSpecifier { + @Override + public String getSourceString() { + return this.specifier.getSourceString() + (this.size != null ? "[" + this.size.getSourceString() + "]" : "[]"); + } + @Override public boolean isNamed() { return this.specifier.isNamed(); @@ -151,6 +164,11 @@ enum BuiltinType implements GlslTypeSpecifier { UIMAGE2DMS, IMAGE2DMSARRAY, IIMAGE2DMSARRAY, - UIMAGE2DMSARRAY + UIMAGE2DMSARRAY; + + @Override + public String getSourceString() { + return this.name().toLowerCase(Locale.ROOT); + } } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslVersion.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslVersion.java index b35a077c..4fa5bdc0 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslVersion.java +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslVersion.java @@ -1,12 +1,76 @@ package foundry.veil.impl.glsl.grammar; -public record GlslVersion(int version, boolean core) { +/** + * Represents the version statement for a GLSL shader source. + * + * @author Ocelot + */ +public class GlslVersion { - public GlslVersion withVersion(int version) { - return new GlslVersion(version, this.core); + private int version; + private boolean core; + + public GlslVersion(int version, boolean core) { + this.version = version; + this.core = core; + } + + /** + * @return The GLSL version number + */ + public int getVersion() { + return this.version; + } + + /** + * @return Whether to use the core or compatibility profile + */ + public boolean isCore() { + return this.core; + } + + public String getVersionStatement() { + return this.version + (this.core ? " core" : ""); + } + + /** + * Sets the GLSL version integer. + * + * @param version The new version + */ + public void setVersion(int version) { + this.version = version; + } + + /** + * Sets whether to use the core or compatibility profile. + * + * @param core Whether to use "core" + */ + public void setCore(boolean core) { + this.core = core; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + GlslVersion that = (GlslVersion) o; + return version == that.version && core == that.core; + } + + @Override + public int hashCode() { + return 31 * this.version + Boolean.hashCode(this.core); } - public GlslVersion withCore(boolean core) { - return new GlslVersion(this.version, core); + @Override + public String toString() { + return "GlslVersion{" + this.getVersionStatement() + '}'; } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslCompoundNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslCompoundNode.java index 3abf8a02..c31d639c 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/GlslCompoundNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslCompoundNode.java @@ -1,13 +1,60 @@ package foundry.veil.impl.glsl.node; -import foundry.veil.impl.glsl.visitor.GlslVisitor; +import foundry.veil.impl.glsl.visitor.GlslNodeVisitor; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.List; -public record GlslCompoundNode(List children) implements GlslNode { +public class GlslCompoundNode implements GlslNode { + + private final List children; + + public GlslCompoundNode(List children) { + this.children = children; + } @Override - public void visit(GlslVisitor visitor) { + public List toList() { + return new ArrayList<>(this.children); + } + + @Override + public void visit(GlslNodeVisitor visitor) { + for (GlslNode child : this.children) { + child.visit(visitor); + } + } + + public List getChildren() { + return this.children; + } + public GlslCompoundNode setChildren(Collection children) { + this.children.clear(); + this.children.addAll(children); + return this; + } + + public GlslCompoundNode setChildren(GlslNode... children) { + this.children.clear(); + this.children.addAll(Arrays.asList(children)); + return this; + } + + @Override + public String getSourceString() { + StringBuilder builder = new StringBuilder(); + for (GlslNode child : this.children) { + builder.append(child.getSourceString()).append('\n'); + } + builder.deleteCharAt(builder.length() - 1); + return builder.toString(); + } + + @Override + public String toString() { + return "GlslCompoundNode{children=" + this.children + '}'; } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslConstantNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslConstantNode.java index ac5ce723..23e4a35d 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/GlslConstantNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslConstantNode.java @@ -2,5 +2,25 @@ public interface GlslConstantNode extends GlslNode { - Object rawValue(); + Number numberValue(); + + default double doubleValue() { + return this.numberValue().doubleValue(); + } + + default float floatValue() { + return this.numberValue().floatValue(); + } + + default int intValue() { + return this.numberValue().intValue(); + } + + default long unsignedIntValue() { + return Integer.toUnsignedLong(this.numberValue().intValue()); + } + + boolean booleanValue(); + + boolean isNumber(); } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslEmptyNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslEmptyNode.java index 8fa4b035..13f455e0 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/GlslEmptyNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslEmptyNode.java @@ -1,11 +1,24 @@ package foundry.veil.impl.glsl.node; -import foundry.veil.impl.glsl.visitor.GlslVisitor; +import foundry.veil.impl.glsl.visitor.GlslNodeVisitor; + +import java.util.ArrayList; +import java.util.List; public enum GlslEmptyNode implements GlslNode { INSTANCE; @Override - public void visit(GlslVisitor visitor) { + public String getSourceString() { + return ""; + } + + @Override + public List toList() { + return new ArrayList<>(); + } + + @Override + public void visit(GlslNodeVisitor visitor) { } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslNode.java index ccbc5c4e..956ed8a4 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/GlslNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslNode.java @@ -1,18 +1,28 @@ package foundry.veil.impl.glsl.node; -import foundry.veil.impl.glsl.visitor.GlslVisitor; +import foundry.veil.impl.glsl.visitor.GlslNodeVisitor; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; +import java.util.*; public interface GlslNode { - void visit(GlslVisitor visitor); + String getSourceString(); - default Collection children() { - return Collections.emptySet(); + default void visit(GlslNodeVisitor visitor) { + visitor.visitNode(this); + } + + /** + * @return A new list with the child contents of this node + */ + default List toList() { + return new ArrayList<>(Collections.singleton(this)); + } + + static void visitAll(Collection nodes, GlslNodeVisitor visitor) { + for (GlslNode node : nodes) { + node.visit(visitor); + } } static GlslNode compound(Collection nodes) { @@ -22,7 +32,16 @@ static GlslNode compound(Collection nodes) { if (nodes.size() == 1) { return nodes.iterator().next(); } - return new GlslCompoundNode(new ArrayList<>(nodes)); + List list = new ArrayList<>(); + for (GlslNode node : nodes) { + if (!(node instanceof GlslCompoundNode compoundNode)) { + list.clear(); + list.addAll(nodes); + break; + } + list.addAll(compoundNode.getChildren()); + } + return new GlslCompoundNode(list); } static GlslNode compound(GlslNode... nodes) { diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java index 7aaaa5e3..4596775d 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java @@ -1,7 +1,10 @@ package foundry.veil.impl.glsl.node; import foundry.veil.impl.glsl.grammar.GlslVersion; -import foundry.veil.impl.glsl.visitor.GlslVisitor; +import foundry.veil.impl.glsl.node.function.GlslFunctionNode; +import foundry.veil.impl.glsl.node.variable.GlslNewNode; +import foundry.veil.impl.glsl.visitor.GlslFunctionVisitor; +import foundry.veil.impl.glsl.visitor.GlslTreeVisitor; import java.util.ArrayList; import java.util.Collection; @@ -9,7 +12,7 @@ public class GlslTree { - private GlslVersion version; + private final GlslVersion version; private final List body; public GlslTree(GlslVersion version, Collection body) { @@ -17,10 +20,23 @@ public GlslTree(GlslVersion version, Collection body) { this.body = new ArrayList<>(body); } - public void visit(GlslVisitor visitor) { - for (GlslNode node : this.body) { - node.visit(visitor); - } + public void visit(GlslTreeVisitor visitor) { + visitor.visitVersion(this.version); + GlslNode.visitAll(this.body, node -> { + if (node instanceof GlslFunctionNode functionNode) { + GlslFunctionVisitor functionVisitor = visitor.visitFunction(functionNode); + if (functionVisitor != null) { + functionNode.visit(functionVisitor); + } + return; + } + if(node instanceof GlslNewNode newNode) { + visitor.visitField(newNode); + return; + } + System.out.println(node); + }); + visitor.visitTreeEnd(); } public GlslVersion getVersion() { @@ -31,10 +47,6 @@ public List getBody() { return this.body; } - public void setVersion(GlslVersion version) { - this.version = version; - } - @Override public String toString() { return "GlslTree{version=" + this.version + ", body=" + this.body + '}'; diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/ForLoopNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/ForLoopNode.java index 91a52c91..4e123e6e 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/branch/ForLoopNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/ForLoopNode.java @@ -1,7 +1,7 @@ package foundry.veil.impl.glsl.node.branch; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; +import foundry.veil.impl.glsl.visitor.GlslTreeVisitor; import org.jetbrains.annotations.Nullable; /** @@ -23,10 +23,6 @@ public ForLoopNode(GlslNode init, GlslNode condition, @Nullable GlslNode increme this.body = body; } - @Override - public void visit(GlslVisitor visitor) { - } - public GlslNode getInit() { return this.init; } @@ -63,4 +59,16 @@ public void setBody(GlslNode body) { public String toString() { return "ForLoopNode{init=" + this.init + ", condition=" + this.condition + ", increment=" + this.increment + ", body=" + this.body + '}'; } + + @Override + public String getSourceString() { + StringBuilder builder = new StringBuilder(); + builder.append("for (").append(this.init.getSourceString()).append("; ").append(this.condition).append(';'); + if (this.increment != null) { + builder.append(this.increment.getSourceString()); + } + builder.append(") {\n").append(this.body.getSourceString().replaceAll("\n", "\n\t")); + builder.append('}'); + return builder.toString(); + } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslCaseLabelNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslCaseLabelNode.java index c0c3e16f..7a7941c7 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslCaseLabelNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslCaseLabelNode.java @@ -1,7 +1,7 @@ package foundry.veil.impl.glsl.node.branch; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; +import foundry.veil.impl.glsl.visitor.GlslTreeVisitor; import org.jetbrains.annotations.Nullable; public class GlslCaseLabelNode implements GlslNode { @@ -12,11 +12,6 @@ public GlslCaseLabelNode(@Nullable GlslNode condition) { this.condition = condition; } - @Override - public void visit(GlslVisitor visitor) { - visitor.visitCaseLabel(this); - } - public boolean isDefault() { return this.condition == null; } @@ -33,4 +28,9 @@ public void setCondition(@Nullable GlslNode condition) { public String toString() { return "GlslCaseLabelNode{condition=" + (this.condition == null ? "default" : this.condition) + '}'; } + + @Override + public String getSourceString() { + return "case: " + this.condition.getSourceString(); + } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/ReturnNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslReturnNode.java similarity index 68% rename from common/src/main/java/foundry/veil/impl/glsl/node/branch/ReturnNode.java rename to common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslReturnNode.java index 54152e62..243f2ab9 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/branch/ReturnNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslReturnNode.java @@ -1,22 +1,16 @@ package foundry.veil.impl.glsl.node.branch; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; import org.jetbrains.annotations.Nullable; -public class ReturnNode implements GlslNode { +public class GlslReturnNode implements GlslNode { private GlslNode value; - public ReturnNode(@Nullable GlslNode value) { + public GlslReturnNode(@Nullable GlslNode value) { this.value = value; } - @Override - public void visit(GlslVisitor visitor) { - - } - public @Nullable GlslNode getValue() { return this.value; } @@ -29,4 +23,9 @@ public void setValue(@Nullable GlslNode value) { public String toString() { return "ReturnNode{value=" + this.value + '}'; } + + @Override + public String getSourceString() { + return this.value != null ? "return " + this.value.getSourceString() : "return"; + } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSelectionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSelectionNode.java index 44a295af..c0652174 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSelectionNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSelectionNode.java @@ -1,7 +1,6 @@ package foundry.veil.impl.glsl.node.branch; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; import org.jetbrains.annotations.Nullable; /** @@ -15,7 +14,14 @@ public record GlslSelectionNode(GlslNode expression, GlslNode first, @Nullable GlslNode branch) implements GlslNode { @Override - public void visit(GlslVisitor visitor) { - + public String getSourceString() { + StringBuilder builder = new StringBuilder("if ("); + builder.append(this.expression.getSourceString().replaceAll("\n", "\n\t")).append(") {\n"); + builder.append(this.first.getSourceString()).append("\n}"); + if (this.branch != null) { + builder.append(" else {\n"); + builder.append(this.branch.getSourceString().replaceAll("\n", "\n\t")).append("\n}"); + } + return builder.toString(); } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSwitchNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSwitchNode.java index bb12fd3f..c217799f 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSwitchNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSwitchNode.java @@ -1,21 +1,88 @@ package foundry.veil.impl.glsl.node.branch; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.List; /** * Switch statement. * - * @param condition The condition inside the switch switch(condition) {} - * @param branches All code inside the switch, including all labels and code under those labels * @author Ocelot */ -public record GlslSwitchNode(GlslNode condition, List branches) implements GlslNode { +public class GlslSwitchNode implements GlslNode { + + private GlslNode condition; + private final List branches; + + public GlslSwitchNode(GlslNode condition, Collection branches) { + this.condition = condition; + this.branches = new ArrayList<>(branches); + } + + /** + * @return The condition inside the switch switch(condition) {} + */ + public GlslNode getCondition() { + return condition; + } + + /** + * @return All code inside the switch, including all labels and code under those labels + */ + public List getBranches() { + return this.branches; + } + + /** + * Sets the input condition for this switch statement. + * + * @param condition The new condition to use + */ + public GlslSwitchNode setCondition(GlslNode condition) { + this.condition = condition; + return this; + } + + /** + * Replaces all branches with the specified values. + * + * @param branches The new branches + */ + public GlslSwitchNode setBranches(Collection branches) { + this.branches.clear(); + this.branches.addAll(branches); + return this; + } + + /** + * Replaces all branches with the specified values. + * + * @param branches The new branches + */ + public GlslSwitchNode setBranches(GlslNode... branches) { + this.branches.clear(); + this.branches.addAll(Arrays.asList(branches)); + return this; + } @Override - public void visit(GlslVisitor visitor) { + public String toString() { + return "GlslSwitchNode{" + + "condition=" + this.condition + ", " + + "branches=" + this.branches + '}'; + } + @Override + public String getSourceString() { + StringBuilder builder = new StringBuilder("switch("); + builder.append(this.condition.getSourceString()).append(") {"); + for (GlslNode branch : this.branches) { + builder.append('\t').append(branch.getSourceString()).append('\n'); + } + builder.append('}'); + return builder.toString(); } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/JumpNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/JumpNode.java index 0fec3a0d..a3724fe3 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/branch/JumpNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/JumpNode.java @@ -1,14 +1,15 @@ package foundry.veil.impl.glsl.node.branch; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; + +import java.util.Locale; public enum JumpNode implements GlslNode { CONTINUE, BREAK, DISCARD; @Override - public void visit(GlslVisitor visitor) { - + public String getSourceString() { + return this.name().toLowerCase(Locale.ROOT); } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/WhileLoopNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/WhileLoopNode.java index 1cbcd122..abcb99ba 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/branch/WhileLoopNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/WhileLoopNode.java @@ -1,7 +1,6 @@ package foundry.veil.impl.glsl.node.branch; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; /** * Represents both while and do/while loops. @@ -20,10 +19,6 @@ public WhileLoopNode(GlslNode condition, GlslNode body, Type type) { this.type = type; } - @Override - public void visit(GlslVisitor visitor) { - } - public GlslNode getCondition() { return this.condition; } @@ -36,16 +31,24 @@ public Type getType() { return this.type; } - public void setCondition(GlslNode condition) { + public WhileLoopNode setCondition(GlslNode condition) { this.condition = condition; + return this; } - public void setBody(GlslNode body) { + public WhileLoopNode setBody(GlslNode body) { this.body = body; + return this; } - public void setType(Type type) { + public WhileLoopNode setType(Type type) { this.type = type; + return this; + } + + @Override + public String getSourceString() { + return "while (" + this.condition.getSourceString() + ") {\n" + this.body.getSourceString().replaceAll("\n", "\n\t") + "\n}"; } public enum Type { diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAndNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAndNode.java index d8f92d03..a0a94a24 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAndNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAndNode.java @@ -1,20 +1,48 @@ package foundry.veil.impl.glsl.node.expression; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; +import java.util.Arrays; +import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; /** * AND; A & B & C * - * @param expressions * @author Ocelot */ -public record GlslAndNode(List expressions) implements GlslNode { +public class GlslAndNode implements GlslNode { + + private final List expressions; + + public GlslAndNode(List expressions) { + this.expressions = expressions; + } + + public List getExpressions() { + return this.expressions; + } + + public GlslAndNode setExpressions(Collection expressions) { + this.expressions.clear(); + this.expressions.addAll(expressions); + return this; + } + + public GlslAndNode setExpressions(GlslNode... expressions) { + this.expressions.clear(); + this.expressions.addAll(Arrays.asList(expressions)); + return this; + } @Override - public void visit(GlslVisitor visitor) { + public String getSourceString() { + return this.expressions.stream().map(GlslNode::getSourceString).collect(Collectors.joining(" & ")); + } + @Override + public String toString() { + return "GlslAndNode[expressions=" + this.expressions + ']'; } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAssignmentNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAssignmentNode.java index aa0f91d5..2ac9ec00 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAssignmentNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAssignmentNode.java @@ -1,7 +1,8 @@ package foundry.veil.impl.glsl.node.expression; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; + +import java.util.Objects; /** * Equal; A = B @@ -26,28 +27,95 @@ *
* Or Assign; A |= B * - * @param left The left operand - * @param right The right operand - * @param operand The operand to perform when setting the left to the right * @author Ocelot */ -public record GlslAssignmentNode(GlslNode left, GlslNode right, Operand operand) implements GlslNode { +public class GlslAssignmentNode implements GlslNode { + + private GlslNode first; + private GlslNode second; + private Operand operand; + + /** + * @param first The first operand + * @param second The second operand + * @param operand The operand to perform when setting the first to the second + */ + public GlslAssignmentNode(GlslNode first, GlslNode second, Operand operand) { + this.first = first; + this.second = second; + this.operand = operand; + } + + /** + * @return The first operand + */ + public GlslNode getFirst() { + return this.first; + } + + /** + * @return The second operand + */ + public GlslNode getSecond() { + return this.second; + } + + /** + * @return The operand to perform when setting the first to the second + */ + public Operand getOperand() { + return this.operand; + } + + public GlslAssignmentNode setFirst(GlslNode first) { + this.first = first; + return this; + } + + public GlslAssignmentNode setSecond(GlslNode second) { + this.second = second; + return this; + } + + public GlslAssignmentNode setOperand(Operand operand) { + this.operand = operand; + return this; + } @Override - public void visit(GlslVisitor visitor) { + public String getSourceString() { + return this.first.getSourceString() + ' ' + this.operand.getDelimiter() + ' ' + this.second.getSourceString(); + } + + @Override + public String toString() { + return "GlslAssignmentNode{" + + "first=" + this.first + ", " + + "second=" + this.second + ", " + + "operand=" + this.operand + ']'; } public enum Operand { - EQUAL, - MUL_ASSIGN, - DIV_ASSIGN, - MOD_ASSIGN, - ADD_ASSIGN, - SUB_ASSIGN, - LEFT_ASSIGN, - RIGHT_ASSIGN, - AND_ASSIGN, - XOR_ASSIGN, - OR_ASSIGN + EQUAL("="), + MUL_ASSIGN("*/"), + DIV_ASSIGN("/="), + MOD_ASSIGN("%="), + ADD_ASSIGN("+="), + SUB_ASSIGN("-="), + LEFT_ASSIGN("<<="), + RIGHT_ASSIGN(">>="), + AND_ASSIGN("&="), + XOR_ASSIGN("^="), + OR_ASSIGN("|="); + + private final String delimiter; + + Operand(String delimiter) { + this.delimiter = delimiter; + } + + public String getDelimiter() { + return this.delimiter; + } } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslCompareNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslCompareNode.java index d5ba41bf..24b537ee 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslCompareNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslCompareNode.java @@ -1,26 +1,93 @@ package foundry.veil.impl.glsl.node.expression; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; + +import java.util.Objects; /** * Equality; A == B, A != B *
* Relational; A < B, A > B, A <= B, A >= B * - * @param first The left operand - * @param second The right operand - * @param type The operand of relationship the expressions have * @author Ocelot */ -public record GlslCompareNode(GlslNode first, GlslNode second, Type type) implements GlslNode { +public class GlslCompareNode implements GlslNode { + + private GlslNode first; + private GlslNode second; + private Operand operand; + + public GlslCompareNode(GlslNode first, GlslNode second, Operand operand) { + this.first = first; + this.second = second; + this.operand = operand; + } @Override - public void visit(GlslVisitor visitor) { + public String getSourceString() { + return this.first.getSourceString() + ' ' + this.operand.getDelimiter() + ' ' + this.second.getSourceString(); + } + + /** + * @return The first operand + */ + public GlslNode getFirst() { + return this.first; + } + + /** + * @return The second operand + */ + public GlslNode getSecond() { + return this.second; + } + + /** + * @return The operand of relationship the expressions have + */ + public Operand getOperand() { + return this.operand; + } + public GlslCompareNode setFirst(GlslNode first) { + this.first = first; + return this; } - public enum Type { - EQUAL, NOT_EQUAL, LESS, GREATER, LEQUAL, GEQUAL + public GlslCompareNode setSecond(GlslNode second) { + this.second = second; + return this; + } + + public GlslCompareNode setOperand(Operand operand) { + this.operand = operand; + return this; + } + + @Override + public String toString() { + return "GlslCompareNode{" + + "first=" + this.first + ", " + + "second=" + this.second + ", " + + "operand=" + this.operand + '}'; + } + + public enum Operand { + EQUAL("=="), + NOT_EQUAL("!="), + LESS("<"), + GREATER(">"), + LEQUAL("<="), + GEQUAL(">="); + + private final String delimiter; + + Operand(String delimiter) { + this.delimiter = delimiter; + } + + public String getDelimiter() { + return this.delimiter; + } } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslConditionalNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslConditionalNode.java index 0e8d4f9e..cab0cf32 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslConditionalNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslConditionalNode.java @@ -1,21 +1,61 @@ package foundry.veil.impl.glsl.node.expression; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; -import org.jetbrains.annotations.Nullable; /** * ?: * - * @param condition - * @param first - * @param branch * @author Ocelot */ -public record GlslConditionalNode(GlslNode condition, GlslNode first, @Nullable GlslNode branch) implements GlslNode { +public class GlslConditionalNode implements GlslNode { + + private GlslNode condition; + private GlslNode first; + private GlslNode second; + + public GlslConditionalNode(GlslNode condition, GlslNode first, GlslNode second) { + this.condition = condition; + this.first = first; + this.second = second; + } + + public GlslNode getCondition() { + return this.condition; + } + + public GlslNode getFirst() { + return this.first; + } + + public GlslNode getSecond() { + return this.second; + } + + public GlslConditionalNode setCondition(GlslNode condition) { + this.condition = condition; + return this; + } + + public GlslConditionalNode setFirst(GlslNode first) { + this.first = first; + return this; + } + + public GlslConditionalNode setSecond(GlslNode second) { + this.second = second; + return this; + } @Override - public void visit(GlslVisitor visitor) { + public String getSourceString() { + return this.condition.getSourceString() + " " + this.first.getSourceString() + " : " + this.second.getSourceString(); + } + @Override + public String toString() { + return "GlslConditionalNode{" + + "condition=" + this.condition + ", " + + "first=" + this.first + ", " + + "second=" + this.second + '}'; } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslExclusiveOrNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslExclusiveOrNode.java index ae5bd4f1..85cc41bf 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslExclusiveOrNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslExclusiveOrNode.java @@ -1,9 +1,10 @@ package foundry.veil.impl.glsl.node.expression; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; +import foundry.veil.impl.glsl.visitor.GlslTreeVisitor; import java.util.List; +import java.util.stream.Collectors; /** * Exclusive OR; A ^ B ^ C @@ -14,7 +15,7 @@ public record GlslExclusiveOrNode(List expressions) implements GlslNode { @Override - public void visit(GlslVisitor visitor) { - + public String getSourceString() { + return this.expressions.stream().map(GlslNode::getSourceString).collect(Collectors.joining(" ^ ")); } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslInclusiveOrNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslInclusiveOrNode.java index 3d6f9e65..cc5b1eeb 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslInclusiveOrNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslInclusiveOrNode.java @@ -1,9 +1,10 @@ package foundry.veil.impl.glsl.node.expression; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; +import foundry.veil.impl.glsl.visitor.GlslTreeVisitor; import java.util.List; +import java.util.stream.Collectors; /** * Inclusive OR; A | B | C @@ -14,7 +15,7 @@ public record GlslInclusiveOrNode(List expressions) implements GlslNode { @Override - public void visit(GlslVisitor visitor) { - + public String getSourceString() { + return this.expressions.stream().map(GlslNode::getSourceString).collect(Collectors.joining(" | ")); } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalAndNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalAndNode.java index fd046379..c6cf2118 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalAndNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalAndNode.java @@ -1,9 +1,10 @@ package foundry.veil.impl.glsl.node.expression; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; +import foundry.veil.impl.glsl.visitor.GlslTreeVisitor; import java.util.List; +import java.util.stream.Collectors; /** * Logical AND; A && B && C @@ -14,7 +15,7 @@ public record GlslLogicalAndNode(List expressions) implements GlslNode { @Override - public void visit(GlslVisitor visitor) { - + public String getSourceString() { + return this.expressions.stream().map(GlslNode::getSourceString).collect(Collectors.joining(" && ")); } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalOrNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalOrNode.java index de7e84ca..97b9c403 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalOrNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalOrNode.java @@ -1,9 +1,10 @@ package foundry.veil.impl.glsl.node.expression; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; +import foundry.veil.impl.glsl.visitor.GlslTreeVisitor; import java.util.List; +import java.util.stream.Collectors; /** * Logical OR; A || B || C @@ -14,7 +15,7 @@ public record GlslLogicalOrNode(List expressions) implements GlslNode { @Override - public void visit(GlslVisitor visitor) { - + public String getSourceString() { + return this.expressions.stream().map(GlslNode::getSourceString).collect(Collectors.joining(" || ")); } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalXorNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalXorNode.java index ae2d4a28..8b5cc61a 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalXorNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalXorNode.java @@ -1,9 +1,10 @@ package foundry.veil.impl.glsl.node.expression; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; +import foundry.veil.impl.glsl.visitor.GlslTreeVisitor; import java.util.List; +import java.util.stream.Collectors; /** * Logical XOR; A ^^ B ^^ C @@ -14,7 +15,7 @@ public record GlslLogicalXorNode(List expressions) implements GlslNode { @Override - public void visit(GlslVisitor visitor) { - + public String getSourceString() { + return this.expressions.stream().map(GlslNode::getSourceString).collect(Collectors.joining(" ^^ ")); } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslOperationNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslOperationNode.java index 8ebc4069..aaa517b2 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslOperationNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslOperationNode.java @@ -1,7 +1,6 @@ package foundry.veil.impl.glsl.node.expression; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; /** * Shift; A << B, A >> B @@ -16,19 +15,83 @@ *
* Modulo; A % B * - * @param first The left operand - * @param second The right operand - * @param operand The operand of relationship the expressions have * @author Ocelot */ -public record GlslOperationNode(GlslNode first, GlslNode second, Operand operand) implements GlslNode { +public final class GlslOperationNode implements GlslNode { + + private GlslNode first; + private GlslNode second; + private Operand operand; + + public GlslOperationNode(GlslNode first, GlslNode second, Operand operand) { + this.first = first; + this.second = second; + this.operand = operand; + } @Override - public void visit(GlslVisitor visitor) { + public String getSourceString() { + return this.first.getSourceString() + " " + this.operand.getDelimiter() + " " + this.second.getSourceString(); + } + + /** + * @return The first operand + */ + public GlslNode getFirst() { + return this.first; + } + + /** + * @return The second operand + */ + public GlslNode getSecond() { + return this.second; + } + + /** + * @return The operand of relationship the expressions have + */ + public Operand getOperand() { + return this.operand; + } + public GlslOperationNode setFirst(GlslNode first) { + this.first = first; + return this; + } + + public GlslOperationNode setSecond(GlslNode second) { + this.second = second; + return this; + } + + public GlslOperationNode setOperand(Operand operand) { + this.operand = operand; + return this; + } + + @Override + public String toString() { + return "GlslOperationNode{first=" + this.first + ", second=" + this.second + ", operand=" + this.operand + '}'; } public enum Operand { - LEFT_SHIFT, RIGHT_SHIFT, ADD, SUBTRACT, MULTIPLY, DIVIDE, MODULO + LEFT_SHIFT("<<"), + RIGHT_SHIFT(">>"), + ADD("+"), + SUBTRACT("-"), + MULTIPLY("*"), + DIVIDE("/"), + MODULO("%"); + + private final String delimiter; + + Operand(String delimiter) { + this.delimiter = delimiter; + } + + public String getDelimiter() { + return this.delimiter; + } } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/PrecisionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslPrecisionNode.java similarity index 57% rename from common/src/main/java/foundry/veil/impl/glsl/node/expression/PrecisionNode.java rename to common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslPrecisionNode.java index 2887a7eb..707ce14d 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/PrecisionNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslPrecisionNode.java @@ -3,23 +3,17 @@ import foundry.veil.impl.glsl.grammar.GlslTypeQualifier; import foundry.veil.impl.glsl.grammar.GlslTypeSpecifier; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; -public class PrecisionNode implements GlslNode { +public class GlslPrecisionNode implements GlslNode { private GlslTypeQualifier.Precision precision; private GlslTypeSpecifier typeSpecifier; - public PrecisionNode(GlslTypeQualifier.Precision precision, GlslTypeSpecifier typeSpecifier) { + public GlslPrecisionNode(GlslTypeQualifier.Precision precision, GlslTypeSpecifier typeSpecifier) { this.precision = precision; this.typeSpecifier = typeSpecifier; } - @Override - public void visit(GlslVisitor visitor) { - - } - public GlslTypeQualifier.Precision getPrecision() { return this.precision; } @@ -28,11 +22,18 @@ public GlslTypeSpecifier getTypeSpecifier() { return this.typeSpecifier; } - public void setPrecision(GlslTypeQualifier.Precision precision) { + public GlslPrecisionNode setPrecision(GlslTypeQualifier.Precision precision) { this.precision = precision; + return this; } - public void setTypeSpecifier(GlslTypeSpecifier typeSpecifier) { + public GlslPrecisionNode setTypeSpecifier(GlslTypeSpecifier typeSpecifier) { this.typeSpecifier = typeSpecifier; + return this; + } + + @Override + public String getSourceString() { + return "precision " + this.precision.getSourceString() + " " + this.typeSpecifier.getSourceString(); } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslUnaryNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslUnaryNode.java index ed83c300..71c7b8f3 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslUnaryNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslUnaryNode.java @@ -1,24 +1,73 @@ package foundry.veil.impl.glsl.node.expression; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; -import java.util.Collection; -import java.util.Collections; +import java.util.Objects; -public record GlslUnaryNode(GlslNode expression, Operand operand) implements GlslNode { +public class GlslUnaryNode implements GlslNode { - @Override - public void visit(GlslVisitor visitor) { + private GlslNode expression; + private Operand operand; + + public GlslUnaryNode(GlslNode expression, Operand operand) { + this.expression = expression; + this.operand = operand; + } + + public GlslNode getExpression() { + return this.expression; + } + + public Operand getOperand() { + return this.operand; + } + public GlslUnaryNode setExpression(GlslNode expression) { + this.expression = expression; + return this; + } + + public GlslUnaryNode setOperand(Operand operand) { + this.operand = operand; + return this; + } + + @Override + public String toString() { + return "GlslUnaryNode{expression=" + this.expression + ", " + "operand=" + this.operand + '}'; } @Override - public Collection children() { - return Collections.singleton(this.expression); + public String getSourceString() { + return switch (this.operand) { + case PRE_INCREMENT, + PRE_DECREMENT, + PLUS, + DASH, + BANG, + TILDE -> this.operand.getDelimiter() + this.expression.getSourceString(); + case POST_INCREMENT, POST_DECREMENT -> this.expression.getSourceString() + this.operand.getDelimiter(); + }; } public enum Operand { - PRE_INCREMENT, PRE_DECREMENT, POST_INCREMENT, POST_DECREMENT, PLUS, DASH, BANG, TILDE + PRE_INCREMENT("++"), + PRE_DECREMENT("--"), + POST_INCREMENT("++"), + POST_DECREMENT("--"), + PLUS("+"), + DASH("-"), + BANG("!"), + TILDE("~"); + + private final String delimiter; + + Operand(String delimiter) { + this.delimiter = delimiter; + } + + public String getDelimiter() { + return this.delimiter; + } } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionHeaderNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionHeaderNode.java deleted file mode 100644 index acca4dde..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionHeaderNode.java +++ /dev/null @@ -1,61 +0,0 @@ -package foundry.veil.impl.glsl.node.function; - -import foundry.veil.impl.glsl.grammar.GlslSpecifiedType; -import foundry.veil.impl.glsl.grammar.GlslType; -import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.grammar.GlslParameterDeclaration; -import foundry.veil.impl.glsl.visitor.GlslVisitor; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -public class GlslFunctionHeaderNode implements GlslNode { - - private String name; - private GlslSpecifiedType returnType; - private final List parameters; - - public GlslFunctionHeaderNode(String name, GlslType returnType, Collection parameters) { - this.name = name; - this.returnType = returnType.asSpecifiedType(); - this.parameters = new ArrayList<>(parameters); - } - - public GlslFunctionHeaderNode withParameters(GlslParameterDeclaration... parameters) { - return new GlslFunctionHeaderNode(this.name, this.returnType, new ArrayList<>(Arrays.asList(parameters))); - } - - public String getName() { - return this.name; - } - - public GlslSpecifiedType getReturnType() { - return this.returnType; - } - - public List getParameters() { - return this.parameters; - } - - public GlslFunctionHeaderNode setName(String name) { - this.name = name; - return this; - } - - public GlslFunctionHeaderNode setReturnType(GlslType returnType) { - this.returnType = returnType.asSpecifiedType(); - return this; - } - - @Override - public void visit(GlslVisitor visitor) { - - } - - @Override - public String toString() { - return "GlslFunctionHeader{name='" + this.name + "', returnType=" + this.returnType +", parameters=" + this.parameters + '}'; - } -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionNode.java index 566e3efe..4603ce90 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionNode.java @@ -1,37 +1,110 @@ package foundry.veil.impl.glsl.node.function; +import foundry.veil.impl.glsl.grammar.GlslFunctionHeader; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; +import foundry.veil.impl.glsl.node.branch.GlslReturnNode; +import foundry.veil.impl.glsl.node.expression.GlslAssignmentNode; +import foundry.veil.impl.glsl.visitor.GlslFunctionVisitor; +import org.jetbrains.annotations.Nullable; +import java.util.*; +import java.util.stream.Collectors; + +/** + * Defines a function in a GLSL file with an optional body. + * + * @author Ocelot + */ public class GlslFunctionNode implements GlslNode { - private GlslFunctionHeaderNode header; - private GlslNode body; + private GlslFunctionHeader header; + private List body; - public GlslFunctionNode(GlslFunctionHeaderNode header, GlslNode body) { + public GlslFunctionNode(GlslFunctionHeader header, @Nullable GlslNode body) { this.header = header; - this.body = body; + this.body = body != null ? body.toList() : null; } - @Override - public void visit(GlslVisitor visitor) { - + public void visit(GlslFunctionVisitor visitor) { + for (GlslNode node : this.body) { + if (node instanceof GlslReturnNode returnNode) { + visitor.visitReturn(returnNode); + return; + } + if(node instanceof GlslAssignmentNode assignmentNode) { + visitor.visitAssignment(assignmentNode); + return; + } + System.out.println(node); + } + visitor.visitFunctionEnd(); } - public GlslFunctionHeaderNode getHeader() { + /** + * @return The full signature of this function + */ + public GlslFunctionHeader getHeader() { return this.header; } - public GlslNode getBody() { + /** + * @return The body of the function or null if this is just a function prototype + */ + public @Nullable List getBody() { return this.body; } - public void setHeader(GlslFunctionHeaderNode header) { + /** + * Sets the function header of this function to the specified value. + * + * @param header The new header + */ + public void setHeader(GlslFunctionHeader header) { this.header = header; } - public void setBody(GlslNode body) { - this.body = body; + /** + * Sets the body of this function or null to make this a function prototype. + * + * @param body The new function body + */ + public void setBody(@Nullable Collection body) { + if (body != null) { + this.body = new ArrayList<>(body); + } else { + this.body = null; + } + } + + /** + * Sets the body of this function or null to make this a function prototype. + * + * @param body The new function body + */ + public void setBody(GlslNode... body) { + if (body != null) { + this.body = new ArrayList<>(Arrays.asList(body)); + } else { + this.body = null; + } + } + + @Override + public String getSourceString() { + StringBuilder builder = new StringBuilder(); + builder.append(this.header.getSourceString()); + + if (this.body == null) { + return builder + ";"; + } + + builder.append(" {\n"); + for (GlslNode node : this.body) { + builder.append('\t').append(node.getSourceString().replaceAll("\n", "\n\t")).append(";\n"); + } + builder.append("}\n"); + + return builder.toString(); } @Override diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslInvokeFunctionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslInvokeFunctionNode.java index eadc5353..440fab81 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslInvokeFunctionNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslInvokeFunctionNode.java @@ -1,11 +1,12 @@ package foundry.veil.impl.glsl.node.function; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; +import foundry.veil.impl.glsl.visitor.GlslTreeVisitor; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; public class GlslInvokeFunctionNode implements GlslNode { @@ -17,11 +18,6 @@ public GlslInvokeFunctionNode(GlslNode header, Collection parameters) this.parameters = new ArrayList<>(parameters); } - @Override - public void visit(GlslVisitor visitor) { - - } - public GlslNode getHeader() { return this.header; } @@ -38,4 +34,10 @@ public void setHeader(GlslNode header) { public String toString() { return "GlslInvokeFunctionNode{name=" + this.header + ", parameters=" + this.parameters + '}'; } + + @Override + public String getSourceString() { + String parameters = this.parameters.stream().map(GlslNode::getSourceString).collect(Collectors.joining(", ")); + return this.header.getSourceString() + "(" + parameters + ")"; + } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/function/PrimitiveConstructorNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslPrimitiveConstructorNode.java similarity index 61% rename from common/src/main/java/foundry/veil/impl/glsl/node/function/PrimitiveConstructorNode.java rename to common/src/main/java/foundry/veil/impl/glsl/node/function/GlslPrimitiveConstructorNode.java index 245f4c99..4e6c528e 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/function/PrimitiveConstructorNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslPrimitiveConstructorNode.java @@ -2,13 +2,12 @@ import foundry.veil.impl.glsl.grammar.GlslTypeSpecifier; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; -public class PrimitiveConstructorNode implements GlslNode { +public class GlslPrimitiveConstructorNode implements GlslNode { private GlslTypeSpecifier type; - public PrimitiveConstructorNode(GlslTypeSpecifier type) { + public GlslPrimitiveConstructorNode(GlslTypeSpecifier type) { this.type = type; } @@ -21,12 +20,12 @@ public void setType(GlslTypeSpecifier type) { } @Override - public void visit(GlslVisitor visitor) { - + public String toString() { + return "PrimitiveConstructorNode{operand=" + this.type + '}'; } @Override - public String toString() { - return "PrimitiveConstructorNode{type=" + this.type + '}'; + public String getSourceString() { + return this.type.getSourceString(); } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslBoolConstantNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslBoolConstantNode.java index 296017bc..a5dd80dc 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslBoolConstantNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslBoolConstantNode.java @@ -1,17 +1,31 @@ package foundry.veil.impl.glsl.node.primary; import foundry.veil.impl.glsl.node.GlslConstantNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; public record GlslBoolConstantNode(boolean value) implements GlslConstantNode { @Override - public void visit(GlslVisitor visitor) { - + public Number numberValue() { + return this.value ? 1 : 0; } @Override - public Object rawValue() { + public boolean booleanValue() { return this.value; } + + @Override + public boolean isNumber() { + return false; + } + + @Override + public String getSourceString() { + return Boolean.toString(this.value); + } + + @Override + public String toString() { + return this.getSourceString(); + } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslDoubleConstantNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslDoubleConstantNode.java index f0292ef4..feee0e51 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslDoubleConstantNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslDoubleConstantNode.java @@ -1,17 +1,36 @@ package foundry.veil.impl.glsl.node.primary; import foundry.veil.impl.glsl.node.GlslConstantNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; public record GlslDoubleConstantNode(double value) implements GlslConstantNode { @Override - public void visit(GlslVisitor visitor) { - + public Number numberValue() { + return this.value; } @Override - public Object rawValue() { + public double doubleValue() { return this.value; } + + @Override + public boolean booleanValue() { + return this.value != 0.0; + } + + @Override + public boolean isNumber() { + return true; + } + + @Override + public String getSourceString() { + return Double.toString(this.value); + } + + @Override + public String toString() { + return this.getSourceString(); + } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslFloatConstantNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslFloatConstantNode.java index 91ef523f..ac699df8 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslFloatConstantNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslFloatConstantNode.java @@ -1,17 +1,36 @@ package foundry.veil.impl.glsl.node.primary; import foundry.veil.impl.glsl.node.GlslConstantNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; public record GlslFloatConstantNode(float value) implements GlslConstantNode { @Override - public void visit(GlslVisitor visitor) { - + public Number numberValue() { + return this.value; } @Override - public Object rawValue() { + public float floatValue() { return this.value; } + + @Override + public boolean booleanValue() { + return this.value != 0.0; + } + + @Override + public boolean isNumber() { + return true; + } + + @Override + public String getSourceString() { + return Float.toString(this.value); + } + + @Override + public String toString() { + return this.getSourceString(); + } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslIntConstantNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslIntConstantNode.java index 6076f7a2..5373af11 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslIntConstantNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslIntConstantNode.java @@ -1,17 +1,40 @@ package foundry.veil.impl.glsl.node.primary; import foundry.veil.impl.glsl.node.GlslConstantNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; -public record GlslIntConstantNode(GlslIntFormat format, int value) implements GlslConstantNode { +public record GlslIntConstantNode(GlslIntFormat format, boolean signed, int value) implements GlslConstantNode { @Override - public void visit(GlslVisitor visitor) { - + public Number numberValue() { + return this.value; } @Override - public Object rawValue() { + public int intValue() { return this.value; } + + @Override + public boolean booleanValue() { + return this.value != 0.0; + } + + @Override + public boolean isNumber() { + return true; + } + + @Override + public String getSourceString() { + return switch (this.format) { + case HEXADECIMAL -> "0x" + Integer.toHexString(this.value); + case OCTAL -> Integer.toOctalString(this.value); + case DECIMAL -> Integer.toString(this.value); + }; + } + + @Override + public String toString() { + return this.getSourceString(); + } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslUIntConstantNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslUIntConstantNode.java deleted file mode 100644 index a18893f7..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/node/primary/GlslUIntConstantNode.java +++ /dev/null @@ -1,17 +0,0 @@ -package foundry.veil.impl.glsl.node.primary; - -import foundry.veil.impl.glsl.node.GlslConstantNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; - -public record GlslUIntConstantNode(GlslIntFormat format, int value) implements GlslConstantNode { - - @Override - public void visit(GlslVisitor visitor) { - - } - - @Override - public Object rawValue() { - return this.value; - } -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslArrayNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslArrayNode.java index 645d0cf0..6555021f 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslArrayNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslArrayNode.java @@ -1,19 +1,44 @@ package foundry.veil.impl.glsl.node.variable; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; -import java.util.Collection; -import java.util.List; +public class GlslArrayNode implements GlslNode { -public record GlslArrayNode(GlslNode expression, GlslNode index) implements GlslNode { + private GlslNode expression; + private GlslNode index; + + public GlslArrayNode(GlslNode expression, GlslNode index) { + this.expression = expression; + this.index = index; + } + + public GlslNode getExpression() { + return this.expression; + } + + public GlslNode getIndex() { + return this.index; + } + + public GlslArrayNode setExpression(GlslNode expression) { + this.expression = expression; + return this; + } + + public GlslArrayNode setIndex(GlslNode index) { + this.index = index; + return this; + } @Override - public void visit(GlslVisitor visitor) { + public String getSourceString() { + return this.expression.getSourceString() + '[' + this.index.getSourceString() + ']'; } @Override - public Collection children() { - return List.of(this.expression, this.index); + public String toString() { + return "GlslArrayNode{" + + "expression=" + this.expression + ", " + + "index=" + this.index + '}'; } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslFieldNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslFieldNode.java index cc21cf17..58f82601 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslFieldNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslFieldNode.java @@ -1,19 +1,44 @@ package foundry.veil.impl.glsl.node.variable; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; -import java.util.Collection; -import java.util.Collections; +public class GlslFieldNode implements GlslNode { -public record GlslFieldNode(GlslNode expression, String fieldSelection) implements GlslNode { + private GlslNode expression; + private String fieldSelection; + + public GlslFieldNode(GlslNode expression, String fieldSelection) { + this.expression = expression; + this.fieldSelection = fieldSelection; + } + + public GlslNode getExpression() { + return this.expression; + } + + public String getFieldSelection() { + return this.fieldSelection; + } + + public GlslFieldNode setExpression(GlslNode expression) { + this.expression = expression; + return this; + } + + public GlslFieldNode setFieldSelection(String fieldSelection) { + this.fieldSelection = fieldSelection; + return this; + } @Override - public void visit(GlslVisitor visitor) { + public String getSourceString() { + return this.expression.getSourceString() + '.' + this.fieldSelection; } @Override - public Collection children() { - return Collections.singleton(this.expression); + public String toString() { + return "GlslFieldNode{" + + "expression=" + this.expression + ", " + + "fieldSelection=" + this.fieldSelection + '}'; } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslNewNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslNewNode.java index b8dc32e6..ecdd0e34 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslNewNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslNewNode.java @@ -1,15 +1,10 @@ package foundry.veil.impl.glsl.node.variable; +import foundry.veil.impl.glsl.grammar.GlslSpecifiedType; import foundry.veil.impl.glsl.grammar.GlslType; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; -import foundry.veil.impl.glsl.grammar.GlslSpecifiedType; import org.jetbrains.annotations.Nullable; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - public class GlslNewNode implements GlslNode { private GlslSpecifiedType type; @@ -22,15 +17,6 @@ public GlslNewNode(GlslType type, String name, @Nullable GlslNode initializer) { this.initializer = initializer; } - @Override - public void visit(GlslVisitor visitor) { - } - - @Override - public Collection children() { - return this.initializer != null ? List.of(this.initializer) : Collections.emptyList(); - } - public GlslSpecifiedType getType() { return this.type; } @@ -58,8 +44,13 @@ public GlslNewNode setInitializer(@Nullable GlslNode initializer) { return this; } + @Override + public String getSourceString() { + return this.type.getSourceString() + ' ' + this.name + (this.initializer != null ? " = " + this.initializer.getSourceString() : ""); + } + @Override public String toString() { - return "GlslNewNode{type=" + this.type + ", name='" + this.name + "', initializer=" + this.initializer + '}'; + return "GlslNewNode{operand=" + this.type + ", name='" + this.name + "', initializer=" + this.initializer + '}'; } } \ No newline at end of file diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslVariableNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslVariableNode.java index 011ab3ca..b1872883 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslVariableNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslVariableNode.java @@ -1,12 +1,32 @@ package foundry.veil.impl.glsl.node.variable; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslVisitor; -public record GlslVariableNode(String name) implements GlslNode { +public class GlslVariableNode implements GlslNode { + + private String name; + + public GlslVariableNode(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public GlslVariableNode setName(String name) { + this.name = name; + return this; + } @Override - public void visit(GlslVisitor visitor) { + public String getSourceString() { + return this.name; + } + @Override + public String toString() { + return "GlslVariableNode{" + + "name=" + this.name + '}'; } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslFunctionVisitor.java b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslFunctionVisitor.java index 5cf321e2..b50af2dd 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslFunctionVisitor.java +++ b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslFunctionVisitor.java @@ -1,4 +1,22 @@ package foundry.veil.impl.glsl.visitor; +import foundry.veil.impl.glsl.node.branch.GlslReturnNode; +import foundry.veil.impl.glsl.node.expression.GlslAssignmentNode; +import foundry.veil.impl.glsl.node.expression.GlslPrecisionNode; +import foundry.veil.impl.glsl.node.function.GlslInvokeFunctionNode; +import foundry.veil.impl.glsl.node.variable.GlslNewNode; + public interface GlslFunctionVisitor { + + void visitReturn(GlslReturnNode node); + + void visitAssignment(GlslAssignmentNode node); + + void visitPrecision(GlslPrecisionNode node); + + void visitInvokeFunction(GlslInvokeFunctionNode node); + + void visitNew(GlslNewNode node); + + void visitFunctionEnd(); } diff --git a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslNodeVisitor.java b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslNodeVisitor.java new file mode 100644 index 00000000..a23c9936 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslNodeVisitor.java @@ -0,0 +1,9 @@ +package foundry.veil.impl.glsl.visitor; + +import foundry.veil.impl.glsl.node.GlslNode; + +@FunctionalInterface +public interface GlslNodeVisitor { + + void visitNode(GlslNode node); +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslStringWriter.java b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslStringWriter.java new file mode 100644 index 00000000..ef81a4d5 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslStringWriter.java @@ -0,0 +1,49 @@ +package foundry.veil.impl.glsl.visitor; + +import foundry.veil.impl.glsl.grammar.GlslVersion; +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.node.function.GlslFunctionNode; +import foundry.veil.impl.glsl.node.variable.GlslNewNode; +import org.jetbrains.annotations.Nullable; + +public class GlslStringWriter implements GlslTreeVisitor, GlslFieldVisitor { + + private final StringBuilder builder; + private String value; + + public GlslStringWriter() { + this.builder = new StringBuilder(); + this.value = ""; + } + + private String formatExpression(GlslNode node) { + return node.getSourceString(); + } + + @Override + public void visitVersion(GlslVersion version) { + this.builder.append("#version ").append(version.getVersionStatement()).append("\n\n"); + } + + @Override + public void visitField(GlslNewNode node) { + this.builder.append(this.formatExpression(node)).append(";\n"); + } + + @Override + public @Nullable GlslFunctionVisitor visitFunction(GlslFunctionNode node) { + this.builder.append(node.getSourceString()); + return null; + } + + @Override + public void visitTreeEnd() { + this.value = this.builder.toString(); + this.builder.setLength(0); + } + + @Override + public String toString() { + return this.value; + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslTreeVisitor.java b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslTreeVisitor.java new file mode 100644 index 00000000..1acba658 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslTreeVisitor.java @@ -0,0 +1,17 @@ +package foundry.veil.impl.glsl.visitor; + +import foundry.veil.impl.glsl.grammar.GlslVersion; +import foundry.veil.impl.glsl.node.function.GlslFunctionNode; +import foundry.veil.impl.glsl.node.variable.GlslNewNode; +import org.jetbrains.annotations.Nullable; + +public interface GlslTreeVisitor { + + void visitVersion(GlslVersion version); + + void visitField(GlslNewNode node); + + @Nullable GlslFunctionVisitor visitFunction(GlslFunctionNode node); + + void visitTreeEnd(); +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslVisitor.java b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslVisitor.java deleted file mode 100644 index 638df832..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslVisitor.java +++ /dev/null @@ -1,18 +0,0 @@ -package foundry.veil.impl.glsl.visitor; - -import foundry.veil.impl.glsl.node.branch.ForLoopNode; -import foundry.veil.impl.glsl.node.branch.GlslCaseLabelNode; -import foundry.veil.impl.glsl.node.variable.GlslFieldNode; - -public interface GlslVisitor { - - default GlslFieldVisitor visitField(GlslFieldNode node) { - return null; - } - - default void visitForLoop(ForLoopNode node) { - } - - default void visitCaseLabel(GlslCaseLabelNode node) { - } -} diff --git a/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/shaders/program/light/area.vsh b/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/shaders/program/light/area.vsh index e3682e95..2936afbb 100644 --- a/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/shaders/program/light/area.vsh +++ b/common/src/main/resources/resourcepacks/deferred/assets/veil/pinwheel/shaders/program/light/area.vsh @@ -21,7 +21,7 @@ void main() { vertexPos *= vec3(Size.x + angleTerm, Size.y + angleTerm, Distance); // awful fix but not sure why just multiplying the matrix doesnt work? it does what it should in - // all the branch calculations. really weird! + // all the second calculations. really weird! vec3 lightPos = LightMatrix[3].xyz; mat3 rotationMatrix = mat3(LightMatrix); lightPos = inverse(rotationMatrix) * lightPos; diff --git a/common/src/test/java/GlslTest.java b/common/src/test/java/GlslTest.java index 3756b460..c6cceef4 100644 --- a/common/src/test/java/GlslTest.java +++ b/common/src/test/java/GlslTest.java @@ -1,19 +1,14 @@ import foundry.veil.impl.glsl.GlslLexer; import foundry.veil.impl.glsl.GlslParser; import foundry.veil.impl.glsl.GlslSyntaxException; -import foundry.veil.impl.glsl.node.GlslTree; import foundry.veil.impl.glsl.grammar.GlslVersion; +import foundry.veil.impl.glsl.node.GlslTree; +import foundry.veil.impl.glsl.visitor.GlslStringWriter; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; public class GlslTest { - @Test - void testLexer() throws GlslSyntaxException { - GlslLexer.Token[] tokens = GlslLexer.createTokens("float a = 4e2; // comment"); - Assertions.assertEquals("float a = 4e2 ;\n// comment\n", this.toString(tokens)); - } - private String toString(GlslLexer.Token[] tokens) { StringBuilder build = new StringBuilder(); for (GlslLexer.Token token : tokens) { @@ -27,16 +22,26 @@ private String toString(GlslLexer.Token[] tokens) { return build.toString(); } + @Test + void testLexer() throws GlslSyntaxException { + GlslLexer.Token[] tokens = GlslLexer.createTokens("float a = 4e2; // comment"); + Assertions.assertEquals("float a = 4e2 ;\n", this.toString(tokens)); + } + @Test void testParser() throws GlslSyntaxException { GlslLexer.Token[] tokens = GlslLexer.createTokens("#version 330 core\nfloat a = 1.0 + 3.0;"); GlslTree tree = GlslParser.parse(tokens); Assertions.assertEquals(new GlslVersion(330, true), tree.getVersion()); + GlslStringWriter stringWriter = new GlslStringWriter(); + tree.visit(stringWriter); + + System.out.println(stringWriter); } @Test void testSet() throws GlslSyntaxException { - GlslLexer.Token[] tokens = GlslLexer.createTokens(""" + this.testSpeed(""" #version 330 core uniform vec4 color; @@ -46,25 +51,20 @@ void main() { test = 2.0; } """); - GlslTree tree = GlslParser.parse(tokens); - System.out.println(tree); } @Test void testCall() throws GlslSyntaxException { - GlslLexer.Token[] tokens = GlslLexer.createTokens(""" + this.testSpeed(""" void main() { vec4 baseColor = texture(DiffuseSampler0, texCoord); } """); - GlslTree tree = GlslParser.parse(tokens); - System.out.println(this.toString(tokens)); } @Test void testShader() throws GlslSyntaxException { - long start = System.nanoTime(); - GlslLexer.Token[] tokens = GlslLexer.createTokens(""" + this.testSpeed(""" #version 430 core uniform sampler2D DiffuseSampler0; @@ -92,23 +92,40 @@ void main() { fragColor = linear_fog(baseColor, vertexDistance, FogStart, FogEnd, FogColor); } """); + } + + private void testSpeed(String source) throws GlslSyntaxException { + // Load classes + for (int i = 0; i < 3; i++) { + GlslLexer.Token[] tokens = GlslLexer.createTokens(source); + GlslTree tree = GlslParser.parse(tokens); + GlslStringWriter stringWriter = new GlslStringWriter(); + tree.visit(stringWriter); + } + + long start = System.nanoTime(); + GlslLexer.Token[] tokens = GlslLexer.createTokens(source); + long parseStart = System.nanoTime(); GlslTree tree = GlslParser.parse(tokens); + long parseEnd = System.nanoTime(); + + GlslStringWriter stringWriter = new GlslStringWriter(); + tree.visit(stringWriter); long end = System.nanoTime(); - System.out.printf("Took %.1fms to tokenize, %.1fms to parse%n", (parseStart - start) / 1_000_000.0F, (end - parseStart) / 1_000_000.0F); - System.out.println(tree); + + System.out.println(stringWriter); + System.out.printf("Took %.1fms to tokenize, %.1fms to parse, %.1fms to stringify%n", (parseStart - start) / 1_000_000.0F, (parseEnd - parseStart) / 1_000_000.0F, (end - parseEnd) / 1_000_000.0F); } @Test void testReturn() throws GlslSyntaxException { - GlslLexer.Token[] tokens = GlslLexer.createTokens(""" + this.testSpeed(""" #version 430 core - vec3 test(int) { + vec3 test(inout vec3 test, int) { return normalize(vec3(7.0, 0.0, 1.0)); } """); - GlslTree tree = GlslParser.parse(tokens); - System.out.println(tree); } } From cb3b3a68fc6c4f4aa83a2c0ec08f65a9e2a95402 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Tue, 12 Nov 2024 02:48:53 -0700 Subject: [PATCH 34/47] Re-implemented shader modifications --- .../main/java/foundry/veil/VeilClient.java | 4 +- .../shader/ShaderModificationManager.java | 36 +- .../modifier/InputShaderModification.java | 5 +- .../modifier/ReplaceShaderModification.java | 8 +- .../shader/modifier/ShaderModification.java | 6 +- .../modifier/SimpleShaderModification.java | 130 +++--- .../modifier/VertexShaderModification.java | 54 ++- .../foundry/veil/impl/glsl/GlslLexer.java | 3 +- .../foundry/veil/impl/glsl/GlslParser.java | 394 +++++++++++------- .../veil/impl/glsl/GlslTokenReader.java | 26 +- .../impl/glsl/grammar/GlslSpecifiedType.java | 5 + .../impl/glsl/grammar/GlslStructField.java | 34 ++ .../glsl/grammar/GlslStructSpecifier.java | 41 +- .../impl/glsl/grammar/GlslTypeQualifier.java | 38 +- .../impl/glsl/grammar/GlslTypeSpecifier.java | 273 ++++++------ .../veil/impl/glsl/node/GlslCompoundNode.java | 15 +- .../veil/impl/glsl/node/GlslEmptyNode.java | 5 - .../foundry/veil/impl/glsl/node/GlslNode.java | 27 +- .../foundry/veil/impl/glsl/node/GlslTree.java | 74 +++- .../impl/glsl/node/branch/ForLoopNode.java | 40 +- .../glsl/node/branch/GlslSelectionNode.java | 67 ++- .../node/expression/GlslAssignmentNode.java | 2 +- .../node/expression/GlslConditionalNode.java | 2 +- .../node/expression/GlslOperationNode.java | 28 +- .../GlslPrimitiveConstructorNode.java | 2 +- .../glsl/node/variable/GlslDeclaration.java | 42 ++ .../glsl/node/variable/GlslFieldNode.java | 5 +- .../impl/glsl/node/variable/GlslNewNode.java | 16 +- .../glsl/node/variable/GlslStructNode.java | 21 + .../impl/glsl/visitor/GlslFieldVisitor.java | 4 - .../impl/glsl/visitor/GlslStringWriter.java | 23 +- .../impl/glsl/visitor/GlslTreeVisitor.java | 11 +- common/src/test/java/GlslTest.java | 210 ++++++++-- 33 files changed, 1159 insertions(+), 492 deletions(-) create mode 100644 common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructField.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslDeclaration.java create mode 100644 common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslStructNode.java delete mode 100644 common/src/main/java/foundry/veil/impl/glsl/visitor/GlslFieldVisitor.java diff --git a/common/src/main/java/foundry/veil/VeilClient.java b/common/src/main/java/foundry/veil/VeilClient.java index 64150ccd..a6484e2a 100644 --- a/common/src/main/java/foundry/veil/VeilClient.java +++ b/common/src/main/java/foundry/veil/VeilClient.java @@ -53,7 +53,9 @@ public static void init() { // debug editors editorManager.add(new DemoEditor()); editorManager.add(new PostEditor()); -// editorManager.add(new ShaderEditor()); + if (Veil.DEBUG) { + editorManager.add(new ShaderEditor()); + } editorManager.add(new TextureEditor()); editorManager.add(new OpenCLEditor()); editorManager.add(new DeviceInfoViewer()); diff --git a/common/src/main/java/foundry/veil/api/client/render/shader/ShaderModificationManager.java b/common/src/main/java/foundry/veil/api/client/render/shader/ShaderModificationManager.java index 7fb2e5e0..5ade6c87 100644 --- a/common/src/main/java/foundry/veil/api/client/render/shader/ShaderModificationManager.java +++ b/common/src/main/java/foundry/veil/api/client/render/shader/ShaderModificationManager.java @@ -5,6 +5,11 @@ import foundry.veil.impl.client.render.shader.modifier.ReplaceShaderModification; import foundry.veil.impl.client.render.shader.modifier.ShaderModification; import foundry.veil.impl.client.render.shader.modifier.SimpleShaderModification; +import foundry.veil.impl.client.render.shader.transformer.VeilJobParameters; +import foundry.veil.impl.glsl.GlslParser; +import foundry.veil.impl.glsl.GlslSyntaxException; +import foundry.veil.impl.glsl.node.GlslTree; +import foundry.veil.impl.glsl.visitor.GlslStringWriter; import net.minecraft.resources.FileToIdConverter; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.Resource; @@ -36,18 +41,10 @@ public class ShaderModificationManager extends SimplePreparableReloadListener> shaders; private Map names; public ShaderModificationManager() { -// this.transformer = new VeilASTTransformer(); -// this.transformer.setPrintType(PrintType.INDENTED_ANNOTATED); -// this.transformer.setRootSupplier(RootSupplier.PREFIX_UNORDERED_ED_EXACT); -// GLSLLexer lexer = this.transformer.getLexer(); -// lexer.enableCustomDirective = true; - this.shaders = Collections.emptyMap(); } @@ -61,11 +58,24 @@ public ShaderModificationManager() { * @see ShaderModification */ public String applyModifiers(ResourceLocation shaderId, String source, int flags) { -// try { -// return this.transformer.transform(source, new VeilJobParameters(this, shaderId, flags)); -// } catch (TransformationException | ParsingException | IllegalStateException | IllegalArgumentException e) { -// Veil.LOGGER.error("Failed to transform shader: {}", shaderId, e); -// } + Collection modifiers = this.getModifiers(shaderId); + if (modifiers.isEmpty()) { + return source; + } + + try { + GlslTree tree = GlslParser.parse(source); + VeilJobParameters parameters = new VeilJobParameters(this, shaderId, flags); + for (ShaderModification modifier : modifiers) { + modifier.inject(tree, parameters); + } + + GlslStringWriter writer = new GlslStringWriter(); + tree.visit(writer); + return writer.toString(); + } catch (Exception e) { + Veil.LOGGER.error("Failed to transform shader: {}", shaderId, e); + } return source; } diff --git a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/InputShaderModification.java b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/InputShaderModification.java index 807f0375..d229deab 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/InputShaderModification.java +++ b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/InputShaderModification.java @@ -1,6 +1,8 @@ package foundry.veil.impl.client.render.shader.modifier; import foundry.veil.impl.client.render.shader.transformer.VeilJobParameters; +import foundry.veil.impl.glsl.GlslParser; +import foundry.veil.impl.glsl.GlslSyntaxException; import foundry.veil.impl.glsl.node.GlslTree; import org.jetbrains.annotations.ApiStatus; @@ -18,7 +20,8 @@ public InputShaderModification(int priority, String input) { } @Override - public void inject(GlslTree tree, VeilJobParameters parameters) throws IOException { + public void inject(GlslTree tree, VeilJobParameters parameters) throws GlslSyntaxException { + tree.getBody().addAll(0, GlslParser.parse(this.input).getBody()); // tree.parseAndInjectNodes(parser, ASTInjectionPoint.BEFORE_DECLARATIONS, this.input.split("\n")); } diff --git a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/ReplaceShaderModification.java b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/ReplaceShaderModification.java index f7c28618..540af44f 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/ReplaceShaderModification.java +++ b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/ReplaceShaderModification.java @@ -1,18 +1,16 @@ package foundry.veil.impl.client.render.shader.modifier; import foundry.veil.impl.client.render.shader.transformer.VeilJobParameters; +import foundry.veil.impl.glsl.GlslSyntaxException; import foundry.veil.impl.glsl.node.GlslTree; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.ApiStatus; -import java.io.IOException; -import java.io.UnsupportedEncodingException; - @ApiStatus.Internal public record ReplaceShaderModification(int priority, ResourceLocation veilShader) implements ShaderModification { @Override - public void inject(GlslTree tree, VeilJobParameters parameters) throws IOException { - throw new UnsupportedEncodingException("Replace modification replaces file"); + public void inject(GlslTree tree, VeilJobParameters parameters) throws GlslSyntaxException { + throw new UnsupportedOperationException("Replace modification replaces file"); } } diff --git a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/ShaderModification.java b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/ShaderModification.java index 719bd548..5a5894ff 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/ShaderModification.java +++ b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/ShaderModification.java @@ -1,6 +1,7 @@ package foundry.veil.impl.client.render.shader.modifier; import foundry.veil.impl.client.render.shader.transformer.VeilJobParameters; +import foundry.veil.impl.glsl.GlslSyntaxException; import foundry.veil.impl.glsl.node.GlslTree; import org.jetbrains.annotations.ApiStatus; @@ -27,9 +28,10 @@ public interface ShaderModification { * * @param tree The source to modify * @param parameters The parameters to use when injecting - * @throws IOException If an error occurs with the format or applying the modifications + * @throws GlslSyntaxException If an error occurs when parsing GLSL code + * @throws IOException If an error occurs with the format or applying the modifications */ - void inject(GlslTree tree, VeilJobParameters parameters) throws IOException; + void inject(GlslTree tree, VeilJobParameters parameters) throws GlslSyntaxException, IOException; /** * @return The priority of this modification. A higher priority will be applied before a lower priority modification diff --git a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/SimpleShaderModification.java b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/SimpleShaderModification.java index 9cb75b4a..41628af8 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/SimpleShaderModification.java +++ b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/SimpleShaderModification.java @@ -1,12 +1,19 @@ package foundry.veil.impl.client.render.shader.modifier; import foundry.veil.impl.client.render.shader.transformer.VeilJobParameters; +import foundry.veil.impl.glsl.GlslParser; +import foundry.veil.impl.glsl.GlslSyntaxException; +import foundry.veil.impl.glsl.grammar.GlslVersion; +import foundry.veil.impl.glsl.node.GlslCompoundNode; +import foundry.veil.impl.glsl.node.GlslNode; import foundry.veil.impl.glsl.node.GlslTree; +import foundry.veil.impl.glsl.node.function.GlslFunctionNode; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import java.io.IOException; +import java.util.List; import java.util.regex.Matcher; @ApiStatus.Internal @@ -29,61 +36,61 @@ public SimpleShaderModification(int version, int priority, ResourceLocation[] in } @Override - public void inject(GlslTree tree, VeilJobParameters parameters) throws IOException { -// if (parameters.applyVersion()) { -// tree.ensureVersionStatement(); -// VersionStatement statement = tree.getVersionStatement(); -// if (statement.version.number < this.version) { -// statement.version = Version.fromNumber(this.version); -// } -// } -// -// String[] includes = new String[this.includes.length]; -// for (int i = 0; i < this.includes.length; i++) { -// includes[i] = "#custom veil:include " + this.includes[i] + "\n"; -// } -// tree.parseAndInjectNodes(parser, ASTInjectionPoint.BEFORE_DECLARATIONS, includes); -// -// if (!StringUtil.isNullOrEmpty(this.uniform)) { -// tree.parseAndInjectNodes(parser, ASTInjectionPoint.BEFORE_DECLARATIONS, this.fillPlaceholders(this.uniform).split("\n")); -// } -// -// if (!StringUtil.isNullOrEmpty(this.output)) { -// tree.parseAndInjectNodes(parser, ASTInjectionPoint.BEFORE_DECLARATIONS, this.fillPlaceholders(this.output).split("\n")); -// } -// -// Root root = tree.getRoot(); -// for (Function function : this.functions) { -// String name = function.name(); -// ChildNodeList statements = root.identifierIndex.getStream(name) -// .map(id -> id.getBranchAncestor(FunctionDefinition.class, FunctionDefinition::getFunctionPrototype)) -// .filter(definition -> { -// if (definition == null) { -// return false; -// } -// -// int paramCount = function.parameters(); -// if (paramCount == -1) { -// return true; -// } -// return definition.getFunctionPrototype().getParameters().size() == paramCount; -// }) -// .findFirst() -// .map(FunctionDefinition::getBody).orElseThrow(() -> { -// int paramCount = function.parameters(); -// if (paramCount == -1) { -// return new IOException("Unknown function: " + name); -// } -// return new IOException("Unknown function with " + paramCount + " parameters: " + name); -// }).getStatements(); -// -// Statement statement = parser.parseStatement(root, this.fillPlaceholders("{" + function.code() + "}")); -// if (function.head()) { -// statements.add(0, statement); -// } else { -// statements.add(statement); -// } -// } + public void inject(GlslTree tree, VeilJobParameters parameters) throws GlslSyntaxException, IOException { + if (parameters.applyVersion()) { + GlslVersion version = tree.getVersion(); + if (version.getVersion() < this.version) { + version.setVersion(this.version); + } + } + + List directives = tree.getDirectives(); + for (ResourceLocation include : this.includes) { + directives.add("#custom veil:include " + include); + } + + if (this.output != null && !this.output.isEmpty()) { + tree.getBody().addAll(0, GlslParser.parse(this.fillPlaceholders(this.output)).getBody()); + } + + if (this.uniform != null && !this.uniform.isEmpty()) { + tree.getBody().addAll(0, GlslParser.parse(this.fillPlaceholders(this.uniform)).getBody()); + } + + for (Function function : this.functions) { + String name = function.name(); + List body = tree.functions().filter(definition -> { + if (definition == null) { + return false; + } + + if (definition.getBody() == null) { + return false; + } + + int paramCount = function.parameters(); + if (paramCount == -1) { + return true; + } + return definition.getHeader().getParameters().size() == paramCount; + }) + .findFirst() + .map(GlslFunctionNode::getBody) + .orElseThrow(() -> { + int paramCount = function.parameters(); + if (paramCount == -1) { + return new IOException("Unknown function: " + name); + } + return new IOException("Unknown function with " + paramCount + " parameters: " + name); + }); + + GlslNode insert = new GlslCompoundNode(GlslParser.parseExpressionList(this.fillPlaceholders(function.code()))); + if (function.head()) { + body.add(0, insert); + } else { + body.add(insert); + } + } } public String fillPlaceholders(String code) { @@ -92,13 +99,12 @@ public String fillPlaceholders(String code) { return code; } - StringBuilder sb = new StringBuilder(); - matcher.appendReplacement(sb, this.getPlaceholder(matcher.group(1))); - while (matcher.find()) { - matcher.appendReplacement(sb, this.getPlaceholder(matcher.group(1))); - } - matcher.appendTail(sb); - return sb.toString(); + StringBuilder builder = new StringBuilder(); + do { + matcher.appendReplacement(builder, this.getPlaceholder(matcher.group(1))); + } while (matcher.find()); + matcher.appendTail(builder); + return builder.toString(); } protected String getPlaceholder(String key) { diff --git a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/VertexShaderModification.java b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/VertexShaderModification.java index 7fe5a6ce..b9e29681 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/VertexShaderModification.java +++ b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/VertexShaderModification.java @@ -1,23 +1,23 @@ package foundry.veil.impl.client.render.shader.modifier; +import foundry.veil.impl.client.render.shader.transformer.VeilJobParameters; +import foundry.veil.impl.glsl.GlslParser; +import foundry.veil.impl.glsl.GlslSyntaxException; +import foundry.veil.impl.glsl.grammar.GlslSpecifiedType; +import foundry.veil.impl.glsl.grammar.GlslTypeQualifier; +import foundry.veil.impl.glsl.node.GlslTree; +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; +import java.io.IOException; import java.util.HashMap; import java.util.Map; @ApiStatus.Internal public class VertexShaderModification extends SimpleShaderModification { -// public static final Matcher INPUT = new Matcher<>("in type name;", ParseShape.EXTERNAL_DECLARATION) { -// { -// Root root = this.pattern.getRoot(); -// this.markClassWildcard("type", root.identifierIndex.getUnique("type").getAncestor(TypeSpecifier.class), BuiltinNumericTypeSpecifier.class); -// this.markClassWildcard("name*", root.identifierIndex.getUnique("name").getAncestor(DeclarationMember.class)); -// } -// }; - private final Attribute[] attributes; private final Map mapper; @@ -71,6 +71,44 @@ public VertexShaderModification(int version, int priority, ResourceLocation[] in // super.inject(parser, tree, parameters); // } + + @Override + public void inject(GlslTree tree, VeilJobParameters parameters) throws GlslSyntaxException, IOException { + if (this.attributes.length > 0) { + Map validInputs = new Int2ObjectArrayMap<>(); + + tree.fields().forEach(node -> { + GlslSpecifiedType type = node.getType(); + + for (GlslTypeQualifier qualifier : type.getQualifiers()) { + if (qualifier instanceof GlslTypeQualifier.StorageType storage && storage == GlslTypeQualifier.StorageType.IN) { + validInputs.put(validInputs.size(), new Attribute(validInputs.size(), type.getSpecifier().getSourceString(), node.getName())); + break; + } + } + }); + + this.mapper.clear(); + for (Attribute attribute : this.attributes) { + Attribute sourceAttribute = validInputs.get(attribute.index); + if (sourceAttribute == null) { + // TODO this might be messed up on mac. It needs to be tested + tree.getBody().add(0, GlslParser.parseExpression("layout(location = " + attribute.index + ") in " + attribute.type + " " + attribute.name)); + this.mapper.put(attribute.name, attribute.name); + continue; + } + + if (!sourceAttribute.type.equals(attribute.type)) { + throw new IOException("Expected attribute " + attribute.index + " to be " + attribute.type + " but was " + sourceAttribute.type); + } + + this.mapper.put(attribute.name, sourceAttribute.name); + } + } + + super.inject(tree, parameters); + } + @Override protected String getPlaceholder(String key) { String name = this.mapper.get(key); diff --git a/common/src/main/java/foundry/veil/impl/glsl/GlslLexer.java b/common/src/main/java/foundry/veil/impl/glsl/GlslLexer.java index 24667743..b074cd2b 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/GlslLexer.java +++ b/common/src/main/java/foundry/veil/impl/glsl/GlslLexer.java @@ -71,7 +71,7 @@ public enum TokenType { DIRECTIVE("#.*"), GLSL_MACRO("__LINE__|__FILE__|__VERSION__"), COMMENT("\\/\\/.*"), - MULTI_COMMENT("\\/\\*(?:.|[\\n\\r])*\\*\\/|\\/\\/(?:.*\\\\[\\n\\r]?)+[\\n\\r]?(?:.*)"), + MULTI_COMMENT("\\/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*\\/"), CONST("const"), BOOL("bool"), @@ -451,7 +451,6 @@ public enum TokenType { case RESTRICT -> GlslTypeQualifier.StorageType.RESTRICT; case READONLY -> GlslTypeQualifier.StorageType.READONLY; case WRITEONLY -> GlslTypeQualifier.StorageType.WRITEONLY; - case SUBROUTINE -> GlslTypeQualifier.StorageType.SUBROUTINE; default -> null; }; } diff --git a/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java b/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java index 0a351c2a..8863079e 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java +++ b/common/src/main/java/foundry/veil/impl/glsl/GlslParser.java @@ -1,18 +1,19 @@ package foundry.veil.impl.glsl; import foundry.veil.impl.glsl.grammar.*; -import foundry.veil.impl.glsl.node.*; +import foundry.veil.impl.glsl.node.GlslEmptyNode; +import foundry.veil.impl.glsl.node.GlslNode; +import foundry.veil.impl.glsl.node.GlslTree; import foundry.veil.impl.glsl.node.branch.*; import foundry.veil.impl.glsl.node.expression.*; import foundry.veil.impl.glsl.node.function.GlslFunctionNode; -import foundry.veil.impl.glsl.grammar.GlslFunctionHeader; import foundry.veil.impl.glsl.node.function.GlslInvokeFunctionNode; import foundry.veil.impl.glsl.node.function.GlslPrimitiveConstructorNode; -import foundry.veil.impl.glsl.node.variable.GlslArrayNode; -import foundry.veil.impl.glsl.node.primary.*; -import foundry.veil.impl.glsl.node.variable.GlslFieldNode; -import foundry.veil.impl.glsl.node.variable.GlslNewNode; -import foundry.veil.impl.glsl.node.variable.GlslVariableNode; +import foundry.veil.impl.glsl.node.primary.GlslBoolConstantNode; +import foundry.veil.impl.glsl.node.primary.GlslFloatConstantNode; +import foundry.veil.impl.glsl.node.primary.GlslIntConstantNode; +import foundry.veil.impl.glsl.node.primary.GlslIntFormat; +import foundry.veil.impl.glsl.node.variable.*; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -23,92 +24,9 @@ public final class GlslParser { - private static final String GRAMMAR = """ - variable_identifier : IDENTIFIER - primary_expression : variable_identifier | INTCONSTANT | UINTCONSTANT | FLOATCONSTANT | BOOLCONSTANT | DOUBLECONSTANT | LEFT_PAREN expression RIGHT_PAREN - postfix_expression : primary_expression | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET | function_call | postfix_expression DOT FIELD_SELECTION | postfix_expression INC_OP | postfix_expression DEC_OP - integer_expression : expression - function_call : function_call_or_method - function_call_or_method : function_call_generic - function_call_generic : function_call_header_with_parameters RIGHT_PAREN | function_call_header_no_parameters RIGHT_PAREN - function_call_header_no_parameters : function_call_header VOID | function_call_header - function_call_header_with_parameters : function_call_header assignment_expression | function_call_header_with_parameters COMMA assignment_expression - function_call_header : function_identifier LEFT_PAREN - function_identifier : type_specifier | postfix_expression - unary_expression : postfix_expression | INC_OP unary_expression | DEC_OP unary_expression | unary_operator unary_expression - unary_operator : PLUS | DASH | BANG | TILDE - multiplicative_expression : unary_expression | multiplicative_expression STAR unary_expression | multiplicative_expression SLASH unary_expression | multiplicative_expression PERCENT unary_expression - additive_expression : multiplicative_expression | additive_expression PLUS multiplicative_expression | additive_expression DASH multiplicative_expression - shift_expression : additive_expression | shift_expression LEFT_OP additive_expression | shift_expression RIGHT_OP additive_expression - relational_expression : shift_expression | relational_expression LEFT_ANGLE shift_expression | relational_expression RIGHT_ANGLE shift_expression | relational_expression LE_OP shift_expression | relational_expression GE_OP shift_expression - equality_expression : relational_expression | equality_expression EQ_OP relational_expression | equality_expression NE_OP relational_expression - and_expression : equality_expression | and_expression AMPERSAND equality_expression - exclusive_or_expression : and_expression | exclusive_or_expression CARET and_expression - inclusive_or_expression : exclusive_or_expression | inclusive_or_expression VERTICAL_BAR exclusive_or_expression - logical_and_expression : inclusive_or_expression | logical_and_expression AND_OP inclusive_or_expression - logical_xor_expression : logical_and_expression | logical_xor_expression XOR_OP logical_and_expression - logical_or_expression : logical_xor_expression | logical_or_expression OR_OP logical_xor_expression - conditional_expression : logical_or_expression | logical_or_expression QUESTION expression COLON assignment_expression - assignment_expression : conditional_expression | unary_expression assignment_operator assignment_expression - assignment_operator : EQUAL | MUL_ASSIGN | DIV_ASSIGN | MOD_ASSIGN | ADD_ASSIGN | SUB_ASSIGN | LEFT_ASSIGN | RIGHT_ASSIGN | AND_ASSIGN | XOR_ASSIGN | OR_ASSIGN - expression : assignment_expression | expression COMMA assignment_expression - constant_expression : conditional_expression - declaration : function_prototype SEMICOLON | init_declarator_list SEMICOLON | PRECISION precision_qualifier type_specifier SEMICOLON | type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE SEMICOLON | type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON | type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER array_specifier SEMICOLON | type_qualifier SEMICOLON | type_qualifier IDENTIFIER SEMICOLON | type_qualifier IDENTIFIER identifier_list SEMICOLON - identifier_list : COMMA IDENTIFIER | identifier_list COMMA IDENTIFIER - function_prototype : function_declarator RIGHT_PAREN - function_declarator : function_header | function_header_with_parameters - function_header_with_parameters : function_header parameter_declaration | function_header_with_parameters COMMA parameter_declaration - function_header : fully_specified_type IDENTIFIER LEFT_PAREN - parameter_declarator : type_specifier IDENTIFIER | type_specifier IDENTIFIER array_specifier - parameter_declaration : type_qualifier parameter_declarator | parameter_declarator | type_qualifier parameter_type_specifier | parameter_type_specifier - parameter_type_specifier : type_specifier - init_declarator_list : single_declaration | init_declarator_list COMMA IDENTIFIER | init_declarator_list COMMA IDENTIFIER array_specifier | init_declarator_list COMMA IDENTIFIER array_specifier EQUAL initializer | init_declarator_list COMMA IDENTIFIER EQUAL initializer - single_declaration : fully_specified_type | fully_specified_type IDENTIFIER | fully_specified_type IDENTIFIER array_specifier | fully_specified_type IDENTIFIER array_specifier EQUAL initializer | fully_specified_type IDENTIFIER EQUAL initializer - fully_specified_type : type_specifier | type_qualifier type_specifier - invariant_qualifier : INVARIANT - interpolation_qualifier : SMOOTH | FLAT | NOPERSPECTIVE - layout_qualifier : LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN - layout_qualifier_id_list : layout_qualifier_id | layout_qualifier_id_list COMMA layout_qualifier_id - layout_qualifier_id : IDENTIFIER | IDENTIFIER EQUAL constant_expression | SHARED - precise_qualifier : PRECISE - type_qualifier : single_type_qualifier | type_qualifier single_type_qualifier - single_type_qualifier : storage_qualifier | layout_qualifier | precision_qualifier | interpolation_qualifier | invariant_qualifier | precise_qualifier - storage_qualifier : CONST | IN | OUT | INOUT | CENTROID | PATCH | SAMPLE | UNIFORM | BUFFER | SHARED | COHERENT | VOLATILE | RESTRICT | READONLY | WRITEONLY | SUBROUTINE | SUBROUTINE LEFT_PAREN type_name_list RIGHT_PAREN - type_name_list : TYPE_NAME | type_name_list COMMA TYPE_NAME - type_specifier : type_specifier_nonarray | type_specifier_nonarray array_specifier - array_specifier : LEFT_BRACKET RIGHT_BRACKET | LEFT_BRACKET conditional_expression RIGHT_BRACKET | array_specifier LEFT_BRACKET RIGHT_BRACKET | array_specifier LEFT_BRACKET conditional_expression RIGHT_BRACKET - type_specifier_nonarray : VOID | FLOAT | DOUBLE | INT | UINT | BOOL | VEC2 | VEC3 | VEC4 | DVEC2 | DVEC3 | DVEC4 | BVEC2 | BVEC3 | BVEC4 | IVEC2 | IVEC3 | IVEC4 | UVEC2 | UVEC3 | UVEC4 | MAT2 | MAT3 | MAT4 | MAT2X2 | MAT2X3 | MAT2X4 | MAT3X2 | MAT3X3 | MAT3X4 | MAT4X2 | MAT4X3 | MAT4X4 | DMAT2 | DMAT3 | DMAT4 | DMAT2X2 | DMAT2X3 | DMAT2X4 | DMAT3X2 | DMAT3X3 | DMAT3X4 | DMAT4X2 | DMAT4X3 | DMAT4X4 | ATOMIC_UINT | SAMPLER2D | SAMPLER3D | SAMPLERCUBE | SAMPLER2DSHADOW | SAMPLERCUBESHADOW | SAMPLER2DARRAY | SAMPLER2DARRAYSHADOW | SAMPLERCUBEARRAY | SAMPLERCUBEARRAYSHADOW | ISAMPLER2D | ISAMPLER3D | ISAMPLERCUBE | ISAMPLER2DARRAY | ISAMPLERCUBEARRAY | USAMPLER2D | USAMPLER3D | USAMPLERCUBE | USAMPLER2DARRAY | USAMPLERCUBEARRAY | SAMPLER1D | SAMPLER1DSHADOW | SAMPLER1DARRAY | SAMPLER1DARRAYSHADOW | ISAMPLER1D | ISAMPLER1DARRAY | USAMPLER1D | USAMPLER1DARRAY | SAMPLER2DRECT | SAMPLER2DRECTSHADOW | ISAMPLER2DRECT | USAMPLER2DRECT | SAMPLERBUFFER | ISAMPLERBUFFER | USAMPLERBUFFER | SAMPLER2DMS | ISAMPLER2DMS | USAMPLER2DMS | SAMPLER2DMSARRAY | ISAMPLER2DMSARRAY | USAMPLER2DMSARRAY | IMAGE2D | IIMAGE2D | UIMAGE2D | IMAGE3D | IIMAGE3D | UIMAGE3D | IMAGECUBE | IIMAGECUBE | UIMAGECUBE | IMAGEBUFFER | IIMAGEBUFFER | UIMAGEBUFFER | IMAGE1D | IIMAGE1D | UIMAGE1D | IMAGE1DARRAY | IIMAGE1DARRAY | UIMAGE1DARRAY | IMAGE2DRECT | IIMAGE2DRECT | UIMAGE2DRECT | IMAGE2DARRAY | IIMAGE2DARRAY | UIMAGE2DARRAY | IMAGECUBEARRAY | IIMAGECUBEARRAY | UIMAGECUBEARRAY | IMAGE2DMS | IIMAGE2DMS | UIMAGE2DMS | IMAGE2DMSARRAY | IIMAGE2DMSARRAY | UIMAGE2DMSARRAY | struct_specifier | TYPE_NAME - precision_qualifier : HIGH_PRECISION | MEDIUM_PRECISION | LOW_PRECISION - struct_specifier : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE | STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE - struct_declaration_list : struct_declaration | struct_declaration_list struct_declaration - struct_declaration : type_specifier struct_declarator_list SEMICOLON | type_qualifier type_specifier struct_declarator_list SEMICOLON - struct_declarator_list : struct_declarator | struct_declarator_list COMMA struct_declarator - struct_declarator : IDENTIFIER | IDENTIFIER array_specifier - initializer : assignment_expression | LEFT_BRACE initializer_list RIGHT_BRACE | LEFT_BRACE initializer_list COMMA RIGHT_BRACE - initializer_list : initializer | initializer_list COMMA initializer - declaration_statement : declaration - statement : compound_statement | simple_statement - simple_statement : declaration_statement | expression_statement | selection_statement | switch_statement | case_label | iteration_statement | jump_statement - compound_statement : LEFT_BRACE RIGHT_BRACE | LEFT_BRACE statement_list RIGHT_BRACE - statement_no_new_scope : compound_statement_no_new_scope | simple_statement - compound_statement_no_new_scope : LEFT_BRACE RIGHT_BRACE | LEFT_BRACE statement_list RIGHT_BRACE - statement_list : statement | statement_list statement - expression_statement : SEMICOLON | expression SEMICOLON - selection_statement : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement - selection_rest_statement : statement ELSE statement | statement - condition : expression | fully_specified_type IDENTIFIER EQUAL initializer - switch_statement : SWITCH LEFT_PAREN expression RIGHT_PAREN LEFT_BRACE switch_statement_list | RIGHT_BRACE - switch_statement_list : statement_list - case_label : CASE expression COLON | DEFAULT COLON - iteration_statement : WHILE LEFT_PAREN condition RIGHT_PAREN statement_no_new_scope | DO statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope - for_init_statement : expression_statement | declaration_statement - conditionopt : condition - for_rest_statement : conditionopt SEMICOLON | conditionopt SEMICOLON expression - jump_statement : CONTINUE SEMICOLON | BREAK SEMICOLON | RETURN SEMICOLON | RETURN expression SEMICOLON | DISCARD SEMICOLON - translation_unit : external_declaration | translation_unit external_declaration - external_declaration : function_definition | declaration | SEMICOLON - function_definition : function_prototype compound_statement_no_new_scope - """; + public static GlslTree parse(String input) throws GlslSyntaxException { + return parse(GlslLexer.createTokens(input)); + } public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxException { GlslTokenReader reader = new GlslTokenReader(tokens); @@ -130,8 +48,14 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio } } + List directives = new ArrayList<>(); List body = new ArrayList<>(); while (reader.canRead()) { + if (reader.tryConsume(GlslLexer.TokenType.DIRECTIVE)) { + directives.add(reader.peek(-1).value()); + continue; + } + GlslFunctionNode functionDefinition = parseFunctionDefinition(reader); if (functionDefinition != null) { body.add(functionDefinition); @@ -148,10 +72,45 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio continue; } - throw reader.error("Failed"); + reader.throwError(); } - return new GlslTree(version, body); + return new GlslTree(version, body, directives); + } + + public static GlslNode parseExpression(String input) throws GlslSyntaxException { + return parseExpression(GlslLexer.createTokens(input)); + } + + public static GlslNode parseExpression(GlslLexer.Token[] tokens) throws GlslSyntaxException { + GlslTokenReader reader = new GlslTokenReader(tokens); + GlslNode expression = parseConditionalExpression(reader); + if (expression == null) { + reader.throwError(); + } + while (reader.canRead()) { + if (reader.peek().type() != GlslLexer.TokenType.SEMICOLON) { + break; + } + reader.skip(); + } + if (reader.canRead()) { + throw reader.error("Too many tokens provided"); + } + return expression; + } + + public static List parseExpressionList(String input) throws GlslSyntaxException { + return parseExpressionList(GlslLexer.createTokens(input)); + } + + public static List parseExpressionList(GlslLexer.Token[] tokens) throws GlslSyntaxException { + GlslTokenReader reader = new GlslTokenReader(tokens); + List expressions = parseStatementList(reader); + if (reader.canRead()) { + throw reader.error("Too many tokens provided"); + } + return expressions; } private static @Nullable GlslNode parsePrimaryExpression(GlslTokenReader reader) { @@ -227,14 +186,19 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio if (reader.tryConsume(GlslLexer.TokenType.LEFT_BRACKET)) { GlslNode integerExpression = parseIntegerExpression(reader); if (integerExpression != null && reader.tryConsume(GlslLexer.TokenType.RIGHT_BRACKET)) { - return new GlslArrayNode(functionCall, integerExpression); + functionCall = new GlslArrayNode(functionCall, integerExpression); + functionCursor = reader.getCursor(); } } reader.setCursor(functionCursor); // function_call DOT FIELD_SELECTION if (reader.tryConsume(GlslLexer.TokenType.DOT, GlslLexer.TokenType.IDENTIFIER)) { - return new GlslFieldNode(functionCall, reader.peek(-1).value()); + StringBuilder fieldSelection = new StringBuilder(reader.peek(-1).value()); + while (reader.tryConsume(GlslLexer.TokenType.DOT, GlslLexer.TokenType.IDENTIFIER)) { + fieldSelection.append('.').append(reader.peek(-1).value()); + } + return new GlslFieldNode(functionCall, fieldSelection.toString()); } reader.setCursor(functionCursor); @@ -263,14 +227,19 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio if (reader.tryConsume(GlslLexer.TokenType.LEFT_BRACKET)) { GlslNode integerExpression = parseIntegerExpression(reader); if (integerExpression != null && reader.tryConsume(GlslLexer.TokenType.RIGHT_BRACKET)) { - return new GlslArrayNode(primaryExpression, integerExpression); + primaryExpression = new GlslArrayNode(primaryExpression, integerExpression); + expressionCursor = reader.getCursor(); } } reader.setCursor(expressionCursor); // primary_expression DOT FIELD_SELECTION if (reader.tryConsume(GlslLexer.TokenType.DOT, GlslLexer.TokenType.IDENTIFIER)) { - return new GlslFieldNode(primaryExpression, reader.peek(-1).value()); + StringBuilder fieldSelection = new StringBuilder(reader.peek(-1).value()); + while (reader.tryConsume(GlslLexer.TokenType.DOT, GlslLexer.TokenType.IDENTIFIER)) { + fieldSelection.append('.').append(reader.peek(-1).value()); + } + return new GlslFieldNode(primaryExpression, fieldSelection.toString()); } reader.setCursor(expressionCursor); // primary_expression INC_OP @@ -293,7 +262,7 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio } private static @Nullable GlslNode parseIntegerExpression(GlslTokenReader reader) { - return parseCondition(reader); + return parseExpression(reader); } private static @Nullable GlslNode parseFunctionCallGeneric(GlslTokenReader reader) { @@ -339,6 +308,7 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio return new GlslInvokeFunctionNode(functionCallHeader, Collections.emptyList()); } + reader.markError("Expected ')'"); reader.setCursor(cursor); return null; } @@ -393,6 +363,7 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio if (reader.canRead()) { GlslUnaryNode.Operand operator = reader.peek().type().asUnaryOperator(); if (operator != null) { + reader.skip(); GlslNode right = parseUnaryExpression(reader); if (right != null) { return new GlslUnaryNode(right, operator); @@ -799,40 +770,80 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio if (reader.tryConsume(GlslLexer.TokenType.IDENTIFIER, GlslLexer.TokenType.LEFT_BRACE)) { String identifier = reader.peek(-2).value(); - GlslStructSpecifier structDeclaration = parseStructDeclaration(reader); - if (structDeclaration != null && reader.tryConsume(GlslLexer.TokenType.RIGHT_BRACE)) { - // type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE SEMICOLON - if (reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { - // SUCCESS - } - - if (reader.tryConsume(GlslLexer.TokenType.IDENTIFIER)) { - String label = reader.peek(-1).value(); + List structFields = parseStructDeclarationList(reader); + if (structFields != null) { + if (reader.tryConsume(GlslLexer.TokenType.RIGHT_BRACE)) { + GlslSpecifiedType structSpecifier = new GlslSpecifiedType(new GlslStructSpecifier(identifier, structFields), typeQualifier); - // type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON + // type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE SEMICOLON if (reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { - // SUCCESS + return new GlslStructNode(structSpecifier); } - // type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER array_specifier SEMICOLON - GlslTypeSpecifier arraySpecifier = parseArraySpecifier(reader, structDeclaration); - if (arraySpecifier != null && reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { - // SUCCESS + if (reader.tryConsume(GlslLexer.TokenType.IDENTIFIER)) { + String label = reader.peek(-1).value(); + + // type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON + if (reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { + return new GlslNewNode(structSpecifier, label, null); + } + + // type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER array_specifier SEMICOLON + GlslSpecifiedType arraySpecifier = parseArraySpecifier(reader, structSpecifier); + if (arraySpecifier != null && reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { + return new GlslNewNode(arraySpecifier, label, null); + } } } + reader.markError("Expected '}'"); } } reader.setCursor(cursor); // type_qualifier SEMICOLON if (reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { - // FIXME struct declaration + return new GlslDeclaration(typeQualifier, Collections.emptyList()); } // type_qualifier IDENTIFIER SEMICOLON // type_qualifier IDENTIFIER identifier_list SEMICOLON + List identifiers = parseIdentifierList(reader); + if (identifiers == null) { + reader.markError("Expected ';'"); + reader.setCursor(cursor); + return null; + } + + if (!reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { + reader.markError("Expected ';'"); + reader.setCursor(cursor); + return null; + } + + return new GlslDeclaration(typeQualifier, identifiers); + } + + private static @Nullable List parseIdentifierList(GlslTokenReader reader) { + List identifiers = new ArrayList<>(); + int cursor = reader.getCursor(); + while (reader.canRead()) { + if (!reader.tryConsume(GlslLexer.TokenType.IDENTIFIER)) { + reader.setCursor(cursor); + break; + } + + identifiers.add(reader.peek(-1).value()); + cursor = reader.getCursor(); + if (!reader.tryConsume(GlslLexer.TokenType.COMMA)) { + break; + } + } - return null; // FIXME + if (identifiers.isEmpty()) { + return null; + } + + return identifiers; } private static @Nullable GlslFunctionHeader parseFunctionPrototype(GlslTokenReader reader) { @@ -877,12 +888,6 @@ public static GlslTree parse(GlslLexer.Token[] tokens) throws GlslSyntaxExceptio return null; } -// private static @Nullable GlslNode parseFunctionDeclarator(GlslTokenReader reader) { -// // function_header -// // function_header_with_parameters -// return null; // TODO -// } - private static List parseParameterList(GlslTokenReader reader) { List parameters = new ArrayList<>(); int cursor = reader.getCursor(); @@ -1009,12 +1014,12 @@ private static List parseParameterList(GlslTokenReader int cursor = reader.getCursor(); GlslSpecifiedType fullySpecifiedType = parseFullySpecifiedType(reader); if (fullySpecifiedType == null) { - return null; // TODO + return null; } if (!reader.tryConsume(GlslLexer.TokenType.IDENTIFIER)) { reader.setCursor(cursor); - return null; // TODO + return null; } cursor = reader.getCursor(); @@ -1117,7 +1122,7 @@ private static List parseParameterList(GlslTokenReader qualifier = GlslTypeQualifier.identifierLayoutId(identifier, expression); } - if (qualifier != null && reader.tryConsume(GlslLexer.TokenType.SHARED)) { + if (qualifier == null && reader.tryConsume(GlslLexer.TokenType.SHARED)) { qualifier = GlslTypeQualifier.sharedLayoutId(); } @@ -1133,6 +1138,7 @@ private static List parseParameterList(GlslTokenReader // RIGHT_PAREN if (!reader.tryConsume(GlslLexer.TokenType.RIGHT_PAREN)) { + reader.markError("Expected ')'"); reader.setCursor(layoutCursor); return null; } @@ -1194,13 +1200,14 @@ private static List parseParameterList(GlslTokenReader private static @Nullable GlslTypeQualifier parseStorageQualifier(GlslTokenReader reader) { GlslTypeQualifier.StorageType storageQualifier = reader.peek().type().asStorageQualifier(); - if (storageQualifier == null) { - return null; + if (storageQualifier != null) { + reader.skip(); + return storageQualifier; } - reader.skip(); // SUBROUTINE LEFT_PAREN type_name_list RIGHT_PAREN - if (storageQualifier == GlslTypeQualifier.StorageType.SUBROUTINE) { + int cursor = reader.getCursor(); + if (reader.tryConsume(GlslLexer.TokenType.SUBROUTINE)) { if (reader.tryConsume(GlslLexer.TokenType.LEFT_PAREN)) { List typeNames = new ArrayList<>(); while (reader.canRead()) { @@ -1213,12 +1220,18 @@ private static List parseParameterList(GlslTokenReader break; } } + if (!reader.tryConsume(GlslLexer.TokenType.RIGHT_PAREN)) { + reader.markError("Expected ')'"); + reader.setCursor(cursor); + return null; + } return GlslTypeQualifier.storage(typeNames.toArray(String[]::new)); } return GlslTypeQualifier.storage(new String[0]); } - return GlslTypeQualifier.storage(storageQualifier); + reader.setCursor(cursor); + return null; } private static @Nullable GlslNode parseTypeNameList(GlslTokenReader reader) { @@ -1316,31 +1329,119 @@ private static List parseParameterList(GlslTokenReader private static @Nullable GlslStructSpecifier parseStructSpecifier(GlslTokenReader reader) { // STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE // STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE - return null; // TODO + + int cursor = reader.getCursor(); + if (!reader.tryConsume(GlslLexer.TokenType.STRUCT)) { + return null; + } + + String name = null; + if (reader.tryConsume(GlslLexer.TokenType.IDENTIFIER)) { + name = reader.peek(-1).value(); + } + + if (!reader.tryConsume(GlslLexer.TokenType.LEFT_BRACE)) { + reader.setCursor(cursor); + return null; + } + + List fields = parseStructDeclarationList(reader); + if (fields == null) { + return null; + } + + if (!reader.tryConsume(GlslLexer.TokenType.RIGHT_BRACE)) { + reader.markError("Expected '}'"); + reader.setCursor(cursor); + return null; + } + + return new GlslStructSpecifier(name, fields); } - private static @Nullable GlslNode parseStructDeclarationList(GlslTokenReader reader) { + private static @Nullable List parseStructDeclarationList(GlslTokenReader reader) { // struct_declaration // struct_declaration_list struct_declaration - return null; // TODO + + List declarations = new ArrayList<>(); + while (reader.canRead()) { + List fields = parseStructDeclaration(reader); + if (fields == null) { + break; + } + + declarations.addAll(fields); + } + + if (declarations.isEmpty()) { + return null; + } + + return declarations; } - private static @Nullable GlslStructSpecifier parseStructDeclaration(GlslTokenReader reader) { + private static @Nullable List parseStructDeclaration(GlslTokenReader reader) { // type_specifier struct_declarator_list SEMICOLON // type_qualifier type_specifier struct_declarator_list SEMICOLON - return null; // TODO + + int cursor = reader.getCursor(); + GlslSpecifiedType fullySpecifiedType = parseFullySpecifiedType(reader); + if (fullySpecifiedType == null) { + return null; + } + + List structDeclaration = parseStructDeclaratorList(fullySpecifiedType, reader); + if (structDeclaration == null) { + return null; + } + + if (!reader.tryConsume(GlslLexer.TokenType.SEMICOLON)) { + reader.markError("Expected ';'"); + reader.setCursor(cursor); + return null; + } + + return structDeclaration; } - private static @Nullable GlslNode parseStructDeclaratorList(GlslTokenReader reader) { + private static @Nullable List parseStructDeclaratorList(GlslSpecifiedType type, GlslTokenReader reader) { // struct_declarator // struct_declarator_list COMMA struct_declarator - return null; // TODO + + int cursor = reader.getCursor(); + List fields = new ArrayList<>(); + while (reader.canRead()) { + GlslStructField field = parseStructDeclarator(type, reader); + if (field == null) { + reader.setCursor(cursor); + break; + } + + fields.add(field); + cursor = reader.getCursor(); + + if (!reader.tryConsume(GlslLexer.TokenType.COMMA)) { + break; + } + } + + if (fields.isEmpty()) { + return null; + } + + return fields; } - private static @Nullable GlslNode parseStructDeclarator(GlslTokenReader reader) { + private static @Nullable GlslStructField parseStructDeclarator(GlslSpecifiedType type, GlslTokenReader reader) { + if (!reader.tryConsume(GlslLexer.TokenType.IDENTIFIER)) { + return null; + } + // IDENTIFIER // IDENTIFIER array_specifier - return null; // TODO + String name = reader.peek(-1).value(); + GlslSpecifiedType arraySpecifier = parseArraySpecifier(reader, type); + return new GlslStructField(Objects.requireNonNullElse(arraySpecifier, type), name); } private static @Nullable GlslNode parseInitializer(GlslTokenReader reader) { @@ -1519,6 +1620,7 @@ private static List parseInitializerList(GlslTokenReader reader) { List statements = parseStatementList(reader); if (!reader.tryConsume(GlslLexer.TokenType.RIGHT_BRACE)) { + reader.markError("Expected '}'"); reader.setCursor(cursor); return null; } @@ -1558,19 +1660,25 @@ private static List parseStatementList(GlslTokenReader reader) { // IF LEFT_PAREN condition RIGHT_PAREN statement ELSE statement // IF LEFT_PAREN condition RIGHT_PAREN statement + if (!reader.tryConsume(GlslLexer.TokenType.IF)) { + return null; + } + int cursor = reader.getCursor(); - if (!reader.tryConsume(GlslLexer.TokenType.IF, GlslLexer.TokenType.LEFT_PAREN)) { + if (!reader.tryConsume(GlslLexer.TokenType.LEFT_PAREN)) { + reader.markError("Expected '('"); reader.setCursor(cursor); return null; } - GlslNode expression = parseExpressionStatement(reader); + GlslNode expression = parseCondition(reader); if (expression == null) { reader.setCursor(cursor); return null; } if (!reader.tryConsume(GlslLexer.TokenType.RIGHT_PAREN)) { + reader.markError("Expected ')'"); reader.setCursor(cursor); return null; } @@ -1596,7 +1704,7 @@ private static List parseStatementList(GlslTokenReader reader) { } reader.setCursor(cursor); - return new GlslSelectionNode(expression, statement, null); + return new GlslSelectionNode(expression, statement, GlslEmptyNode.INSTANCE); } private static @Nullable GlslNode parseCondition(GlslTokenReader reader) { diff --git a/common/src/main/java/foundry/veil/impl/glsl/GlslTokenReader.java b/common/src/main/java/foundry/veil/impl/glsl/GlslTokenReader.java index 738307c2..7a29c6cf 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/GlslTokenReader.java +++ b/common/src/main/java/foundry/veil/impl/glsl/GlslTokenReader.java @@ -10,8 +10,8 @@ public class GlslTokenReader { private final GlslLexer.Token[] tokens; private int cursor; - private final List errors; - private final List errorsView; + private final List errors; + private final List errorsView; public GlslTokenReader(GlslLexer.Token[] tokens) { this.tokens = tokens; @@ -20,9 +20,9 @@ public GlslTokenReader(GlslLexer.Token[] tokens) { this.errorsView = Collections.unmodifiableList(this.errors); } - private int getCursorOffset() { + public int getCursorOffset(int cursor) { int offset = -1; - for (int i = 0; i <= Math.min(this.cursor, this.tokens.length - 1); i++) { + for (int i = 0; i <= Math.min(cursor, this.tokens.length - 1); i++) { offset += this.tokens[i].value().length() + 1; } return offset; @@ -83,7 +83,19 @@ public boolean tryConsume(GlslLexer.TokenType... tokens) { } public GlslSyntaxException error(String error) { - return new GlslSyntaxException(error, this.getString(), this.getCursorOffset()); + return new GlslSyntaxException(error, this.getString(), this.getCursorOffset(this.cursor)); + } + + public void throwError() throws GlslSyntaxException { + if (this.errors.isEmpty()) { + return; + } + + GlslSyntaxException exception = new GlslSyntaxException("Failed", this.getString(), this.getCursorOffset(this.cursor)); + for (GlslSyntaxException error : this.errors) { + exception.addSuppressed(error); + } + throw exception; } public void skip() { @@ -95,13 +107,13 @@ public void skip(int amount) { } public void markError(String message) { - this.errors.add(new Error(this.cursor, message)); + this.errors.add(new GlslSyntaxException(message, this.getString(), this.getCursorOffset(this.cursor))); } /** * @return All errors marked from reading tokens */ - public List getErrors() { + public List getErrors() { return this.errorsView; } diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslSpecifiedType.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslSpecifiedType.java index a4d26e7f..9761756c 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslSpecifiedType.java +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslSpecifiedType.java @@ -44,6 +44,7 @@ public List getQualifiers() { /** * Sets the operand of this + * * @param specifier * @return */ @@ -73,6 +74,10 @@ public String getSourceString() { return builder.toString(); } + public String getPostSourceString() { + return this.specifier.getPostSourceString(); + } + @Override public String toString() { return "GlslSpecifiedType[specifier=" + this.specifier + ", qualifiers=" + this.qualifiers; diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructField.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructField.java new file mode 100644 index 00000000..68b2ac3f --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructField.java @@ -0,0 +1,34 @@ +package foundry.veil.impl.glsl.grammar; + +public class GlslStructField { + + private GlslSpecifiedType type; + private String name; + + public GlslStructField(GlslType type, String name) { + this.type = type.asSpecifiedType(); + this.name = name; + } + + public GlslSpecifiedType getType() { + return this.type; + } + + public String getName() { + return this.name; + } + + public GlslStructField setType(GlslSpecifiedType type) { + this.type = type; + return this; + } + + public GlslStructField setName(String name) { + this.name = name; + return this; + } + + public String getSourceString() { + return this.type.getSourceString() + " " + this.name + this.type.getPostSourceString(); + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructSpecifier.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructSpecifier.java index 6e63e627..24a44b58 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructSpecifier.java +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslStructSpecifier.java @@ -1,10 +1,45 @@ package foundry.veil.impl.glsl.grammar; -// TODO -public record GlslStructSpecifier() implements GlslTypeSpecifier { +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public final class GlslStructSpecifier implements GlslTypeSpecifier { + + private String name; + private final List fields; + + public GlslStructSpecifier(String name, Collection fields) { + this.name = name; + this.fields = new ArrayList<>(fields); + } + + public String getName() { + return this.name; + } + + public List getFields() { + return this.fields; + } + + public GlslStructSpecifier setName(String name) { + this.name = name; + return this; + } @Override public String getSourceString() { - return "TODO STRUCT"; + StringBuilder builder = new StringBuilder(); + builder.append(this.name).append(" {\n"); + for (GlslStructField field : this.fields) { + builder.append('\t').append(field.getSourceString().replaceAll("\n", "\n\t")).append(";\n"); + } + builder.append('}'); + return builder.toString(); + } + + @Override + public String toString() { + return "GlslStructSpecifier{name=" + this.name + '}'; } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeQualifier.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeQualifier.java index 25e85979..890ccca8 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeQualifier.java +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeQualifier.java @@ -10,15 +10,8 @@ public sealed interface GlslTypeQualifier { String getSourceString(); - static GlslTypeQualifier storage(Storage.StorageType storageType) { - if (storageType == StorageType.SUBROUTINE) { - throw new IllegalArgumentException("Subroutine storage must specify operand names"); - } - return new Storage(storageType, null); - } - static GlslTypeQualifier storage(String[] typeNames) { - return new Storage(Storage.StorageType.SUBROUTINE, typeNames); + return new StorageSubroutine(typeNames); } static Layout layout(LayoutId... ids) { @@ -34,25 +27,24 @@ static LayoutId sharedLayoutId() { } /** - * A storage qualifier for a operand. + * A storage qualifier for a subroutine operand. * - * @param storageType The operand of storage qualifier - * @param typeNames The operand names for subroutines. null if {@link #storageType} is not SUBROUTINE + * @param typeNames The operand names for subroutines * @author Ocelot */ - record Storage(StorageType storageType, @Nullable String[] typeNames) implements GlslTypeQualifier { + record StorageSubroutine(String[] typeNames) implements GlslTypeQualifier { @Override public String toString() { - return this.storageType == StorageType.SUBROUTINE ? "Storage[operand=SUBROUTINE, typeNames=" + Arrays.toString(this.typeNames) + "]" : "Storage[operand=" + this.storageType + ']'; + return "Storage[operand=SUBROUTINE, typeNames=" + Arrays.toString(this.typeNames) + "]"; } @Override public String getSourceString() { - if (this.typeNames != null && this.typeNames.length > 0) { + if (this.typeNames.length > 0) { return "subroutine(" + String.join(",", this.typeNames) + ")"; } - return this.storageType.name().toLowerCase(Locale.ROOT); + return "subroutine"; } } @@ -67,12 +59,12 @@ public String getSourceString() { builder.append(layoutId.identifier()); GlslNode expression = layoutId.expression(); if (expression != null) { - builder.append('=').append(expression.getSourceString()); + builder.append(" = ").append(expression.getSourceString()); } - builder.append(" "); + builder.append(", "); } } - builder.deleteCharAt(builder.length() - 1); + builder.delete(builder.length() - 2, builder.length()); return "layout(" + builder + ")"; } } @@ -84,7 +76,7 @@ public boolean shared() { } } - enum StorageType { + enum StorageType implements GlslTypeQualifier { CONST, IN, OUT, @@ -99,8 +91,12 @@ enum StorageType { VOLATILE, RESTRICT, READONLY, - WRITEONLY, - SUBROUTINE + WRITEONLY; + + @Override + public String getSourceString() { + return this.name().toLowerCase(Locale.ROOT); + } } enum Precision implements GlslTypeQualifier { diff --git a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeSpecifier.java b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeSpecifier.java index 85ebd09a..b2fff378 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeSpecifier.java +++ b/common/src/main/java/foundry/veil/impl/glsl/grammar/GlslTypeSpecifier.java @@ -3,12 +3,14 @@ import foundry.veil.impl.glsl.node.GlslNode; import org.jetbrains.annotations.Nullable; -import java.util.Locale; - -public sealed interface GlslTypeSpecifier extends GlslType permits GlslStructSpecifier, GlslTypeSpecifier.Array, GlslTypeSpecifier.BuiltinType, GlslTypeSpecifier.Name { +public sealed interface GlslTypeSpecifier extends GlslType permits GlslStructSpecifier, GlslTypeSpecifier.Array, GlslTypeSpecifier.BuiltinType, GlslTypeSpecifier.Name, GlslTypeSpecifier.Struct { String getSourceString(); + default String getPostSourceString() { + return ""; + } + default boolean isNamed() { return this instanceof Name; } @@ -36,7 +38,12 @@ public String getSourceString() { record Array(GlslTypeSpecifier specifier, @Nullable GlslNode size) implements GlslTypeSpecifier { @Override public String getSourceString() { - return this.specifier.getSourceString() + (this.size != null ? "[" + this.size.getSourceString() + "]" : "[]"); + return this.specifier.getSourceString(); + } + + @Override + public String getPostSourceString() { + return this.size != null ? "[" + this.size.getSourceString() + "]" : "[]"; } @Override @@ -45,130 +52,148 @@ public boolean isNamed() { } } + record Struct(GlslStructSpecifier structSpecifier) implements GlslTypeSpecifier { + @Override + public String getSourceString() { + return this.structSpecifier.getSourceString(); + } + + @Override + public boolean isNamed() { + return false; + } + } + enum BuiltinType implements GlslTypeSpecifier { - VOID, - FLOAT, - DOUBLE, - INT, - UINT, - BOOL, - VEC2, - VEC3, - VEC4, - DVEC2, - DVEC3, - DVEC4, - BVEC2, - BVEC3, - BVEC4, - IVEC2, - IVEC3, - IVEC4, - UVEC2, - UVEC3, - UVEC4, - MAT2, - MAT3, - MAT4, - MAT2X2, - MAT2X3, - MAT2X4, - MAT3X2, - MAT3X3, - MAT3X4, - MAT4X2, - MAT4X3, - MAT4X4, - DMAT2, - DMAT3, - DMAT4, - DMAT2X2, - DMAT2X3, - DMAT2X4, - DMAT3X2, - DMAT3X3, - DMAT3X4, - DMAT4X2, - DMAT4X3, - DMAT4X4, - ATOMIC_UINT, - SAMPLER2D, - SAMPLER3D, - SAMPLERCUBE, - SAMPLER2DSHADOW, - SAMPLERCUBESHADOW, - SAMPLER2DARRAY, - SAMPLER2DARRAYSHADOW, - SAMPLERCUBEARRAY, - SAMPLERCUBEARRAYSHADOW, - ISAMPLER2D, - ISAMPLER3D, - ISAMPLERCUBE, - ISAMPLER2DARRAY, - ISAMPLERCUBEARRAY, - USAMPLER2D, - USAMPLER3D, - USAMPLERCUBE, - USAMPLER2DARRAY, - USAMPLERCUBEARRAY, - SAMPLER1D, - SAMPLER1DSHADOW, - SAMPLER1DARRAY, - SAMPLER1DARRAYSHADOW, - ISAMPLER1D, - ISAMPLER1DARRAY, - USAMPLER1D, - USAMPLER1DARRAY, - SAMPLER2DRECT, - SAMPLER2DRECTSHADOW, - ISAMPLER2DRECT, - USAMPLER2DRECT, - SAMPLERBUFFER, - ISAMPLERBUFFER, - USAMPLERBUFFER, - SAMPLER2DMS, - ISAMPLER2DMS, - USAMPLER2DMS, - SAMPLER2DMSARRAY, - ISAMPLER2DMSARRAY, - USAMPLER2DMSARRAY, - IMAGE2D, - IIMAGE2D, - UIMAGE2D, - IMAGE3D, - IIMAGE3D, - UIMAGE3D, - IMAGECUBE, - IIMAGECUBE, - UIMAGECUBE, - IMAGEBUFFER, - IIMAGEBUFFER, - UIMAGEBUFFER, - IMAGE1D, - IIMAGE1D, - UIMAGE1D, - IMAGE1DARRAY, - IIMAGE1DARRAY, - UIMAGE1DARRAY, - IMAGE2DRECT, - IIMAGE2DRECT, - UIMAGE2DRECT, - IMAGE2DARRAY, - IIMAGE2DARRAY, - UIMAGE2DARRAY, - IMAGECUBEARRAY, - IIMAGECUBEARRAY, - UIMAGECUBEARRAY, - IMAGE2DMS, - IIMAGE2DMS, - UIMAGE2DMS, - IMAGE2DMSARRAY, - IIMAGE2DMSARRAY, - UIMAGE2DMSARRAY; + VOID("void"), + FLOAT("float"), + DOUBLE("double"), + INT("int"), + UINT("uint"), + BOOL("bool"), + VEC2("vec2"), + VEC3("vec3"), + VEC4("vec4"), + DVEC2("dvec2"), + DVEC3("dvec3"), + DVEC4("dvec4"), + BVEC2("bvec2"), + BVEC3("bvec3"), + BVEC4("bvec4"), + IVEC2("ivec2"), + IVEC3("ivec3"), + IVEC4("ivec4"), + UVEC2("uvec2"), + UVEC3("uvec3"), + UVEC4("uvec4"), + MAT2("mat2"), + MAT3("mat3"), + MAT4("mat4"), + MAT2X2("mat2x2"), + MAT2X3("mat2x3"), + MAT2X4("mat2x4"), + MAT3X2("mat3x2"), + MAT3X3("mat3x3"), + MAT3X4("mat3x4"), + MAT4X2("mat4x2"), + MAT4X3("mat4x3"), + MAT4X4("mat4x4"), + DMAT2("dmat2"), + DMAT3("dmat3"), + DMAT4("dmat4"), + DMAT2X2("dmat2x2"), + DMAT2X3("dmat2x3"), + DMAT2X4("dmat2x4"), + DMAT3X2("dmat3x2"), + DMAT3X3("dmat3x3"), + DMAT3X4("dmat3x4"), + DMAT4X2("dmat4x2"), + DMAT4X3("dmat4x3"), + DMAT4X4("dmat4x4"), + ATOMIC_UINT("atomic_uint"), + SAMPLER2D("sampler2D"), + SAMPLER3D("sampler3D"), + SAMPLERCUBE("samplerCube"), + SAMPLER2DSHADOW("sampler2DShadow"), + SAMPLERCUBESHADOW("samplerCubeShadow"), + SAMPLER2DARRAY("sampler2DArray"), + SAMPLER2DARRAYSHADOW("sampler2DArrayShadow"), + SAMPLERCUBEARRAY("samplerCubeArray"), + SAMPLERCUBEARRAYSHADOW("samplerCubeArrayShadow"), + ISAMPLER2D("isampler2D"), + ISAMPLER3D("isampler3D"), + ISAMPLERCUBE("isamplerCube"), + ISAMPLER2DARRAY("isampler2DArray"), + ISAMPLERCUBEARRAY("isamplerCubeArray"), + USAMPLER2D("usampler2D"), + USAMPLER3D("usampler3D"), + USAMPLERCUBE("usamplerCube"), + USAMPLER2DARRAY("usampler2DArray"), + USAMPLERCUBEARRAY("usamplerCubeArray"), + SAMPLER1D("sampler1D"), + SAMPLER1DSHADOW("sampler1DShadow"), + SAMPLER1DARRAY("sampler1DArray"), + SAMPLER1DARRAYSHADOW("sampler1DArrayShadow"), + ISAMPLER1D("isampler1D"), + ISAMPLER1DARRAY("isampler1DArray"), + USAMPLER1D("usampler1D"), + USAMPLER1DARRAY("usampler1DArray"), + SAMPLER2DRECT("sampler2DRect"), + SAMPLER2DRECTSHADOW("sampler2DRectShadow"), + ISAMPLER2DRECT("isampler2DRect"), + USAMPLER2DRECT("usampler2DRect"), + SAMPLERBUFFER("samplerBuffer"), + ISAMPLERBUFFER("isamplerBuffer"), + USAMPLERBUFFER("usamplerBuffer"), + SAMPLER2DMS("sampler2DMS"), + ISAMPLER2DMS("isampler2DMS"), + USAMPLER2DMS("usampler2DMS"), + SAMPLER2DMSARRAY("sampler2DMSArray"), + ISAMPLER2DMSARRAY("isampler2DMSArray"), + USAMPLER2DMSARRAY("usampler2DMSArray"), + IMAGE2D("image2D"), + IIMAGE2D("iimage2D"), + UIMAGE2D("uimage2D"), + IMAGE3D("image3D"), + IIMAGE3D("iimage3D"), + UIMAGE3D("uimage3D"), + IMAGECUBE("imageCube"), + IIMAGECUBE("iimageCube"), + UIMAGECUBE("uimageCube"), + IMAGEBUFFER("imageBuffer"), + IIMAGEBUFFER("iimageBuffer"), + UIMAGEBUFFER("uimageBuffer"), + IMAGE1D("image1D"), + IIMAGE1D("iimage1D"), + UIMAGE1D("uimage1D"), + IMAGE1DARRAY("image1DArray"), + IIMAGE1DARRAY("iimage1DArray"), + UIMAGE1DARRAY("uimage1DArray"), + IMAGE2DRECT("image2DRect"), + IIMAGE2DRECT("iimage2DRect"), + UIMAGE2DRECT("uimage2DRect"), + IMAGE2DARRAY("image2DArray"), + IIMAGE2DARRAY("iimage2DArray"), + UIMAGE2DARRAY("uimage2DArray"), + IMAGECUBEARRAY("imageCubeArray"), + IIMAGECUBEARRAY("iimageCubeArray"), + UIMAGECUBEARRAY("uimageCubeArray"), + IMAGE2DMS("image2DMS"), + IIMAGE2DMS("iimage2DMS"), + UIMAGE2DMS("uimage2DMS"), + IMAGE2DMSARRAY("image2DMSArray"), + IIMAGE2DMSARRAY("iimage2DMSArray"), + UIMAGE2DMSARRAY("uimage2DMSArray"); + + private final String source; + + BuiltinType(String source) { + this.source = source; + } @Override public String getSourceString() { - return this.name().toLowerCase(Locale.ROOT); + return this.source; } } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslCompoundNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslCompoundNode.java index c31d639c..b28ef0cd 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/GlslCompoundNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslCompoundNode.java @@ -1,7 +1,5 @@ package foundry.veil.impl.glsl.node; -import foundry.veil.impl.glsl.visitor.GlslNodeVisitor; - import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -20,13 +18,6 @@ public List toList() { return new ArrayList<>(this.children); } - @Override - public void visit(GlslNodeVisitor visitor) { - for (GlslNode child : this.children) { - child.visit(visitor); - } - } - public List getChildren() { return this.children; } @@ -45,11 +36,11 @@ public GlslCompoundNode setChildren(GlslNode... children) { @Override public String getSourceString() { - StringBuilder builder = new StringBuilder(); + StringBuilder builder = new StringBuilder("{\n"); for (GlslNode child : this.children) { - builder.append(child.getSourceString()).append('\n'); + builder.append('\t').append(child.getSourceString().replaceAll("\n", "\n\t")).append(";\n"); } - builder.deleteCharAt(builder.length() - 1); + builder.append('}'); return builder.toString(); } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslEmptyNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslEmptyNode.java index 13f455e0..db2c8879 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/GlslEmptyNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslEmptyNode.java @@ -1,7 +1,5 @@ package foundry.veil.impl.glsl.node; -import foundry.veil.impl.glsl.visitor.GlslNodeVisitor; - import java.util.ArrayList; import java.util.List; @@ -18,7 +16,4 @@ public List toList() { return new ArrayList<>(); } - @Override - public void visit(GlslNodeVisitor visitor) { - } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslNode.java index 956ed8a4..13d41ea6 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/GlslNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslNode.java @@ -1,6 +1,9 @@ package foundry.veil.impl.glsl.node; -import foundry.veil.impl.glsl.visitor.GlslNodeVisitor; +import foundry.veil.impl.glsl.node.primary.GlslBoolConstantNode; +import foundry.veil.impl.glsl.node.primary.GlslFloatConstantNode; +import foundry.veil.impl.glsl.node.primary.GlslIntConstantNode; +import foundry.veil.impl.glsl.node.primary.GlslIntFormat; import java.util.*; @@ -8,10 +11,6 @@ public interface GlslNode { String getSourceString(); - default void visit(GlslNodeVisitor visitor) { - visitor.visitNode(this); - } - /** * @return A new list with the child contents of this node */ @@ -19,10 +18,20 @@ default List toList() { return new ArrayList<>(Collections.singleton(this)); } - static void visitAll(Collection nodes, GlslNodeVisitor visitor) { - for (GlslNode node : nodes) { - node.visit(visitor); - } + static GlslIntConstantNode intConstant(int value) { + return new GlslIntConstantNode(GlslIntFormat.DECIMAL, true, value); + } + + static GlslIntConstantNode unsignedIntConstant(int value) { + return new GlslIntConstantNode(GlslIntFormat.DECIMAL, false, value); + } + + static GlslFloatConstantNode floatConstant(float value) { + return new GlslFloatConstantNode(value); + } + + static GlslBoolConstantNode booleanConstant(boolean value) { + return new GlslBoolConstantNode(value); } static GlslNode compound(Collection nodes) { diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java index 4596775d..0314e6f6 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java @@ -1,44 +1,88 @@ package foundry.veil.impl.glsl.node; +import foundry.veil.impl.glsl.grammar.GlslStructSpecifier; import foundry.veil.impl.glsl.grammar.GlslVersion; import foundry.veil.impl.glsl.node.function.GlslFunctionNode; +import foundry.veil.impl.glsl.node.variable.GlslDeclaration; import foundry.veil.impl.glsl.node.variable.GlslNewNode; +import foundry.veil.impl.glsl.node.variable.GlslStructNode; import foundry.veil.impl.glsl.visitor.GlslFunctionVisitor; import foundry.veil.impl.glsl.visitor.GlslTreeVisitor; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.stream.Stream; public class GlslTree { private final GlslVersion version; private final List body; + private final List directives; - public GlslTree(GlslVersion version, Collection body) { + public GlslTree(GlslVersion version, Collection body, Collection directives) { this.version = version; this.body = new ArrayList<>(body); + this.directives = new ArrayList<>(directives); + } + + private void visit(GlslTreeVisitor visitor, GlslNode node) { + if (node instanceof GlslFunctionNode functionNode) { + GlslFunctionVisitor functionVisitor = visitor.visitFunction(functionNode); + if (functionVisitor != null) { + functionNode.visit(functionVisitor); + } + return; + } + if (node instanceof GlslNewNode newNode) { + visitor.visitField(newNode); + return; + } + if (node instanceof GlslStructNode struct) { + visitor.visitStruct(struct); + return; + } + if (node instanceof GlslDeclaration declaration) { + visitor.visitDeclaration(declaration); + return; + } + throw new AssertionError("Not Possible"); } public void visit(GlslTreeVisitor visitor) { visitor.visitVersion(this.version); - GlslNode.visitAll(this.body, node -> { - if (node instanceof GlslFunctionNode functionNode) { - GlslFunctionVisitor functionVisitor = visitor.visitFunction(functionNode); - if (functionVisitor != null) { - functionNode.visit(functionVisitor); - } - return; + for (String directive : this.directives) { + visitor.visitDirective(directive); + } + + for (GlslNode node : this.body) { + if (node instanceof GlslEmptyNode) { + continue; } - if(node instanceof GlslNewNode newNode) { - visitor.visitField(newNode); - return; + if (node instanceof GlslCompoundNode compoundNode) { + for (GlslNode child : compoundNode.getChildren()) { + this.visit(visitor, child); + } + continue; } - System.out.println(node); - }); + this.visit(visitor, node); + } + visitor.visitTreeEnd(); } + public Stream functions() { + return this.body.stream().filter(node -> node instanceof GlslFunctionNode).map(node -> (GlslFunctionNode) node); + } + + public Stream fields() { + return this.body.stream().filter(node -> node instanceof GlslNewNode).map(node -> (GlslNewNode) node); + } + + public void add(GlslNode node) { + this.body.add(node); + } + public GlslVersion getVersion() { return this.version; } @@ -47,6 +91,10 @@ public List getBody() { return this.body; } + public List getDirectives() { + return this.directives; + } + @Override public String toString() { return "GlslTree{version=" + this.version + ", body=" + this.body + '}'; diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/ForLoopNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/ForLoopNode.java index 4e123e6e..e9fadda1 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/branch/ForLoopNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/ForLoopNode.java @@ -4,6 +4,10 @@ import foundry.veil.impl.glsl.visitor.GlslTreeVisitor; import org.jetbrains.annotations.Nullable; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + /** * Represents for loops. * @@ -14,13 +18,13 @@ public class ForLoopNode implements GlslNode { private GlslNode init; private GlslNode condition; private GlslNode increment; - private GlslNode body; + private final List body; public ForLoopNode(GlslNode init, GlslNode condition, @Nullable GlslNode increment, GlslNode body) { this.init = init; this.condition = condition; this.increment = increment; - this.body = body; + this.body = body.toList(); } public GlslNode getInit() { @@ -35,24 +39,35 @@ public GlslNode getCondition() { return this.increment; } - public GlslNode getBody() { + public List getBody() { return this.body; } - public void setInit(GlslNode init) { + public ForLoopNode setInit(GlslNode init) { this.init = init; + return this; } - public void setCondition(GlslNode condition) { + public ForLoopNode setCondition(GlslNode condition) { this.condition = condition; + return this; } - public void setIncrement(GlslNode increment) { + public ForLoopNode setIncrement(@Nullable GlslNode increment) { this.increment = increment; + return this; + } + + public ForLoopNode setBody(Collection body) { + this.body.clear(); + this.body.addAll(body); + return this; } - public void setBody(GlslNode body) { - this.body = body; + public ForLoopNode setBody(GlslNode... body) { + this.body.clear(); + this.body.addAll(Arrays.asList(body)); + return this; } @Override @@ -63,11 +78,14 @@ public String toString() { @Override public String getSourceString() { StringBuilder builder = new StringBuilder(); - builder.append("for (").append(this.init.getSourceString()).append("; ").append(this.condition).append(';'); + builder.append("for (").append(this.init.getSourceString()).append("; ").append(this.condition.getSourceString()).append(';'); if (this.increment != null) { - builder.append(this.increment.getSourceString()); + builder.append(' ').append(this.increment.getSourceString()); + } + builder.append(") {\n"); + for (GlslNode node : this.body) { + builder.append('\t').append(node.getSourceString().replaceAll("\n", "\n\t")).append(";\n"); } - builder.append(") {\n").append(this.body.getSourceString().replaceAll("\n", "\n\t")); builder.append('}'); return builder.toString(); } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSelectionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSelectionNode.java index c0652174..3ffc0f59 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSelectionNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSelectionNode.java @@ -3,25 +3,78 @@ import foundry.veil.impl.glsl.node.GlslNode; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + /** * if/else * - * @param expression - * @param first - * @param branch * @author Ocelot */ -public record GlslSelectionNode(GlslNode expression, GlslNode first, @Nullable GlslNode branch) implements GlslNode { +public final class GlslSelectionNode implements GlslNode { + + private GlslNode expression; + private final List first; + private final List second; + + public GlslSelectionNode(GlslNode expression, GlslNode first, GlslNode second) { + this.expression = expression; + this.first = first.toList(); + this.second = second.toList(); + } + + public GlslNode getExpression() { + return this.expression; + } + + public List getFirst() { + return this.first; + } + + public List getSecond() { + return this.second; + } + + public void setExpression(GlslNode expression) { + this.expression = expression; + } + + public GlslSelectionNode setFirst(Collection first) { + this.first.clear(); + this.first.addAll(first); + return this; + } + + public GlslSelectionNode setSecond(Collection first) { + this.first.clear(); + this.first.addAll(first); + return this; + } @Override public String getSourceString() { StringBuilder builder = new StringBuilder("if ("); builder.append(this.expression.getSourceString().replaceAll("\n", "\n\t")).append(") {\n"); - builder.append(this.first.getSourceString()).append("\n}"); - if (this.branch != null) { + for (GlslNode node : this.first) { + builder.append('\t').append(node.getSourceString().replaceAll("\n", "\n\t")).append(";\n"); + } + builder.append("}"); + if (!this.second.isEmpty()) { builder.append(" else {\n"); - builder.append(this.branch.getSourceString().replaceAll("\n", "\n\t")).append("\n}"); + for (GlslNode node : this.second) { + builder.append('\t').append(node.getSourceString().replaceAll("\n", "\n\t")).append(";\n"); + } + builder.append("}"); } return builder.toString(); } + + @Override + public String toString() { + return "GlslSelectionNode{" + + "expression=" + this.expression + ", " + + "first=" + this.first + ", " + + "branch=" + this.second + '}'; + } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAssignmentNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAssignmentNode.java index 2ac9ec00..99ef0be0 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAssignmentNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAssignmentNode.java @@ -97,7 +97,7 @@ public String toString() { public enum Operand { EQUAL("="), - MUL_ASSIGN("*/"), + MUL_ASSIGN("*="), DIV_ASSIGN("/="), MOD_ASSIGN("%="), ADD_ASSIGN("+="), diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslConditionalNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslConditionalNode.java index cab0cf32..6bc1f621 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslConditionalNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslConditionalNode.java @@ -48,7 +48,7 @@ public GlslConditionalNode setSecond(GlslNode second) { @Override public String getSourceString() { - return this.condition.getSourceString() + " " + this.first.getSourceString() + " : " + this.second.getSourceString(); + return this.condition.getSourceString() + " ? " + this.first.getSourceString() + " : " + this.second.getSourceString(); } @Override diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslOperationNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslOperationNode.java index aaa517b2..f81f7593 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslOperationNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslOperationNode.java @@ -31,7 +31,26 @@ public GlslOperationNode(GlslNode first, GlslNode second, Operand operand) { @Override public String getSourceString() { - return this.first.getSourceString() + " " + this.operand.getDelimiter() + " " + this.second.getSourceString(); + StringBuilder builder = new StringBuilder(); + boolean firstOrder = this.first instanceof GlslOperationNode operation && operation.operand.needsParentheses(); + boolean secondOrder = this.second instanceof GlslOperationNode operation && operation.operand.needsParentheses(); + + if (firstOrder) { + builder.append('('); + } + builder.append(this.first.getSourceString()); + if (firstOrder) { + builder.append(')'); + } + builder.append(' ').append(this.operand.getDelimiter()).append(' '); + if (secondOrder) { + builder.append('('); + } + builder.append(this.second.getSourceString()); + if (secondOrder) { + builder.append(')'); + } + return builder.toString(); } /** @@ -93,5 +112,12 @@ public enum Operand { public String getDelimiter() { return this.delimiter; } + + public boolean needsParentheses() { + return switch (this) { + case LEFT_SHIFT, RIGHT_SHIFT, ADD, SUBTRACT, MODULO -> true; + case MULTIPLY, DIVIDE -> false; + }; + } } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslPrimitiveConstructorNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslPrimitiveConstructorNode.java index 4e6c528e..63439b11 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslPrimitiveConstructorNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslPrimitiveConstructorNode.java @@ -26,6 +26,6 @@ public String toString() { @Override public String getSourceString() { - return this.type.getSourceString(); + return this.type.getSourceString() + this.type.getPostSourceString(); } } diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslDeclaration.java b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslDeclaration.java new file mode 100644 index 00000000..2e00028f --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslDeclaration.java @@ -0,0 +1,42 @@ +package foundry.veil.impl.glsl.node.variable; + +import foundry.veil.impl.glsl.grammar.GlslTypeQualifier; +import foundry.veil.impl.glsl.node.GlslNode; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class GlslDeclaration implements GlslNode { + + private final List typeQualifiers; + private final List names; + + public GlslDeclaration(Collection typeQualifiers, Collection names) { + this.typeQualifiers = new ArrayList<>(typeQualifiers); + this.names = new ArrayList<>(names); + } + + public List getTypeQualifiers() { + return this.typeQualifiers; + } + + public List getNames() { + return this.names; + } + + @Override + public String getSourceString() { + StringBuilder builder = new StringBuilder(); + for (GlslTypeQualifier qualifier : this.typeQualifiers) { + builder.append(qualifier.getSourceString()).append(' '); + } + for (String name : this.names) { + builder.append(name).append(", "); + } + if (!this.names.isEmpty()) { + builder.delete(builder.length() - 2, builder.length()); + } + return builder.toString().trim(); + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslFieldNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslFieldNode.java index 58f82601..2f929446 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslFieldNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslFieldNode.java @@ -32,7 +32,10 @@ public GlslFieldNode setFieldSelection(String fieldSelection) { @Override public String getSourceString() { - return this.expression.getSourceString() + '.' + this.fieldSelection; + if (this.expression instanceof GlslVariableNode || this.expression instanceof GlslFieldNode) { + return this.expression.getSourceString() + '.' + this.fieldSelection; + } + return '(' + this.expression.getSourceString() + ")." + this.fieldSelection; } @Override diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslNewNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslNewNode.java index ecdd0e34..9d8ee1b6 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslNewNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslNewNode.java @@ -11,7 +11,7 @@ public class GlslNewNode implements GlslNode { private String name; private GlslNode initializer; - public GlslNewNode(GlslType type, String name, @Nullable GlslNode initializer) { + public GlslNewNode(GlslType type, @Nullable String name, @Nullable GlslNode initializer) { this.type = type.asSpecifiedType(); this.name = name; this.initializer = initializer; @@ -21,11 +21,11 @@ public GlslSpecifiedType getType() { return this.type; } - public String getName() { + public @Nullable String getName() { return this.name; } - public GlslNode getInitializer() { + public @Nullable GlslNode getInitializer() { return this.initializer; } @@ -46,7 +46,15 @@ public GlslNewNode setInitializer(@Nullable GlslNode initializer) { @Override public String getSourceString() { - return this.type.getSourceString() + ' ' + this.name + (this.initializer != null ? " = " + this.initializer.getSourceString() : ""); + StringBuilder builder = new StringBuilder(this.type.getSourceString()); + if (this.name != null) { + builder.append(' ').append(this.name); + builder.append(this.type.getPostSourceString()); + if (this.initializer != null) { + builder.append(" = ").append(this.initializer.getSourceString()); + } + } + return builder.toString(); } @Override diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslStructNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslStructNode.java new file mode 100644 index 00000000..97260044 --- /dev/null +++ b/common/src/main/java/foundry/veil/impl/glsl/node/variable/GlslStructNode.java @@ -0,0 +1,21 @@ +package foundry.veil.impl.glsl.node.variable; + +import foundry.veil.impl.glsl.grammar.GlslSpecifiedType; +import foundry.veil.impl.glsl.node.GlslNode; + +public class GlslStructNode implements GlslNode { + + private GlslSpecifiedType specifiedType; + + public GlslStructNode(GlslSpecifiedType specifiedType) { + this.specifiedType = specifiedType; + } + + @Override + public String getSourceString() { + if (this.specifiedType.getQualifiers().isEmpty()) { + return "struct " + this.specifiedType.getSpecifier().getSourceString(); + } + return this.specifiedType.getSourceString(); + } +} diff --git a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslFieldVisitor.java b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslFieldVisitor.java deleted file mode 100644 index 05bb761e..00000000 --- a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslFieldVisitor.java +++ /dev/null @@ -1,4 +0,0 @@ -package foundry.veil.impl.glsl.visitor; - -public interface GlslFieldVisitor { -} diff --git a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslStringWriter.java b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslStringWriter.java index ef81a4d5..4a7fee9f 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslStringWriter.java +++ b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslStringWriter.java @@ -3,10 +3,12 @@ import foundry.veil.impl.glsl.grammar.GlslVersion; import foundry.veil.impl.glsl.node.GlslNode; import foundry.veil.impl.glsl.node.function.GlslFunctionNode; +import foundry.veil.impl.glsl.node.variable.GlslDeclaration; import foundry.veil.impl.glsl.node.variable.GlslNewNode; +import foundry.veil.impl.glsl.node.variable.GlslStructNode; import org.jetbrains.annotations.Nullable; -public class GlslStringWriter implements GlslTreeVisitor, GlslFieldVisitor { +public class GlslStringWriter implements GlslTreeVisitor { private final StringBuilder builder; private String value; @@ -26,8 +28,23 @@ public void visitVersion(GlslVersion version) { } @Override - public void visitField(GlslNewNode node) { - this.builder.append(this.formatExpression(node)).append(";\n"); + public void visitDirective(String directive) { + this.builder.append(directive).append('\n'); + } + + @Override + public void visitField(GlslNewNode newNode) { + this.builder.append(this.formatExpression(newNode)).append(";\n"); + } + + @Override + public void visitStruct(GlslStructNode structSpecifier) { + this.builder.append(this.formatExpression(structSpecifier)).append(";\n"); + } + + @Override + public void visitDeclaration(GlslDeclaration declaration) { + this.builder.append(this.formatExpression(declaration)).append(";\n"); } @Override diff --git a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslTreeVisitor.java b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslTreeVisitor.java index 1acba658..f7807263 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslTreeVisitor.java +++ b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslTreeVisitor.java @@ -1,15 +1,24 @@ package foundry.veil.impl.glsl.visitor; +import foundry.veil.impl.glsl.grammar.GlslStructSpecifier; import foundry.veil.impl.glsl.grammar.GlslVersion; import foundry.veil.impl.glsl.node.function.GlslFunctionNode; +import foundry.veil.impl.glsl.node.variable.GlslDeclaration; import foundry.veil.impl.glsl.node.variable.GlslNewNode; +import foundry.veil.impl.glsl.node.variable.GlslStructNode; import org.jetbrains.annotations.Nullable; public interface GlslTreeVisitor { void visitVersion(GlslVersion version); - void visitField(GlslNewNode node); + void visitDirective(String directive); + + void visitField(GlslNewNode newNode); + + void visitStruct(GlslStructNode structSpecifier); + + void visitDeclaration(GlslDeclaration declaration); @Nullable GlslFunctionVisitor visitFunction(GlslFunctionNode node); diff --git a/common/src/test/java/GlslTest.java b/common/src/test/java/GlslTest.java index c6cceef4..baeed420 100644 --- a/common/src/test/java/GlslTest.java +++ b/common/src/test/java/GlslTest.java @@ -2,6 +2,7 @@ import foundry.veil.impl.glsl.GlslParser; import foundry.veil.impl.glsl.GlslSyntaxException; import foundry.veil.impl.glsl.grammar.GlslVersion; +import foundry.veil.impl.glsl.node.GlslNode; import foundry.veil.impl.glsl.node.GlslTree; import foundry.veil.impl.glsl.visitor.GlslStringWriter; import org.junit.jupiter.api.Assertions; @@ -22,6 +23,30 @@ private String toString(GlslLexer.Token[] tokens) { return build.toString(); } + private void testSpeed(String source) throws GlslSyntaxException { + // Load classes + for (int i = 0; i < 10; i++) { + GlslLexer.Token[] tokens = GlslLexer.createTokens(source); + GlslTree tree = GlslParser.parse(tokens); + GlslStringWriter stringWriter = new GlslStringWriter(); + tree.visit(stringWriter); + } + + long start = System.nanoTime(); + GlslLexer.Token[] tokens = GlslLexer.createTokens(source); + + long parseStart = System.nanoTime(); + GlslTree tree = GlslParser.parse(tokens); + long parseEnd = System.nanoTime(); + + GlslStringWriter stringWriter = new GlslStringWriter(); + tree.visit(stringWriter); + long end = System.nanoTime(); + + System.out.println(stringWriter); + System.out.printf("Took %.1fms to tokenize, %.1fms to parse, %.1fms to stringify%n", (parseStart - start) / 1_000_000.0F, (parseEnd - parseStart) / 1_000_000.0F, (end - parseEnd) / 1_000_000.0F); + } + @Test void testLexer() throws GlslSyntaxException { GlslLexer.Token[] tokens = GlslLexer.createTokens("float a = 4e2; // comment"); @@ -30,9 +55,13 @@ void testLexer() throws GlslSyntaxException { @Test void testParser() throws GlslSyntaxException { - GlslLexer.Token[] tokens = GlslLexer.createTokens("#version 330 core\nfloat a = 1.0 + 3.0;"); - GlslTree tree = GlslParser.parse(tokens); + GlslTree tree = GlslParser.parse("#version 330 core\nfloat a = 1.0 + 3.0;"); Assertions.assertEquals(new GlslVersion(330, true), tree.getVersion()); + + GlslNode replace = GlslParser.parseExpression("2 + 7 / 3 + max(gl_Position.x, 2.0);"); + + tree.fields().forEach(node -> node.setInitializer(replace)); + GlslStringWriter stringWriter = new GlslStringWriter(); tree.visit(stringWriter); @@ -88,36 +117,26 @@ void main() { float depthSample = texture(DiffuseDepthSampler, texCoord).r; vec3 pos = viewPosFromDepthSample(depthSample, texCoord); + { + int a = 4; + float b = 7.0; + { + float h = 7.0; + int w = 1; + } + } + + for (int i = 0; i < 7; i++) { + float g = float(i); + int k = 1; + } + float vertexDistance = fog_distance(pos, FogShape); fragColor = linear_fog(baseColor, vertexDistance, FogStart, FogEnd, FogColor); } """); } - private void testSpeed(String source) throws GlslSyntaxException { - // Load classes - for (int i = 0; i < 3; i++) { - GlslLexer.Token[] tokens = GlslLexer.createTokens(source); - GlslTree tree = GlslParser.parse(tokens); - GlslStringWriter stringWriter = new GlslStringWriter(); - tree.visit(stringWriter); - } - - long start = System.nanoTime(); - GlslLexer.Token[] tokens = GlslLexer.createTokens(source); - - long parseStart = System.nanoTime(); - GlslTree tree = GlslParser.parse(tokens); - long parseEnd = System.nanoTime(); - - GlslStringWriter stringWriter = new GlslStringWriter(); - tree.visit(stringWriter); - long end = System.nanoTime(); - - System.out.println(stringWriter); - System.out.printf("Took %.1fms to tokenize, %.1fms to parse, %.1fms to stringify%n", (parseStart - start) / 1_000_000.0F, (parseEnd - parseStart) / 1_000_000.0F, (end - parseEnd) / 1_000_000.0F); - } - @Test void testReturn() throws GlslSyntaxException { this.testSpeed(""" @@ -128,4 +147,143 @@ vec3 test(inout vec3 test, int) { } """); } + + @Test + void testStruct() throws GlslSyntaxException { + GlslTree tree = GlslParser.parse(""" + struct Test { + float a; + }; + """); + + GlslStringWriter writer = new GlslStringWriter(); + tree.visit(writer); + System.out.println(writer); + } + + @Test + void testCompute() throws GlslSyntaxException { + GlslTree tree = GlslParser.parse(""" + #version 430 core + + #extension GL_ARB_compute_shader : enable + #extension GL_ARB_shader_atomic_counters : enable + #extension GL_ARB_shader_storage_buffer_object : enable + + layout(std140) uniform CameraMatrices { + mat4 ProjMat; + mat4 IProjMat; + mat4 ViewMat; + mat4 IViewMat; + mat3 IViewRotMat; + vec3 CameraPosition; + float NearPlane; + float FarPlane; + } VeilCamera; + + layout(std430) readonly buffer VeilLightInstanced { + float data[]; + }; + + layout(std430) writeonly buffer VeilLightIndirect { + int commands[]; + }; + + layout(binding = 0) uniform atomic_uint VeilLightCount; + + uniform int HighResSize; + uniform int LowResSize; + uniform int LightSize; + uniform int PositionOffset; + uniform int RangeOffset; + uniform float FrustumPlanes[24]; + + bool testSphere(float x, float y, float z, float r) { + return FrustumPlanes[0] * x + FrustumPlanes[1] * y + FrustumPlanes[2] * z + FrustumPlanes[3] >= -r && + FrustumPlanes[4] * x + FrustumPlanes[5] * y + FrustumPlanes[6] * z + FrustumPlanes[7] >= -r && + FrustumPlanes[8] * x + FrustumPlanes[9] * y + FrustumPlanes[10] * z + FrustumPlanes[11] >= -r && + FrustumPlanes[12] * x + FrustumPlanes[13] * y + FrustumPlanes[14] * z + FrustumPlanes[15] >= -r && + FrustumPlanes[16] * x + FrustumPlanes[17] * y + FrustumPlanes[18] * z + FrustumPlanes[19] >= -r && + FrustumPlanes[20] * x + FrustumPlanes[21] * y + FrustumPlanes[22] * z + FrustumPlanes[23] >= -r; + } + + layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + void main() { + uint lightId = gl_GlobalInvocationID.x; + uint lightDataIndex = lightId * LightSize; + + float x = data[lightDataIndex + PositionOffset]; + float y = data[lightDataIndex + PositionOffset + 1]; + float z = data[lightDataIndex + PositionOffset + 2]; + float range = data[lightDataIndex + RangeOffset]; + float dx = x - VeilCamera.CameraPosition.x; + float dy = y - VeilCamera.CameraPosition.y; + float dz = z - VeilCamera.CameraPosition.z; + + bool visible = testSphere(dx, dy, dz, range * 1.414); + if (visible) { + uint i = atomicCounterIncrement(VeilLightCount) * 5; + bool highRes = dx * dx + dy * dy + dz * dz <= range * range; + commands[i] = highRes ? HighResSize : LowResSize; + commands[i + 1] = 1; + commands[i + 2] = !highRes ? HighResSize : 0; + commands[i + 3] = 0; + commands[i + 4] = int(lightId); + } + }"""); + + GlslStringWriter writer = new GlslStringWriter(); + tree.visit(writer); + System.out.println(writer); + } + + @Test + void testArray() throws GlslSyntaxException { + GlslTree tree = GlslParser.parse(""" + void main() { + float fragmentDistance = -ProjMat[3].z / ((gl_FragCoord.z) * -2.0 + 1.0 - ProjMat[2].z); + } + """); + + GlslStringWriter writer = new GlslStringWriter(); + tree.visit(writer); + System.out.println(writer); + } + + @Test + void testPrimitiveArray() throws GlslSyntaxException { + GlslTree tree = GlslParser.parse(""" + #version 150 + + 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 + ); + """); + + GlslStringWriter writer = new GlslStringWriter(); + tree.visit(writer); + System.out.println(writer); + } } From ef696420ed8f385d3b16de0c240cbd1ace97d925 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Tue, 12 Nov 2024 02:56:52 -0700 Subject: [PATCH 35/47] Fixed resource reload breaking hand --- .../java/foundry/veil/impl/client/editor/ShaderEditor.java | 2 +- .../impl/client/render/pipeline/VeilFirstPersonRenderer.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/foundry/veil/impl/client/editor/ShaderEditor.java b/common/src/main/java/foundry/veil/impl/client/editor/ShaderEditor.java index 78aef17d..013d3448 100644 --- a/common/src/main/java/foundry/veil/impl/client/editor/ShaderEditor.java +++ b/common/src/main/java/foundry/veil/impl/client/editor/ShaderEditor.java @@ -503,7 +503,7 @@ public void addShaders(ObjIntConsumer registry) { @Override public void addShaders(ObjIntConsumer registry) { IntSet programs = new IntOpenHashSet(); - for (int i = 0; i < 10000; i++) { + for (int i = 1; i < 10000; i++) { if (!glIsProgram(i)) { continue; } diff --git a/common/src/main/java/foundry/veil/impl/client/render/pipeline/VeilFirstPersonRenderer.java b/common/src/main/java/foundry/veil/impl/client/render/pipeline/VeilFirstPersonRenderer.java index ca0c4c6a..e638a7ff 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/pipeline/VeilFirstPersonRenderer.java +++ b/common/src/main/java/foundry/veil/impl/client/render/pipeline/VeilFirstPersonRenderer.java @@ -29,14 +29,16 @@ public static void bind() { AdvancedFbo mainRenderTarget = postTarget != null ? postTarget : AdvancedFbo.getMainFramebuffer(); int w = mainRenderTarget.getWidth(); int h = mainRenderTarget.getHeight(); + int framebufferTexture = mainRenderTarget.getColorTextureAttachment(0).getId(); if (firstPerson == null || firstPerson.getWidth() != w || firstPerson.getHeight() != h) { free(); firstPerson = AdvancedFbo.withSize(w, h) - .addColorTextureWrapper(mainRenderTarget.getColorTextureAttachment(0).getId()) + .addColorTextureWrapper(framebufferTexture) .setFormat(FramebufferAttachmentDefinition.Format.DEPTH_COMPONENT) .setDepthTextureBuffer() .build(true); } + firstPerson.setColorAttachmentTexture(0, framebufferTexture); VeilRenderSystem.renderer().getFramebufferManager().setFramebuffer(VeilFramebuffers.FIRST_PERSON, firstPerson); firstPerson.bind(false); } From 8147db381847238229c83390a9bdcb23572ec712 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Tue, 12 Nov 2024 03:04:52 -0700 Subject: [PATCH 36/47] Fixed attachment being bound to wrong fbo --- .../impl/client/render/pipeline/VeilFirstPersonRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/foundry/veil/impl/client/render/pipeline/VeilFirstPersonRenderer.java b/common/src/main/java/foundry/veil/impl/client/render/pipeline/VeilFirstPersonRenderer.java index e638a7ff..628c8c4a 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/pipeline/VeilFirstPersonRenderer.java +++ b/common/src/main/java/foundry/veil/impl/client/render/pipeline/VeilFirstPersonRenderer.java @@ -38,9 +38,9 @@ public static void bind() { .setDepthTextureBuffer() .build(true); } - firstPerson.setColorAttachmentTexture(0, framebufferTexture); VeilRenderSystem.renderer().getFramebufferManager().setFramebuffer(VeilFramebuffers.FIRST_PERSON, firstPerson); firstPerson.bind(false); + firstPerson.setColorAttachmentTexture(0, framebufferTexture); } public static void unbind() { From c990f38612016c68dc884869a510d31580850204 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Tue, 12 Nov 2024 03:14:21 -0700 Subject: [PATCH 37/47] Fixed crash when opening in-game text editor --- common/src/main/java/foundry/veil/Veil.java | 11 +++++++++++ .../veil/api/client/imgui/CodeEditor.java | 17 +++++++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/common/src/main/java/foundry/veil/Veil.java b/common/src/main/java/foundry/veil/Veil.java index fc3e719e..d65e5d4a 100644 --- a/common/src/main/java/foundry/veil/Veil.java +++ b/common/src/main/java/foundry/veil/Veil.java @@ -42,6 +42,17 @@ public static void init() { VeilMolang.set(MolangCompiler.create(MolangCompiler.DEFAULT_FLAGS, Veil.class.getClassLoader())); } + /** + * Runs the specified code with the correct ImGui context. + * + * @param task The ImGui task to run + */ + public static void withImGui(Runnable task) { + beginImGui(); + task.run(); + endImGui(); + } + /** *

Enables writing ImGui to the screen. This useful for debugging during the normal render loop.

*

Be sure to call {@link #endImGui()} when done.

diff --git a/common/src/main/java/foundry/veil/api/client/imgui/CodeEditor.java b/common/src/main/java/foundry/veil/api/client/imgui/CodeEditor.java index 1344119d..53384ec9 100644 --- a/common/src/main/java/foundry/veil/api/client/imgui/CodeEditor.java +++ b/common/src/main/java/foundry/veil/api/client/imgui/CodeEditor.java @@ -1,5 +1,6 @@ package foundry.veil.api.client.imgui; +import foundry.veil.Veil; import imgui.ImGui; import imgui.ImVec2; import imgui.extension.texteditor.TextEditor; @@ -59,7 +60,7 @@ public void save() { if (errors.isEmpty()) { this.oldSource = this.editor.getText(); } - this.editor.setErrorMarkers(errors); + Veil.withImGui(() -> this.editor.setErrorMarkers(errors)); } /** @@ -73,8 +74,10 @@ public void show(@Nullable String fileName, String source) { this.oldSource = this.editor.getText(); this.editor.setErrorMarkers(Collections.emptyMap()); this.open.set(true); - ImGui.setWindowFocus("###editor"); - ImGui.setWindowCollapsed("###editor", false); + Veil.withImGui(() -> { + ImGui.setWindowFocus("###editor"); + ImGui.setWindowCollapsed("###editor", false); + }); } /** @@ -83,9 +86,11 @@ public void show(@Nullable String fileName, String source) { public void hide() { if (this.hasTextChanged()) { this.open.set(true); - ImGui.pushID(this.hashCode()); - ImGui.openPopup("###save_confirm"); - ImGui.popID(); + Veil.withImGui(() -> { + ImGui.pushID(this.hashCode()); + ImGui.openPopup("###save_confirm"); + ImGui.popID(); + }); } else { this.oldSource = null; this.open.set(false); From fdec7e4b4483566f1658d7e46459f6c433f2baf6 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Sat, 16 Nov 2024 11:27:46 -0700 Subject: [PATCH 38/47] Added extra logging for mac --- .../api/client/render/VeilRenderSystem.java | 26 +++++++++++++++++-- .../AdvancedFboMutableTextureAttachment.java | 14 ++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/foundry/veil/api/client/render/VeilRenderSystem.java b/common/src/main/java/foundry/veil/api/client/render/VeilRenderSystem.java index c8390804..14893fc0 100644 --- a/common/src/main/java/foundry/veil/api/client/render/VeilRenderSystem.java +++ b/common/src/main/java/foundry/veil/api/client/render/VeilRenderSystem.java @@ -361,6 +361,26 @@ public static void drawIndirect(VertexBuffer vbo, long indirect, int drawCount, ((VertexBufferExtension) vbo).veil$drawIndirect(indirect, drawCount, stride); } + /** + * Consumes all OpenGL errors and prints them to console. + * + * @param glCall The name of the OpenGL call made for extra logging or null to not include + */ + public static void printGlErrors(@Nullable String glCall) { + while (true) { + int error = GlStateManager._getError(); + if (error == GL_NO_ERROR) { + break; + } + + if (glCall != null) { + Veil.LOGGER.error("[OpenGL Error] '{}' 0x{}", glCall, Integer.toHexString(error).toUpperCase(Locale.ROOT)); + } else { + Veil.LOGGER.error("[OpenGL Error] 0x{}", Integer.toHexString(error).toUpperCase(Locale.ROOT)); + } + } + } + /** * Retrieves the number of indices in the specified vertex buffer. * @@ -439,7 +459,8 @@ public static int maxTargetBindings(int target) { case GL_UNIFORM_BUFFER -> maxUniformBuffersBindings(); case GL_ATOMIC_COUNTER_BUFFER -> maxAtomicCounterBufferBindings(); case GL_SHADER_STORAGE_BUFFER -> maxShaderStorageBufferBindings(); - default -> throw new IllegalArgumentException("Invalid Target: 0x" + Integer.toHexString(target).toUpperCase(Locale.ROOT)); + default -> + throw new IllegalArgumentException("Invalid Target: 0x" + Integer.toHexString(target).toUpperCase(Locale.ROOT)); }; } @@ -457,7 +478,8 @@ public static VeilShaderLimits shaderLimits(int shader) { case GL_GEOMETRY_SHADER -> GL_GEOMETRY_SHADER_LIMITS.get(); case GL_FRAGMENT_SHADER -> GL_FRAGMENT_SHADER_LIMITS.get(); case GL_COMPUTE_SHADER -> GL_COMPUTE_SHADER_LIMITS.get(); - default -> throw new IllegalArgumentException("Invalid Shader Type: 0x" + Integer.toHexString(shader).toUpperCase(Locale.ROOT)); + default -> + throw new IllegalArgumentException("Invalid Shader Type: 0x" + Integer.toHexString(shader).toUpperCase(Locale.ROOT)); }; } diff --git a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java index 0bc673ed..bb18549a 100644 --- a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java +++ b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java @@ -1,6 +1,10 @@ package foundry.veil.api.client.render.framebuffer; import com.mojang.blaze3d.platform.GlStateManager; +import foundry.veil.Veil; +import foundry.veil.api.client.render.VeilRenderSystem; +import foundry.veil.api.client.render.deferred.VeilDeferredRenderer; +import net.minecraft.client.Minecraft; import org.apache.commons.lang3.Validate; import org.jetbrains.annotations.ApiStatus; @@ -24,6 +28,10 @@ public AdvancedFboMutableTextureAttachment(int attachmentType, int textureId, in public void attach(int attachment) { int attachmentType = this.getAttachmentType(); Validate.isTrue(attachmentType < GL_DEPTH_ATTACHMENT || attachment == 0, "Only one depth buffer attachment is supported."); + + if (Minecraft.ON_OSX) { + VeilRenderSystem.printGlErrors(null); + } if (this.layer == -1) { GlStateManager._glFramebufferTexture2D( GL_FRAMEBUFFER, @@ -32,6 +40,9 @@ public void attach(int attachment) { this.textureId, 0 ); + if (Minecraft.ON_OSX) { + VeilRenderSystem.printGlErrors("glFramebufferTexture2D"); + } } else { glFramebufferTextureLayer( GL_FRAMEBUFFER, @@ -40,6 +51,9 @@ public void attach(int attachment) { 0, this.layer ); + if (Minecraft.ON_OSX) { + VeilRenderSystem.printGlErrors("glFramebufferTextureLayer"); + } } } From 478e9f2e65f026fc818dbd5b5025be12bd48125e Mon Sep 17 00:00:00 2001 From: Ocelot Date: Sat, 16 Nov 2024 11:55:09 -0700 Subject: [PATCH 39/47] Fixed GL error when a different shader is bound. Fixes #16 --- .../veil/mixin/client/pipeline/VertexBufferMixin.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/foundry/veil/mixin/client/pipeline/VertexBufferMixin.java b/common/src/main/java/foundry/veil/mixin/client/pipeline/VertexBufferMixin.java index fc739f67..18d087c2 100644 --- a/common/src/main/java/foundry/veil/mixin/client/pipeline/VertexBufferMixin.java +++ b/common/src/main/java/foundry/veil/mixin/client/pipeline/VertexBufferMixin.java @@ -16,8 +16,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import static org.lwjgl.opengl.GL11C.glDrawArrays; +import static org.lwjgl.opengl.GL11C.glGetInteger; import static org.lwjgl.opengl.GL15C.GL_ELEMENT_ARRAY_BUFFER; import static org.lwjgl.opengl.GL15C.glBindBuffer; +import static org.lwjgl.opengl.GL20C.GL_CURRENT_PROGRAM; import static org.lwjgl.opengl.GL31C.glDrawArraysInstanced; import static org.lwjgl.opengl.GL31C.glDrawElementsInstanced; import static org.lwjgl.opengl.GL40C.GL_PATCHES; @@ -75,7 +77,7 @@ public void drawPatches(CallbackInfo ci) { } ShaderProgram shader = VeilRenderSystem.getShader(); - if (shader != null && shader.hasTesselation()) { + if (shader != null && shader.hasTesselation() && shader.getProgram() == glGetInteger(GL_CURRENT_PROGRAM)) { // Quads are internally switched to triangles with indices in vanilla mc, so just use draw arrays // This will be wrong if custom indices are used! (transparent objects) glDrawArrays(GL_PATCHES, 0, this.indexCount * 4 / 6); @@ -91,7 +93,7 @@ public int modifyDrawMode(int glMode) { @Unique private int veil$getDrawMode(int defaultMode) { ShaderProgram shader = VeilRenderSystem.getShader(); - if (shader != null && shader.hasTesselation()) { + if (shader != null && shader.hasTesselation() && shader.getProgram() == glGetInteger(GL_CURRENT_PROGRAM)) { return GL_PATCHES; } return defaultMode; @@ -101,7 +103,7 @@ public int modifyDrawMode(int glMode) { private void _veil$drawInstanced(int instances) { if (this.mode == VertexFormat.Mode.QUADS) { ShaderProgram shader = VeilRenderSystem.getShader(); - if (shader != null && shader.hasTesselation()) { + if (shader != null && shader.hasTesselation() && shader.getProgram() == glGetInteger(GL_CURRENT_PROGRAM)) { // Quads are internally switched to triangles with indices in vanilla mc, so just use draw arrays // This will be wrong if custom indices are used! (transparent objects) glDrawArraysInstanced(GL_PATCHES, 0, this.indexCount * 4 / 6, instances); From 975f2753fe16a496888cffedf1f685156a930dd6 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Sat, 16 Nov 2024 17:16:19 -0700 Subject: [PATCH 40/47] Fixed cubemaps --- .../api/client/render/VeilRenderSystem.java | 37 +++++- .../render/framebuffer/AdvancedFbo.java | 10 +- .../AdvancedFboMutableTextureAttachment.java | 7 +- .../api/client/render/post/PostPipeline.java | 6 - .../render/post/PostProcessingManager.java | 1 - .../render/post/stage/BlitPostStage.java | 3 +- .../api/client/render/shader/VeilShaders.java | 8 ++ .../render/texture/DynamicCubemapTexture.java | 33 ++--- .../impl/client/editor/DeviceInfoViewer.java | 1 + .../impl/client/editor/TextureEditor.java | 119 +++++++++++++++--- .../render/pipeline/PostPipelineContext.java | 35 +----- .../resources/assets/veil/lang/en_us.json | 1 + .../shaders/program/debug/cubemap.fsh | 15 +++ .../shaders/program/debug/cubemap.json | 4 + common/src/test/java/GlslTest.java | 13 ++ 15 files changed, 206 insertions(+), 87 deletions(-) create mode 100644 common/src/main/resources/assets/veil/pinwheel/shaders/program/debug/cubemap.fsh create mode 100644 common/src/main/resources/assets/veil/pinwheel/shaders/program/debug/cubemap.json diff --git a/common/src/main/java/foundry/veil/api/client/render/VeilRenderSystem.java b/common/src/main/java/foundry/veil/api/client/render/VeilRenderSystem.java index c8390804..5ef32b4b 100644 --- a/common/src/main/java/foundry/veil/api/client/render/VeilRenderSystem.java +++ b/common/src/main/java/foundry/veil/api/client/render/VeilRenderSystem.java @@ -3,8 +3,7 @@ import com.google.common.base.Suppliers; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.BufferUploader; -import com.mojang.blaze3d.vertex.VertexBuffer; +import com.mojang.blaze3d.vertex.*; import foundry.veil.Veil; import foundry.veil.api.client.render.shader.ShaderManager; import foundry.veil.api.client.render.shader.definition.ShaderBlock; @@ -60,6 +59,7 @@ public final class VeilRenderSystem { private static final BooleanSupplier TRANSFORM_FEEDBACK_SUPPORTED = glCapability(caps -> caps.OpenGL40 || caps.GL_ARB_transform_feedback3); private static final BooleanSupplier TEXTURE_MULTIBIND_SUPPORTED = glCapability(caps -> caps.OpenGL44 || caps.glBindTextures != 0L); private static final BooleanSupplier SPARSE_BUFFERS_SUPPORTED = glCapability(caps -> caps.OpenGL44 || caps.GL_ARB_sparse_buffer); + private static final BooleanSupplier DIRECT_STATE_ACCESS_SUPPORTED = glCapability(caps -> caps.OpenGL45 || caps.GL_ARB_direct_state_access); private static final IntSupplier MAX_COMBINED_TEXTURE_IMAGE_UNITS = VeilRenderSystem.glGetter(() -> glGetInteger(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)); private static final IntSupplier MAX_COLOR_ATTACHMENTS = VeilRenderSystem.glGetter(() -> glGetInteger(GL_MAX_COLOR_ATTACHMENTS)); private static final IntSupplier MAX_SAMPLES = VeilRenderSystem.glGetter(() -> glGetInteger(GL_MAX_SAMPLES)); @@ -185,6 +185,8 @@ public final class VeilRenderSystem { private static VeilRenderer renderer; private static ResourceLocation shaderLocation; + private static VertexBuffer vbo; + private VeilRenderSystem() { } @@ -245,6 +247,20 @@ public static void init() { renderer = new VeilRenderer(resourceManager); VeilImGuiImpl.init(client.getWindow().getWindow()); + + Tesselator tesselator = RenderSystem.renderThreadTesselator(); + BufferBuilder bufferBuilder = tesselator.getBuilder(); + + bufferBuilder.begin(VertexFormat.Mode.TRIANGLE_STRIP, DefaultVertexFormat.POSITION); + bufferBuilder.vertex(-1, 1, 0).endVertex(); + bufferBuilder.vertex(-1, -1, 0).endVertex(); + bufferBuilder.vertex(1, 1, 0).endVertex(); + bufferBuilder.vertex(1, -1, 0).endVertex(); + + vbo = new VertexBuffer(VertexBuffer.Usage.STATIC); + vbo.bind(); + vbo.upload(bufferBuilder.end()); + VertexBuffer.unbind(); } private static void invalidateTextures(int first, int count) { @@ -276,6 +292,15 @@ public static void bindTextures(int first, int... textures) { glBindTextures(first, textures); } + /** + * Draws a quad onto the full screen using {@link DefaultVertexFormat#POSITION}. + */ + public static void drawScreenQuad() { + vbo.bind(); + vbo.draw(); + VertexBuffer.unbind(); + } + /** * Sets the shader instance to be a reference to the shader manager. * @@ -406,6 +431,13 @@ public static boolean sparseBuffersSupported() { return VeilRenderSystem.SPARSE_BUFFERS_SUPPORTED.getAsBoolean(); } + /** + * @return Whether {@link ARBDirectStateAccess} is supported + */ + public static boolean directStateAccessSupported() { + return VeilRenderSystem.DIRECT_STATE_ACCESS_SUPPORTED.getAsBoolean(); + } + /** * @return The GL maximum number of texture units that can be bound */ @@ -669,6 +701,7 @@ public static void close() { if (renderer != null) { renderer.free(); } + vbo.close(); } @ApiStatus.Internal diff --git a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java index acb5789d..536fbe1b 100644 --- a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java +++ b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFbo.java @@ -351,9 +351,8 @@ default void setColorAttachmentTexture(int attachment, int textureId, int layer) AdvancedFboAttachment advancedFboAttachment = this.getColorAttachment(attachment); Validate.isTrue(this.isMutableColorTextureAttachment(attachment), "Color attachment " + attachment + " must be a mutable texture attachment to modify texture information."); AdvancedFboMutableTextureAttachment mutableTextureAttachment = (AdvancedFboMutableTextureAttachment) advancedFboAttachment; - if (mutableTextureAttachment.setTexture(textureId, layer)) { - mutableTextureAttachment.attach(attachment); - } + mutableTextureAttachment.setTexture(textureId, layer); + mutableTextureAttachment.attach(attachment); } /** @@ -443,9 +442,8 @@ default void setDepthAttachmentTexture(int textureId, int layer) { AdvancedFboAttachment advancedFboAttachment = this.getDepthAttachment(); Validate.isTrue(this.isDepthMutableTextureAttachment(), "Depth attachment must be a mutable texture attachment to modify texture information."); AdvancedFboMutableTextureAttachment mutableTextureAttachment = (AdvancedFboMutableTextureAttachment) advancedFboAttachment; - if (mutableTextureAttachment.setTexture(textureId, layer)) { - mutableTextureAttachment.attach(0); - } + mutableTextureAttachment.setTexture(textureId, layer); + mutableTextureAttachment.attach(0); } /** diff --git a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java index 0bc673ed..e3af689b 100644 --- a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java +++ b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java @@ -61,13 +61,8 @@ public int getId() { return this.textureId; } - public boolean setTexture(int textureId, int layer) { - if (this.textureId == textureId && this.layer == layer) { - return false; - } - + public void setTexture(int textureId, int layer) { this.textureId = textureId; this.layer = layer; - return true; } } diff --git a/common/src/main/java/foundry/veil/api/client/render/post/PostPipeline.java b/common/src/main/java/foundry/veil/api/client/render/post/PostPipeline.java index de654aa5..6c98dbf0 100644 --- a/common/src/main/java/foundry/veil/api/client/render/post/PostPipeline.java +++ b/common/src/main/java/foundry/veil/api/client/render/post/PostPipeline.java @@ -1,6 +1,5 @@ package foundry.veil.api.client.render.post; -import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.serialization.Codec; import foundry.veil.api.client.registry.PostPipelineStageRegistry; import foundry.veil.api.client.render.VeilRenderSystem; @@ -251,11 +250,6 @@ default void setMatrix(CharSequence name, Matrix4x3fc value) { */ interface Context extends ShaderTextureSource.Context { - /** - * Draws a quad onto the full screen using {@link DefaultVertexFormat#POSITION}. - */ - void drawScreenQuad(); - /** * Binds a named sampler id. All samplers can be applied with {@link #applySamplers(ShaderProgram)} for adding them to shaders. * diff --git a/common/src/main/java/foundry/veil/api/client/render/post/PostProcessingManager.java b/common/src/main/java/foundry/veil/api/client/render/post/PostProcessingManager.java index 9cc9b24a..6260199c 100644 --- a/common/src/main/java/foundry/veil/api/client/render/post/PostProcessingManager.java +++ b/common/src/main/java/foundry/veil/api/client/render/post/PostProcessingManager.java @@ -293,7 +293,6 @@ protected void apply(@NotNull Map data, public void free() { this.pipelines.values().forEach(PostPipeline::free); this.pipelines.clear(); - this.context.free(); } /** diff --git a/common/src/main/java/foundry/veil/api/client/render/post/stage/BlitPostStage.java b/common/src/main/java/foundry/veil/api/client/render/post/stage/BlitPostStage.java index 355ded22..6b616ce4 100644 --- a/common/src/main/java/foundry/veil/api/client/render/post/stage/BlitPostStage.java +++ b/common/src/main/java/foundry/veil/api/client/render/post/stage/BlitPostStage.java @@ -5,6 +5,7 @@ import foundry.veil.Veil; import foundry.veil.api.client.registry.PostPipelineStageRegistry; import foundry.veil.api.client.render.VeilRenderSystem; +import foundry.veil.api.client.render.VeilRenderer; import foundry.veil.api.client.render.framebuffer.FramebufferManager; import foundry.veil.api.client.render.post.PostPipeline; import foundry.veil.api.client.render.shader.program.ShaderProgram; @@ -69,7 +70,7 @@ public void apply(Context context) { context.applySamplers(shader); this.setupFramebuffer(context, shader); shader.applyShaderSamplers(context, 0); - context.drawScreenQuad(); + VeilRenderSystem.drawScreenQuad(); } @Override diff --git a/common/src/main/java/foundry/veil/api/client/render/shader/VeilShaders.java b/common/src/main/java/foundry/veil/api/client/render/shader/VeilShaders.java index 1955bb92..7d92355b 100644 --- a/common/src/main/java/foundry/veil/api/client/render/shader/VeilShaders.java +++ b/common/src/main/java/foundry/veil/api/client/render/shader/VeilShaders.java @@ -1,7 +1,9 @@ package foundry.veil.api.client.render.shader; import foundry.veil.Veil; +import foundry.veil.api.client.render.shader.program.ShaderProgram; import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.Nullable; /** * Default shader names. @@ -24,6 +26,8 @@ private VeilShaders() { public static final ResourceLocation SKINNED_MESH = necromancer("skinned_mesh"); + public static final ResourceLocation DEBUG_CUBEMAP = debug("cubemap"); + private static ResourceLocation quasar(String name) { return Veil.veilPath("quasar/" + name); } @@ -35,4 +39,8 @@ private static ResourceLocation light(String name) { private static ResourceLocation necromancer(String name) { return Veil.veilPath("necromancer/" + name); } + + private static ResourceLocation debug(String name) { + return Veil.veilPath("debug/" + name); + } } diff --git a/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java b/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java index a9457f05..229a7522 100644 --- a/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java +++ b/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java @@ -11,6 +11,7 @@ import static org.lwjgl.opengl.GL11C.*; import static org.lwjgl.opengl.GL12C.*; +import static org.lwjgl.opengl.GL13C.GL_TEXTURE_CUBE_MAP; import static org.lwjgl.opengl.GL13C.GL_TEXTURE_CUBE_MAP_POSITIVE_X; import static org.lwjgl.opengl.GL14C.GL_TEXTURE_LOD_BIAS; @@ -21,8 +22,13 @@ */ public class DynamicCubemapTexture extends CubemapTexture { - private int width; - private int height; + private final int[] width; + private final int[] height; + + public DynamicCubemapTexture() { + this.width = new int[6]; + this.height = new int[6]; + } /** * Initializes each face to the same size white texture. @@ -31,14 +37,17 @@ public class DynamicCubemapTexture extends CubemapTexture { * @param height The height of each face */ public void init(int width, int height) { - this.width = width; - this.height = height; + for (int i = 0; i < 6; i++) { + this.width[i] = width; + this.height[i] = height; + } this.bind(); - GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); - GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); - GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, 0.0F); + this.setFilter(false, false); + GlStateManager._texParameter(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0); + GlStateManager._texParameter(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_LOD, 0); + GlStateManager._texParameter(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LOD, 0); + GlStateManager._texParameter(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_LOD_BIAS, 0.0F); RenderSystem.assertOnRenderThreadOrInit(); for (int i = 0; i < 6; i++) { @@ -52,11 +61,7 @@ public void init(int width, int height) { * @param image The image to upload */ public void upload(NativeImage image) { - if (this.width != image.getWidth() || this.height != image.getHeight()) { - this.init(image.getWidth(), image.getHeight()); - } else { - this.bind(); - } + this.init(image.getWidth(), image.getHeight()); int width = image.getWidth(); int height = image.getHeight(); @@ -90,7 +95,7 @@ public void upload(Direction face, NativeImage image) { * @param image The image to upload */ public void upload(int face, NativeImage image) { - if (this.width != image.getWidth() || this.height != image.getHeight()) { + if (this.width[face - GL_TEXTURE_CUBE_MAP_POSITIVE_X] != image.getWidth() || this.height[face - GL_TEXTURE_CUBE_MAP_POSITIVE_X] != image.getHeight()) { this.init(image.getWidth(), image.getHeight()); } else { this.bind(); diff --git a/common/src/main/java/foundry/veil/impl/client/editor/DeviceInfoViewer.java b/common/src/main/java/foundry/veil/impl/client/editor/DeviceInfoViewer.java index b37ac4c4..9d35de6f 100644 --- a/common/src/main/java/foundry/veil/impl/client/editor/DeviceInfoViewer.java +++ b/common/src/main/java/foundry/veil/impl/client/editor/DeviceInfoViewer.java @@ -106,6 +106,7 @@ private void renderOpenGL() { flagText("editor.veil.device_info.opengl.feature_flag.transform_feedback", VeilRenderSystem.transformFeedbackSupported(), "Whether transform feedback can be used"); flagText("editor.veil.device_info.opengl.feature_flag.texture_multi_bind", VeilRenderSystem.textureMultibindSupported(), "Whether glBindTextures can be used instead of glBindTexture"); flagText("editor.veil.device_info.opengl.feature_flag.sparse_buffers", VeilRenderSystem.sparseBuffersSupported(), "Whether sparse buffers can be used"); + flagText("editor.veil.device_info.opengl.feature_flag.direct_state_access", VeilRenderSystem.directStateAccessSupported(), "Whether direct state accesss can be used"); ImGui.separator(); GLCapabilities caps = GL.getCapabilities(); diff --git a/common/src/main/java/foundry/veil/impl/client/editor/TextureEditor.java b/common/src/main/java/foundry/veil/impl/client/editor/TextureEditor.java index 85c799e7..0cf2fcc2 100644 --- a/common/src/main/java/foundry/veil/impl/client/editor/TextureEditor.java +++ b/common/src/main/java/foundry/veil/impl/client/editor/TextureEditor.java @@ -3,27 +3,39 @@ import com.mojang.blaze3d.systems.RenderSystem; import foundry.veil.Veil; import foundry.veil.api.client.editor.SingleWindowEditor; +import foundry.veil.api.client.render.VeilRenderSystem; +import foundry.veil.api.client.render.framebuffer.AdvancedFbo; +import foundry.veil.api.client.render.shader.VeilShaders; +import foundry.veil.api.client.render.shader.program.ShaderProgram; import foundry.veil.api.client.util.TextureDownloader; import imgui.ImGui; import imgui.flag.ImGuiDir; import imgui.flag.ImGuiWindowFlags; import imgui.type.ImBoolean; +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.IntArraySet; import it.unimi.dsi.fastutil.ints.IntSet; +import it.unimi.dsi.fastutil.objects.ObjectIterator; import net.minecraft.Util; import net.minecraft.client.Minecraft; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import org.jetbrains.annotations.ApiStatus; +import org.lwjgl.system.NativeResource; import java.io.IOException; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; -import java.util.*; +import java.util.LinkedList; +import java.util.List; import java.util.concurrent.CompletableFuture; import static org.lwjgl.opengl.GL11C.*; +import static org.lwjgl.opengl.GL13C.GL_TEXTURE_CUBE_MAP; import static org.lwjgl.opengl.GL20C.glIsTexture; +import static org.lwjgl.opengl.GL45C.GL_TEXTURE_TARGET; +import static org.lwjgl.opengl.GL45C.glGetTextureParameteri; @ApiStatus.Internal public class TextureEditor extends SingleWindowEditor { @@ -36,7 +48,8 @@ public class TextureEditor extends SingleWindowEditor { public static final Component NO_TEXTURE = Component.translatable("editor.veil.texture.asset.missing"); private final IntSet texturesSet; - private final Map openTextures; + private final Int2ObjectMap openTextures; + private final Int2ObjectMap cubemapStorage; private final ImBoolean flipX; private final ImBoolean flipY; private int[] textures; @@ -46,7 +59,8 @@ public class TextureEditor extends SingleWindowEditor { public TextureEditor() { this.texturesSet = new IntArraySet(); - this.openTextures = new HashMap<>(); + this.openTextures = new Int2ObjectArrayMap<>(); + this.cubemapStorage = new Int2ObjectArrayMap<>(); this.flipX = new ImBoolean(); this.flipY = new ImBoolean(); this.textures = new int[0]; @@ -69,7 +83,16 @@ private void scanTextures() { this.selectedTexture = 0; } this.textures = this.texturesSet.toIntArray(); - this.openTextures.keySet().removeIf(a -> !this.texturesSet.contains(a.intValue())); + this.openTextures.keySet().removeIf(a -> !this.texturesSet.contains(a)); + + ObjectIterator> iterator = this.cubemapStorage.int2ObjectEntrySet().iterator(); + while (iterator.hasNext()) { + Int2ObjectMap.Entry entry = iterator.next(); + if (!this.texturesSet.contains(entry.getIntKey())) { + entry.getValue().free(); + iterator.remove(); + } + } } } @@ -134,7 +157,7 @@ protected void renderComponents() { ImGui.checkbox(FLIP_Y.getString(), this.flipY); if (selectedId != 0) { - addImage(selectedId, this.flipX.get(), this.flipY.get()); + this.addImage(selectedId, this.flipX.get(), this.flipY.get()); } } @@ -142,10 +165,10 @@ protected void renderComponents() { public void render() { super.render(); - Iterator> iterator = this.openTextures.entrySet().iterator(); + ObjectIterator> iterator = this.openTextures.int2ObjectEntrySet().iterator(); while (iterator.hasNext()) { - Map.Entry entry = iterator.next(); - int id = entry.getKey(); + Int2ObjectMap.Entry entry = iterator.next(); + int id = entry.getIntKey(); OpenTexture texture = entry.getValue(); if (!texture.visible.get()) { @@ -163,7 +186,7 @@ public void render() { ImGui.checkbox(FLIP_X.getString(), flipX); ImGui.sameLine(0.0f, ImGui.getStyle().getItemInnerSpacingX()); ImGui.checkbox(FLIP_Y.getString(), flipY); - addImage(id, flipX.get(), flipY.get()); + this.addImage(id, flipX.get(), flipY.get()); } ImGui.end(); @@ -209,8 +232,8 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO @Override public void renderMenuBar() { - for (Map.Entry entry : this.openTextures.entrySet()) { - ImGui.menuItem(I18n.get("editor.veil.texture.asset", entry.getKey()), null, entry.getValue().visible); + for (Int2ObjectMap.Entry entry : this.openTextures.int2ObjectEntrySet()) { + ImGui.menuItem(I18n.get("editor.veil.texture.asset", entry.getIntKey()), null, entry.getValue().visible); } } @@ -223,16 +246,32 @@ public boolean isMenuBarEnabled() { public void onHide() { super.onHide(); this.texturesSet.clear(); + this.cubemapStorage.values().forEach(CubemapStorage::free); + this.cubemapStorage.clear(); this.textures = new int[0]; this.selectedTexture = 0; } - private static void addImage(int selectedId, boolean flipX, boolean flipY) { - RenderSystem.bindTexture(selectedId); - int width = glGetTexLevelParameteri(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH); - int height = glGetTexLevelParameteri(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT); - float size = ImGui.getContentRegionAvailX(); - ImGui.image(selectedId, size, size * (float) height / (float) width, flipX ? 1 : 0, flipY ? 1 : 0, flipX ? 0 : 1, flipY ? 0 : 1, 1.0F, 1.0F, 1.0F, 1.0F, 1.0F, 1.0F, 1.0F, 1.0F); + private void addImage(int selectedId, boolean flipX, boolean flipY) { + int target = VeilRenderSystem.directStateAccessSupported() ? glGetTextureParameteri(selectedId, GL_TEXTURE_TARGET) : GL_TEXTURE_2D; + if (target == GL_TEXTURE_CUBE_MAP) { + CubemapStorage storage = this.cubemapStorage.computeIfAbsent(selectedId, CubemapStorage::new); + float size = ImGui.getContentRegionAvailX(); + + storage.render((int) size, (int) (size / 2.0F)); + ImGui.image(storage.renderedTextureId(), size, size / 2.0F, flipX ? 1 : 0, flipY ? 1 : 0, flipX ? 0 : 1, flipY ? 0 : 1, 1.0F, 1.0F, 1.0F, 1.0F, 1.0F, 1.0F, 1.0F, 1.0F); + } else if (target == GL_TEXTURE_2D) { + CubemapStorage storage = this.cubemapStorage.remove(selectedId); + if (storage != null) { + storage.free(); + } + + RenderSystem.bindTexture(selectedId); + int width = glGetTexLevelParameteri(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH); + int height = glGetTexLevelParameteri(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT); + float size = ImGui.getContentRegionAvailX(); + ImGui.image(selectedId, size, size * (float) height / (float) width, flipX ? 1 : 0, flipY ? 1 : 0, flipX ? 0 : 1, flipY ? 0 : 1, 1.0F, 1.0F, 1.0F, 1.0F, 1.0F, 1.0F, 1.0F, 1.0F); + } } private record OpenTexture(ImBoolean open, ImBoolean visible, ImBoolean flipX, ImBoolean flipY) { @@ -241,4 +280,50 @@ private OpenTexture(boolean flipX, boolean flipY) { this(new ImBoolean(), new ImBoolean(true), new ImBoolean(flipX), new ImBoolean(flipY)); } } + + private static final class CubemapStorage implements NativeResource { + + private final int texture; + private AdvancedFbo fbo; + + private CubemapStorage(int texture) { + this.texture = texture; + } + + public void render(int width, int height) { + ShaderProgram shaderProgram = VeilRenderSystem.setShader(VeilShaders.DEBUG_CUBEMAP); + if (shaderProgram == null) { + VeilRenderSystem.throwShaderError(); + this.free(); + return; + } + + if (this.fbo == null || this.fbo.getWidth() != width || this.fbo.getHeight() != height) { + this.free(); + this.fbo = AdvancedFbo.withSize(width, height) + .addColorTextureBuffer() + .setDepthRenderBuffer() + .build(true); + } + + this.fbo.bind(true); + this.fbo.clear(); + glBindTexture(GL_TEXTURE_CUBE_MAP, this.texture); + shaderProgram.bind(); + VeilRenderSystem.drawScreenQuad(); + AdvancedFbo.unbind(); + } + + public int renderedTextureId() { + return this.fbo.getColorTextureAttachment(0).getId(); + } + + @Override + public void free() { + if (this.fbo != null) { + this.fbo.free(); + this.fbo = null; + } + } + } } diff --git a/common/src/main/java/foundry/veil/impl/client/render/pipeline/PostPipelineContext.java b/common/src/main/java/foundry/veil/impl/client/render/pipeline/PostPipelineContext.java index 7cb1c28d..2232048d 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/pipeline/PostPipelineContext.java +++ b/common/src/main/java/foundry/veil/impl/client/render/pipeline/PostPipelineContext.java @@ -1,7 +1,5 @@ package foundry.veil.impl.client.render.pipeline; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.*; import foundry.veil.api.client.render.VeilRenderSystem; import foundry.veil.api.client.render.framebuffer.AdvancedFbo; import foundry.veil.api.client.render.framebuffer.VeilFramebuffers; @@ -10,7 +8,6 @@ import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; -import org.lwjgl.system.NativeResource; import java.util.HashMap; import java.util.Map; @@ -19,9 +16,8 @@ * Default implementation of {@link PostPipeline.Context}. */ @ApiStatus.Internal -public class PostPipelineContext implements PostPipeline.Context, NativeResource { +public class PostPipelineContext implements PostPipeline.Context { - private final VertexBuffer vbo; private final Map samplers; private final Map framebuffers; @@ -29,25 +25,8 @@ public class PostPipelineContext implements PostPipeline.Context, NativeResource * Creates a new context to fit the specified window. */ public PostPipelineContext() { - this.vbo = new VertexBuffer(VertexBuffer.Usage.STATIC); this.samplers = new HashMap<>(); this.framebuffers = new HashMap<>(); - this.setupScreenQuad(); - } - - private void setupScreenQuad() { - Tesselator tesselator = RenderSystem.renderThreadTesselator(); - BufferBuilder bufferBuilder = tesselator.getBuilder(); - - bufferBuilder.begin(VertexFormat.Mode.TRIANGLE_STRIP, DefaultVertexFormat.POSITION); - bufferBuilder.vertex(-1, 1, 0).endVertex(); - bufferBuilder.vertex(-1, -1, 0).endVertex(); - bufferBuilder.vertex(1, 1, 0).endVertex(); - bufferBuilder.vertex(1, -1, 0).endVertex(); - - this.vbo.bind(); - this.vbo.upload(bufferBuilder.end()); - VertexBuffer.unbind(); } /** @@ -66,13 +45,6 @@ public void end() { this.framebuffers.clear(); } - @Override - public void drawScreenQuad() { - this.vbo.bind(); - this.vbo.draw(); - VertexBuffer.unbind(); - } - @Override public void setSampler(CharSequence name, int id) { this.samplers.put(name, id); @@ -97,9 +69,4 @@ public void applySamplers(ShaderProgram shader) { public AdvancedFbo getDrawFramebuffer() { return this.framebuffers.getOrDefault(VeilFramebuffers.POST, AdvancedFbo.getMainFramebuffer()); } - - @Override - public void free() { - this.vbo.close(); - } } diff --git a/common/src/main/resources/assets/veil/lang/en_us.json b/common/src/main/resources/assets/veil/lang/en_us.json index 5378cdfa..d65d0bff 100644 --- a/common/src/main/resources/assets/veil/lang/en_us.json +++ b/common/src/main/resources/assets/veil/lang/en_us.json @@ -51,6 +51,7 @@ "editor.veil.device_info.opengl.feature_flag.transform_feedback": "Transform Feedback? %s", "editor.veil.device_info.opengl.feature_flag.texture_multi_bind": "Texture Multi-bind? %s", "editor.veil.device_info.opengl.feature_flag.sparse_buffers": "Sparse Buffers? %s", + "editor.veil.device_info.opengl.feature_flag.direct_state_access": "Direct Space Access? %s", "editor.veil.device_info.opengl.shader.max_uniform_components": "Max Uniform Components: %s", "editor.veil.device_info.opengl.shader.max_uniform_blocks": "Max Uniform Blocks: %s", diff --git a/common/src/main/resources/assets/veil/pinwheel/shaders/program/debug/cubemap.fsh b/common/src/main/resources/assets/veil/pinwheel/shaders/program/debug/cubemap.fsh new file mode 100644 index 00000000..90d5b5b8 --- /dev/null +++ b/common/src/main/resources/assets/veil/pinwheel/shaders/program/debug/cubemap.fsh @@ -0,0 +1,15 @@ +#include veil:common + +uniform samplerCube DiffuseSampler0; + +in vec2 texCoord; + +out vec4 outColor; + +void main() { + float phi = texCoord.s * TWO_PI; + float theta = (0.5 - texCoord.t) * PI; + + vec3 direction = vec3(cos(phi) * cos(theta), sin(theta), sin(phi) * cos(theta)); + outColor = texture(DiffuseSampler0, direction); +} \ No newline at end of file diff --git a/common/src/main/resources/assets/veil/pinwheel/shaders/program/debug/cubemap.json b/common/src/main/resources/assets/veil/pinwheel/shaders/program/debug/cubemap.json new file mode 100644 index 00000000..cc44bc87 --- /dev/null +++ b/common/src/main/resources/assets/veil/pinwheel/shaders/program/debug/cubemap.json @@ -0,0 +1,4 @@ +{ + "vertex": "veil:blit_screen", + "fragment": "veil:debug/cubemap" +} diff --git a/common/src/test/java/GlslTest.java b/common/src/test/java/GlslTest.java index baeed420..16db5027 100644 --- a/common/src/test/java/GlslTest.java +++ b/common/src/test/java/GlslTest.java @@ -4,6 +4,7 @@ import foundry.veil.impl.glsl.grammar.GlslVersion; import foundry.veil.impl.glsl.node.GlslNode; import foundry.veil.impl.glsl.node.GlslTree; +import foundry.veil.impl.glsl.node.function.GlslFunctionNode; import foundry.veil.impl.glsl.visitor.GlslStringWriter; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -286,4 +287,16 @@ void testPrimitiveArray() throws GlslSyntaxException { tree.visit(writer); System.out.println(writer); } + + @Test + void testSmall() throws GlslSyntaxException { + GlslTree tree = GlslParser.parse("void mainImage(out vec4 z,vec2 I){z*=0.;for(vec3 R=iResolution;dot(z,z)<9.;z.z+=.1)z.xy=vec2(z.x*z.x-z.y*z.y,2.*z.x*z.y)+2.*(I+I-R.xy)/R.x;}"); + + GlslFunctionNode mainImage = tree.functions().filter(fun -> fun.getHeader().getName().equals("mainImage")).findFirst().orElseThrow(); + mainImage.getBody().addAll(GlslParser.parseExpressionList("return 42;")); + + GlslStringWriter writer = new GlslStringWriter(); + tree.visit(writer); + System.out.println(writer); + } } From 5aee6f40e04357a2da27550c6b4cee1d053d5a59 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Sat, 16 Nov 2024 17:17:31 -0700 Subject: [PATCH 41/47] Removed mac logging --- .../framebuffer/AdvancedFboMutableTextureAttachment.java | 9 --------- .../veil/api/client/render/post/stage/BlitPostStage.java | 1 - .../client/render/shader/ShaderModificationManager.java | 1 - .../veil/api/client/render/shader/VeilShaders.java | 2 -- .../render/shader/modifier/InputShaderModification.java | 2 -- .../main/java/foundry/veil/impl/glsl/node/GlslTree.java | 1 - .../foundry/veil/impl/glsl/node/branch/ForLoopNode.java | 1 - .../veil/impl/glsl/node/branch/GlslCaseLabelNode.java | 1 - .../veil/impl/glsl/node/branch/GlslSelectionNode.java | 2 -- .../impl/glsl/node/expression/GlslAssignmentNode.java | 2 -- .../veil/impl/glsl/node/expression/GlslCompareNode.java | 2 -- .../impl/glsl/node/expression/GlslExclusiveOrNode.java | 1 - .../impl/glsl/node/expression/GlslInclusiveOrNode.java | 1 - .../impl/glsl/node/expression/GlslLogicalAndNode.java | 1 - .../impl/glsl/node/expression/GlslLogicalOrNode.java | 1 - .../impl/glsl/node/expression/GlslLogicalXorNode.java | 1 - .../veil/impl/glsl/node/expression/GlslUnaryNode.java | 2 -- .../veil/impl/glsl/node/function/GlslFunctionNode.java | 6 ++++-- .../impl/glsl/node/function/GlslInvokeFunctionNode.java | 1 - .../foundry/veil/impl/glsl/visitor/GlslTreeVisitor.java | 1 - common/src/test/java/GlslGrammarGenerator.java | 4 ---- 21 files changed, 4 insertions(+), 39 deletions(-) diff --git a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java index e1ceb3ca..87c85aee 100644 --- a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java +++ b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java @@ -29,9 +29,6 @@ public void attach(int attachment) { int attachmentType = this.getAttachmentType(); Validate.isTrue(attachmentType < GL_DEPTH_ATTACHMENT || attachment == 0, "Only one depth buffer attachment is supported."); - if (Minecraft.ON_OSX) { - VeilRenderSystem.printGlErrors(null); - } if (this.layer == -1) { GlStateManager._glFramebufferTexture2D( GL_FRAMEBUFFER, @@ -40,9 +37,6 @@ public void attach(int attachment) { this.textureId, 0 ); - if (Minecraft.ON_OSX) { - VeilRenderSystem.printGlErrors("glFramebufferTexture2D"); - } } else { glFramebufferTextureLayer( GL_FRAMEBUFFER, @@ -51,9 +45,6 @@ public void attach(int attachment) { 0, this.layer ); - if (Minecraft.ON_OSX) { - VeilRenderSystem.printGlErrors("glFramebufferTextureLayer"); - } } } diff --git a/common/src/main/java/foundry/veil/api/client/render/post/stage/BlitPostStage.java b/common/src/main/java/foundry/veil/api/client/render/post/stage/BlitPostStage.java index 6b616ce4..eea36add 100644 --- a/common/src/main/java/foundry/veil/api/client/render/post/stage/BlitPostStage.java +++ b/common/src/main/java/foundry/veil/api/client/render/post/stage/BlitPostStage.java @@ -5,7 +5,6 @@ import foundry.veil.Veil; import foundry.veil.api.client.registry.PostPipelineStageRegistry; import foundry.veil.api.client.render.VeilRenderSystem; -import foundry.veil.api.client.render.VeilRenderer; import foundry.veil.api.client.render.framebuffer.FramebufferManager; import foundry.veil.api.client.render.post.PostPipeline; import foundry.veil.api.client.render.shader.program.ShaderProgram; diff --git a/common/src/main/java/foundry/veil/api/client/render/shader/ShaderModificationManager.java b/common/src/main/java/foundry/veil/api/client/render/shader/ShaderModificationManager.java index 5ade6c87..123bb03a 100644 --- a/common/src/main/java/foundry/veil/api/client/render/shader/ShaderModificationManager.java +++ b/common/src/main/java/foundry/veil/api/client/render/shader/ShaderModificationManager.java @@ -7,7 +7,6 @@ import foundry.veil.impl.client.render.shader.modifier.SimpleShaderModification; import foundry.veil.impl.client.render.shader.transformer.VeilJobParameters; import foundry.veil.impl.glsl.GlslParser; -import foundry.veil.impl.glsl.GlslSyntaxException; import foundry.veil.impl.glsl.node.GlslTree; import foundry.veil.impl.glsl.visitor.GlslStringWriter; import net.minecraft.resources.FileToIdConverter; diff --git a/common/src/main/java/foundry/veil/api/client/render/shader/VeilShaders.java b/common/src/main/java/foundry/veil/api/client/render/shader/VeilShaders.java index 7d92355b..e89b8e61 100644 --- a/common/src/main/java/foundry/veil/api/client/render/shader/VeilShaders.java +++ b/common/src/main/java/foundry/veil/api/client/render/shader/VeilShaders.java @@ -1,9 +1,7 @@ package foundry.veil.api.client.render.shader; import foundry.veil.Veil; -import foundry.veil.api.client.render.shader.program.ShaderProgram; import net.minecraft.resources.ResourceLocation; -import org.jetbrains.annotations.Nullable; /** * Default shader names. diff --git a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/InputShaderModification.java b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/InputShaderModification.java index d229deab..d8760b84 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/InputShaderModification.java +++ b/common/src/main/java/foundry/veil/impl/client/render/shader/modifier/InputShaderModification.java @@ -6,8 +6,6 @@ import foundry.veil.impl.glsl.node.GlslTree; import org.jetbrains.annotations.ApiStatus; -import java.io.IOException; - @ApiStatus.Internal public class InputShaderModification implements ShaderModification { diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java b/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java index 0314e6f6..7b0b77a2 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/GlslTree.java @@ -1,6 +1,5 @@ package foundry.veil.impl.glsl.node; -import foundry.veil.impl.glsl.grammar.GlslStructSpecifier; import foundry.veil.impl.glsl.grammar.GlslVersion; import foundry.veil.impl.glsl.node.function.GlslFunctionNode; import foundry.veil.impl.glsl.node.variable.GlslDeclaration; diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/ForLoopNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/ForLoopNode.java index e9fadda1..a3cc9348 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/branch/ForLoopNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/ForLoopNode.java @@ -1,7 +1,6 @@ package foundry.veil.impl.glsl.node.branch; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslTreeVisitor; import org.jetbrains.annotations.Nullable; import java.util.Arrays; diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslCaseLabelNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslCaseLabelNode.java index 7a7941c7..2cecced2 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslCaseLabelNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslCaseLabelNode.java @@ -1,7 +1,6 @@ package foundry.veil.impl.glsl.node.branch; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslTreeVisitor; import org.jetbrains.annotations.Nullable; public class GlslCaseLabelNode implements GlslNode { diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSelectionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSelectionNode.java index 3ffc0f59..53b4afbd 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSelectionNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/branch/GlslSelectionNode.java @@ -1,9 +1,7 @@ package foundry.veil.impl.glsl.node.branch; import foundry.veil.impl.glsl.node.GlslNode; -import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; import java.util.Collection; import java.util.List; diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAssignmentNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAssignmentNode.java index 99ef0be0..ec66a2fa 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAssignmentNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslAssignmentNode.java @@ -2,8 +2,6 @@ import foundry.veil.impl.glsl.node.GlslNode; -import java.util.Objects; - /** * Equal; A = B *
diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslCompareNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslCompareNode.java index 24b537ee..5349b5af 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslCompareNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslCompareNode.java @@ -2,8 +2,6 @@ import foundry.veil.impl.glsl.node.GlslNode; -import java.util.Objects; - /** * Equality; A == B, A != B *
diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslExclusiveOrNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslExclusiveOrNode.java index 85cc41bf..3e9aec98 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslExclusiveOrNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslExclusiveOrNode.java @@ -1,7 +1,6 @@ package foundry.veil.impl.glsl.node.expression; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslTreeVisitor; import java.util.List; import java.util.stream.Collectors; diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslInclusiveOrNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslInclusiveOrNode.java index cc5b1eeb..3b9bb972 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslInclusiveOrNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslInclusiveOrNode.java @@ -1,7 +1,6 @@ package foundry.veil.impl.glsl.node.expression; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslTreeVisitor; import java.util.List; import java.util.stream.Collectors; diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalAndNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalAndNode.java index c6cf2118..e810a421 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalAndNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalAndNode.java @@ -1,7 +1,6 @@ package foundry.veil.impl.glsl.node.expression; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslTreeVisitor; import java.util.List; import java.util.stream.Collectors; diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalOrNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalOrNode.java index 97b9c403..ac3cb4e0 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalOrNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalOrNode.java @@ -1,7 +1,6 @@ package foundry.veil.impl.glsl.node.expression; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslTreeVisitor; import java.util.List; import java.util.stream.Collectors; diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalXorNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalXorNode.java index 8b5cc61a..5e8c27e5 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalXorNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslLogicalXorNode.java @@ -1,7 +1,6 @@ package foundry.veil.impl.glsl.node.expression; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslTreeVisitor; import java.util.List; import java.util.stream.Collectors; diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslUnaryNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslUnaryNode.java index 71c7b8f3..43cc52a6 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslUnaryNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/expression/GlslUnaryNode.java @@ -2,8 +2,6 @@ import foundry.veil.impl.glsl.node.GlslNode; -import java.util.Objects; - public class GlslUnaryNode implements GlslNode { private GlslNode expression; diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionNode.java index 4603ce90..49851ae9 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslFunctionNode.java @@ -7,8 +7,10 @@ import foundry.veil.impl.glsl.visitor.GlslFunctionVisitor; import org.jetbrains.annotations.Nullable; -import java.util.*; -import java.util.stream.Collectors; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; /** * Defines a function in a GLSL file with an optional body. diff --git a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslInvokeFunctionNode.java b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslInvokeFunctionNode.java index 440fab81..4630229a 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslInvokeFunctionNode.java +++ b/common/src/main/java/foundry/veil/impl/glsl/node/function/GlslInvokeFunctionNode.java @@ -1,7 +1,6 @@ package foundry.veil.impl.glsl.node.function; import foundry.veil.impl.glsl.node.GlslNode; -import foundry.veil.impl.glsl.visitor.GlslTreeVisitor; import java.util.ArrayList; import java.util.Collection; diff --git a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslTreeVisitor.java b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslTreeVisitor.java index f7807263..40fd9867 100644 --- a/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslTreeVisitor.java +++ b/common/src/main/java/foundry/veil/impl/glsl/visitor/GlslTreeVisitor.java @@ -1,6 +1,5 @@ package foundry.veil.impl.glsl.visitor; -import foundry.veil.impl.glsl.grammar.GlslStructSpecifier; import foundry.veil.impl.glsl.grammar.GlslVersion; import foundry.veil.impl.glsl.node.function.GlslFunctionNode; import foundry.veil.impl.glsl.node.variable.GlslDeclaration; diff --git a/common/src/test/java/GlslGrammarGenerator.java b/common/src/test/java/GlslGrammarGenerator.java index 6cc01661..249733c8 100644 --- a/common/src/test/java/GlslGrammarGenerator.java +++ b/common/src/test/java/GlslGrammarGenerator.java @@ -1,7 +1,3 @@ -import foundry.veil.impl.glsl.GlslTokenReader; -import foundry.veil.impl.glsl.node.GlslNode; -import org.jetbrains.annotations.Nullable; - import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; From 0c07cfbab40685e8695832ee6077a937c4312631 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Sat, 16 Nov 2024 18:08:53 -0700 Subject: [PATCH 42/47] Fixer cubemap face initialization --- .../render/texture/DynamicCubemapTexture.java | 18 +++++++++++------- .../foundry/veil/mixin/debug/RenderDocker.java | 3 ++- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java b/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java index 229a7522..6cda5481 100644 --- a/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java +++ b/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java @@ -30,6 +30,13 @@ public DynamicCubemapTexture() { this.height = new int[6]; } + private void init(int face, int width, int height) { + this.width[face] = width; + this.height[face] = height; + RenderSystem.assertOnRenderThreadOrInit(); + glTexImage2D(face, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0L); + } + /** * Initializes each face to the same size white texture. * @@ -37,11 +44,6 @@ public DynamicCubemapTexture() { * @param height The height of each face */ public void init(int width, int height) { - for (int i = 0; i < 6; i++) { - this.width[i] = width; - this.height[i] = height; - } - this.bind(); this.setFilter(false, false); GlStateManager._texParameter(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0); @@ -51,7 +53,7 @@ public void init(int width, int height) { RenderSystem.assertOnRenderThreadOrInit(); for (int i = 0; i < 6; i++) { - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0L); + this.init(i, width, height); } } @@ -95,8 +97,10 @@ public void upload(Direction face, NativeImage image) { * @param image The image to upload */ public void upload(int face, NativeImage image) { - if (this.width[face - GL_TEXTURE_CUBE_MAP_POSITIVE_X] != image.getWidth() || this.height[face - GL_TEXTURE_CUBE_MAP_POSITIVE_X] != image.getHeight()) { + if (this.id == -1) { this.init(image.getWidth(), image.getHeight()); + } else if (this.width[face - GL_TEXTURE_CUBE_MAP_POSITIVE_X] != image.getWidth() || this.height[face - GL_TEXTURE_CUBE_MAP_POSITIVE_X] != image.getHeight()) { + this.init(face, image.getWidth(), image.getHeight()); } else { this.bind(); } diff --git a/common/src/main/java/foundry/veil/mixin/debug/RenderDocker.java b/common/src/main/java/foundry/veil/mixin/debug/RenderDocker.java index 99442288..ad15e528 100644 --- a/common/src/main/java/foundry/veil/mixin/debug/RenderDocker.java +++ b/common/src/main/java/foundry/veil/mixin/debug/RenderDocker.java @@ -2,6 +2,7 @@ import foundry.veil.Veil; import foundry.veil.platform.VeilPlatform; +import net.minecraft.Util; import net.minecraft.client.main.Main; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -32,7 +33,7 @@ private static void preMain(String[] pArgs, CallbackInfo ci) { String path = System.getProperty("java.library.path"); String name = System.mapLibraryName("renderdoc"); boolean detected = false; - for (String folder : path.split(";")) { + for (String folder : path.split(Util.getPlatform() == Util.OS.WINDOWS ? ";" : ":")) { if (Files.exists(Path.of(folder + "/" + name))) { detected = true; break; From f20631ca7bc5d961d774844d1ea338753e7c1ef0 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Mon, 18 Nov 2024 11:21:40 -0700 Subject: [PATCH 43/47] Fixed issue with shader limits --- .../api/client/render/VeilRenderSystem.java | 64 +++++++++++-------- .../api/client/render/VeilShaderLimits.java | 10 +-- .../impl/client/editor/DeviceInfoViewer.java | 6 ++ .../resources/assets/veil/lang/en_us.json | 4 ++ 4 files changed, 51 insertions(+), 33 deletions(-) diff --git a/common/src/main/java/foundry/veil/api/client/render/VeilRenderSystem.java b/common/src/main/java/foundry/veil/api/client/render/VeilRenderSystem.java index ffe328e4..b642e770 100644 --- a/common/src/main/java/foundry/veil/api/client/render/VeilRenderSystem.java +++ b/common/src/main/java/foundry/veil/api/client/render/VeilRenderSystem.java @@ -67,15 +67,16 @@ public final class VeilRenderSystem { private static final IntSupplier MAX_UNIFORM_BUFFER_BINDINGS = VeilRenderSystem.glGetter(() -> glGetInteger(GL_MAX_UNIFORM_BUFFER_BINDINGS)); private static final IntSupplier MAX_ATOMIC_COUNTER_BUFFER_BINDINGS = VeilRenderSystem.glGetter(() -> glGetInteger(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)); private static final IntSupplier MAX_SHADER_STORAGE_BUFFER_BINDINGS = VeilRenderSystem.glGetter(() -> glGetInteger(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)); + private static final IntSupplier MAX_ARRAY_TEXTURE_LAYERS = VeilRenderSystem.glGetter(() -> glGetInteger(GL_MAX_ARRAY_TEXTURE_LAYERS)); private static final Supplier VERTEX_SHADER_LIMITS = VeilRenderSystem.glGetter(() -> { GLCapabilities caps = GL.getCapabilities(); return new VeilShaderLimits(caps, - GL_MAX_VERTEX_UNIFORM_COMPONENTS, - GL_MAX_VERTEX_UNIFORM_BLOCKS, - GL_MAX_VERTEX_ATTRIBS * 4, - GL_MAX_VERTEX_OUTPUT_COMPONENTS, - GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, + glGetInteger(GL_MAX_VERTEX_UNIFORM_COMPONENTS), + glGetInteger(GL_MAX_VERTEX_UNIFORM_BLOCKS), + glGetInteger(GL_MAX_VERTEX_ATTRIBS) * 4, + glGetInteger(GL_MAX_VERTEX_OUTPUT_COMPONENTS), + glGetInteger(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS), GL_MAX_VERTEX_IMAGE_UNIFORMS, GL_MAX_VERTEX_ATOMIC_COUNTERS, GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS, @@ -84,11 +85,11 @@ public final class VeilRenderSystem { private static final Supplier GL_TESS_CONTROL_SHADER_LIMITS = VeilRenderSystem.glGetter(() -> { GLCapabilities caps = GL.getCapabilities(); return new VeilShaderLimits(caps, - GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS, - GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS, - GL_MAX_TESS_CONTROL_INPUT_COMPONENTS, - GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS, - GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS, + glGetInteger(GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS), + glGetInteger(GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS), + glGetInteger(GL_MAX_TESS_CONTROL_INPUT_COMPONENTS), + glGetInteger(GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS), + glGetInteger(GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS), GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS, GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS, @@ -97,11 +98,11 @@ public final class VeilRenderSystem { private static final Supplier GL_TESS_EVALUATION_SHADER_LIMITS = VeilRenderSystem.glGetter(() -> { GLCapabilities caps = GL.getCapabilities(); return new VeilShaderLimits(caps, - GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS, - GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS, - GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS, - GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS, - GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS, + glGetInteger(GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS), + glGetInteger(GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS), + glGetInteger(GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS), + glGetInteger(GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS), + glGetInteger(GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS), GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS, GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS, @@ -110,11 +111,11 @@ public final class VeilRenderSystem { private static final Supplier GL_GEOMETRY_SHADER_LIMITS = VeilRenderSystem.glGetter(() -> { GLCapabilities caps = GL.getCapabilities(); return new VeilShaderLimits(caps, - GL_MAX_GEOMETRY_UNIFORM_COMPONENTS, - GL_MAX_GEOMETRY_UNIFORM_BLOCKS, - GL_MAX_GEOMETRY_INPUT_COMPONENTS, - GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, - GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, + glGetInteger(GL_MAX_GEOMETRY_UNIFORM_COMPONENTS), + glGetInteger(GL_MAX_GEOMETRY_UNIFORM_BLOCKS), + glGetInteger(GL_MAX_GEOMETRY_INPUT_COMPONENTS), + glGetInteger(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS), + glGetInteger(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS), GL_MAX_GEOMETRY_IMAGE_UNIFORMS, GL_MAX_GEOMETRY_ATOMIC_COUNTERS, GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS, @@ -123,11 +124,11 @@ public final class VeilRenderSystem { private static final Supplier GL_FRAGMENT_SHADER_LIMITS = VeilRenderSystem.glGetter(() -> { GLCapabilities caps = GL.getCapabilities(); return new VeilShaderLimits(caps, - GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, - GL_MAX_FRAGMENT_UNIFORM_BLOCKS, - GL_MAX_FRAGMENT_INPUT_COMPONENTS, - GL_MAX_DRAW_BUFFERS * 4, - GL_MAX_TEXTURE_IMAGE_UNITS, + glGetInteger(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS), + glGetInteger(GL_MAX_FRAGMENT_UNIFORM_BLOCKS), + glGetInteger(GL_MAX_FRAGMENT_INPUT_COMPONENTS), + glGetInteger(GL_MAX_DRAW_BUFFERS) * 4, + glGetInteger(GL_MAX_TEXTURE_IMAGE_UNITS), GL_MAX_FRAGMENT_IMAGE_UNIFORMS, GL_MAX_FRAGMENT_ATOMIC_COUNTERS, GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, @@ -136,11 +137,11 @@ public final class VeilRenderSystem { private static final Supplier GL_COMPUTE_SHADER_LIMITS = VeilRenderSystem.glGetter(() -> { GLCapabilities caps = GL.getCapabilities(); return new VeilShaderLimits(caps, - GL_MAX_COMPUTE_UNIFORM_COMPONENTS, - GL_MAX_COMPUTE_UNIFORM_BLOCKS, + glGetInteger(GL_MAX_COMPUTE_UNIFORM_COMPONENTS), + glGetInteger(GL_MAX_COMPUTE_UNIFORM_BLOCKS), 0, 0, - GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, + glGetInteger(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS), GL_MAX_COMPUTE_IMAGE_UNIFORMS, GL_MAX_COMPUTE_ATOMIC_COUNTERS, GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, @@ -543,6 +544,13 @@ public static int maxShaderStorageBufferBindings() { return VeilRenderSystem.MAX_SHADER_STORAGE_BUFFER_BINDINGS.getAsInt(); } + /** + * @return The GL maximum number of array texture layers available + */ + public static int maxArrayTextureLayers() { + return VeilRenderSystem.MAX_ARRAY_TEXTURE_LAYERS.getAsInt(); + } + /** * @return The GL maximum width of framebuffers */ diff --git a/common/src/main/java/foundry/veil/api/client/render/VeilShaderLimits.java b/common/src/main/java/foundry/veil/api/client/render/VeilShaderLimits.java index b5eed98c..93779ce1 100644 --- a/common/src/main/java/foundry/veil/api/client/render/VeilShaderLimits.java +++ b/common/src/main/java/foundry/veil/api/client/render/VeilShaderLimits.java @@ -49,11 +49,11 @@ public VeilShaderLimits(GLCapabilities caps, int maxAtomicCounters, int maxAtomicCountBuffers, int maxShaderStorageBlocks) { - this(glGetInteger(maxUniformComponents), - glGetInteger(maxUniformBlocks), - glGetInteger(maxInputComponents), - glGetInteger(maxOutputComponents), - glGetInteger(maxTextureImageUnits), + this(maxUniformComponents, + maxUniformBlocks, + maxInputComponents, + maxOutputComponents, + maxTextureImageUnits, caps.OpenGL42 || caps.GL_ARB_shader_image_load_store ? glGetInteger(maxImageUniforms) : 0, caps.OpenGL42 || caps.GL_ARB_shader_atomic_counters ? glGetInteger(maxAtomicCounters) : 0, caps.OpenGL42 || caps.GL_ARB_shader_atomic_counters ? glGetInteger(maxAtomicCountBuffers) : 0, diff --git a/common/src/main/java/foundry/veil/impl/client/editor/DeviceInfoViewer.java b/common/src/main/java/foundry/veil/impl/client/editor/DeviceInfoViewer.java index 9d35de6f..9abce23d 100644 --- a/common/src/main/java/foundry/veil/impl/client/editor/DeviceInfoViewer.java +++ b/common/src/main/java/foundry/veil/impl/client/editor/DeviceInfoViewer.java @@ -1,5 +1,6 @@ package foundry.veil.impl.client.editor; +import com.mojang.blaze3d.systems.RenderSystem; import foundry.veil.api.client.editor.SingleWindowEditor; import foundry.veil.api.client.imgui.VeilImGuiUtil; import foundry.veil.api.client.render.VeilRenderSystem; @@ -41,6 +42,7 @@ public class DeviceInfoViewer extends SingleWindowEditor { private static final Component GL_TRANSFORM_FEEDBACK = Component.translatable("editor.veil.device_info.opengl.transform_feedback"); private static final Component GL_ATOMIC_COUNTER = Component.translatable("editor.veil.device_info.opengl.atomic_counter"); private static final Component GL_SHADER_STORAGE = Component.translatable("editor.veil.device_info.opengl.shader_storage"); + private static final Component GL_TEXTURE = Component.translatable("editor.veil.device_info.opengl.texture"); private static final Component GL_FRAMEBUFFER = Component.translatable("editor.veil.device_info.opengl.framebuffer"); private static final Component CL_PLATFORMS = Component.translatable("editor.veil.device_info.opencl.platforms"); private static final Component CL_DEVICES = Component.translatable("editor.veil.device_info.opencl.devices"); @@ -166,6 +168,10 @@ private void renderOpenGL() { text("editor.veil.device_info.opengl.shader_storage.max_output_resources", shaderStorageBuffers ? glGetInteger(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES) : null, "The total number of shader storage blocks, image variables, and fragment shader outputs across all active programs cannot exceed this number. This is the \"amount of stuff\" that a sequence of shaders can write to (barring Transform Feedback)."); ImGui.separator(); + title(GL_TEXTURE); + text("editor.veil.device_info.opengl.texture.max_texture_size", RenderSystem.maxSupportedTextureSize(), null); + text("editor.veil.device_info.opengl.texture.max_array_texture_layers", VeilRenderSystem.maxArrayTextureLayers(), null); + title(GL_FRAMEBUFFER); text("editor.veil.device_info.opengl.framebuffer.max_color_attachments", VeilRenderSystem.maxColorAttachments(), null); text("editor.veil.device_info.opengl.framebuffer.max_samples", VeilRenderSystem.maxSamples(), null); diff --git a/common/src/main/resources/assets/veil/lang/en_us.json b/common/src/main/resources/assets/veil/lang/en_us.json index d65d0bff..43c37ecd 100644 --- a/common/src/main/resources/assets/veil/lang/en_us.json +++ b/common/src/main/resources/assets/veil/lang/en_us.json @@ -40,6 +40,7 @@ "editor.veil.device_info.opengl.transform_feedback": "Transform Feedback:", "editor.veil.device_info.opengl.atomic_counter": "Atomic Counter:", "editor.veil.device_info.opengl.shader_storage": "Shader Storage:", + "editor.veil.device_info.opengl.texture": "Texture:", "editor.veil.device_info.opengl.framebuffer": "Framebuffer:", "editor.veil.device_info.opengl.vendor": "Vendor: %s", @@ -80,6 +81,9 @@ "editor.veil.device_info.opengl.shader_storage.max_combined_blocks": "Max Combined Shader Storage Blocks: %s", "editor.veil.device_info.opengl.shader_storage.max_output_resources": "Max Combined Shader Output Resources: %s", + "editor.veil.device_info.opengl.texture.max_texture_size": "Max Texture Size: %1$sx%1$s", + "editor.veil.device_info.opengl.texture.max_array_texture_layers": "Max Array Texture Layers: %s", + "editor.veil.device_info.opengl.framebuffer.max_color_attachments": "Max Framebuffer Color Attachments: %s", "editor.veil.device_info.opengl.framebuffer.max_samples": "Max Framebuffer Samples: %s", From e6f048c0482308a3e41cb4a369e1fee4d8d94530 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Mon, 18 Nov 2024 20:13:32 -0700 Subject: [PATCH 44/47] Added discord to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d9f70d3c..38d48fba 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![Veil 1.20](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fmaven.blamejared.com%2Ffoundry%2Fveil%2FVeil-common-1.20.1%2Fmaven-metadata.xml&label=Veil%201.20)](https://maven.blamejared.com/foundry/veil/Veil-common-1.20.1/) [![Veil 1.20.4](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fmaven.blamejared.com%2Ffoundry%2Fveil%2FVeil-common-1.20.4%2Fmaven-metadata.xml&label=Veil%201.20.4)](https://maven.blamejared.com/foundry/veil/Veil-common-1.20.4/) [![Javadoc](https://img.shields.io/badge/javadoc-latest-blue)](https://foundrymc.github.io/Veil/) +[![Discord](https://img.shields.io/discord/1022254439836430386.svg?label=Discord&logo=discord&color=blue)](https://discord.com/invite/2aqTX9QWKU) Veil is a sophisticated collection of tools and utilities designed to facilitate advanced rendering for Minecraft mod developers. Our goal is to enable more modern game-engine level content in Java Minecraft, pushing the boundaries of what is possible in modding. From d5ee2b4d43c174c41e2b9a787bbe65aa8ea3f49e Mon Sep 17 00:00:00 2001 From: Ocelot Date: Mon, 18 Nov 2024 20:15:01 -0700 Subject: [PATCH 45/47] Formatting --- README.md | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 38d48fba..1f9ed07e 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,11 @@ [![Veil 1.20](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fmaven.blamejared.com%2Ffoundry%2Fveil%2FVeil-common-1.20.1%2Fmaven-metadata.xml&label=Veil%201.20)](https://maven.blamejared.com/foundry/veil/Veil-common-1.20.1/) [![Veil 1.20.4](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fmaven.blamejared.com%2Ffoundry%2Fveil%2FVeil-common-1.20.4%2Fmaven-metadata.xml&label=Veil%201.20.4)](https://maven.blamejared.com/foundry/veil/Veil-common-1.20.4/) [![Javadoc](https://img.shields.io/badge/javadoc-latest-blue)](https://foundrymc.github.io/Veil/) -[![Discord](https://img.shields.io/discord/1022254439836430386.svg?label=Discord&logo=discord&color=blue)](https://discord.com/invite/2aqTX9QWKU) +[![Discord](https://img.shields.io/discord/1022254439836430386.svg?label=Discord&color=blue)](https://discord.com/invite/2aqTX9QWKU) -Veil is a sophisticated collection of tools and utilities designed to facilitate advanced rendering for Minecraft mod developers. Our goal is to enable more modern game-engine level content in Java Minecraft, pushing the boundaries of what is possible in modding. +Veil is a sophisticated collection of tools and utilities designed to facilitate advanced rendering for Minecraft mod +developers. Our goal is to enable more modern game-engine level content in Java Minecraft, pushing the boundaries of +what is possible in modding. ## Features @@ -21,26 +23,34 @@ Veil is a sophisticated collection of tools and utilities designed to facilitate ## Getting Started -Explore our [Example Mod](https://github.com/FoundryMC/veil-example-mod) to see Veil in action and learn how to integrate it into your projects. +Explore our [Example Mod](https://github.com/FoundryMC/veil-example-mod) to see Veil in action and learn how to +integrate it into your projects. For comprehensive documentation and guides, visit our [Veil Developer Wiki](https://github.com/FoundryMC/Veil/wiki). ## Contribution Guidelines -We welcome contributions from the community! Before contributing, please read our [Contributing Guidelines](CONTRIBUTING.md) to understand our processes and ensure your contributions align with the project goals. +We welcome contributions from the community! Before contributing, please read +our [Contributing Guidelines](CONTRIBUTING.md) to understand our processes and ensure your contributions align with the +project goals. ## Code of Conduct -Please note that we expect all contributors to adhere to our [Code of Conduct](CODE_OF_CONDUCT.md). Respectful and constructive interactions are crucial for maintaining a positive and collaborative community. +Please note that we expect all contributors to adhere to our [Code of Conduct](CODE_OF_CONDUCT.md). Respectful and +constructive interactions are crucial for maintaining a positive and collaborative community. ## License -Veil is licensed under the [LGPL License](LICENSE). Feel free to use, modify, and distribute the code as per the terms of the license. +Veil is licensed under the [LGPL License](LICENSE). Feel free to use, modify, and distribute the code as per the terms +of the license. ## Goals -Our primary goal with Veil is to enable the creation of more modern, game engine-level content within Java Minecraft. We strive to provide mod developers with the tools they need to push the boundaries of what is possible in Minecraft modding, bringing new and exciting experiences to players. +Our primary goal with Veil is to enable the creation of more modern, game engine-level content within Java Minecraft. We +strive to provide mod developers with the tools they need to push the boundaries of what is possible in Minecraft +modding, bringing new and exciting experiences to players. ## Contact -If you have any questions, feel free to reach out to us through the issues section on GitHub. We're here to help and appreciate your efforts to improve Veil! +If you have any questions, feel free to reach out to us through the issues section on GitHub. We're here to help and +appreciate your efforts to improve Veil! From d9f82c44d6c98f12e34939dea4ac1f3718f6ab5a Mon Sep 17 00:00:00 2001 From: Ocelot Date: Tue, 19 Nov 2024 10:19:03 -0700 Subject: [PATCH 46/47] Code cleanup --- .../AdvancedFboMutableTextureAttachment.java | 4 -- .../client/quasar/EntityRendererMixin.java | 62 ------------------- .../quasar/FireworkRocketEntityMixin.java | 20 ------ common/src/main/resources/veil.mixins.json | 2 - 4 files changed, 88 deletions(-) delete mode 100644 common/src/main/java/foundry/veil/mixin/client/quasar/EntityRendererMixin.java delete mode 100644 common/src/main/java/foundry/veil/mixin/client/quasar/FireworkRocketEntityMixin.java diff --git a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java index 87c85aee..5d700003 100644 --- a/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java +++ b/common/src/main/java/foundry/veil/api/client/render/framebuffer/AdvancedFboMutableTextureAttachment.java @@ -1,10 +1,6 @@ package foundry.veil.api.client.render.framebuffer; import com.mojang.blaze3d.platform.GlStateManager; -import foundry.veil.Veil; -import foundry.veil.api.client.render.VeilRenderSystem; -import foundry.veil.api.client.render.deferred.VeilDeferredRenderer; -import net.minecraft.client.Minecraft; import org.apache.commons.lang3.Validate; import org.jetbrains.annotations.ApiStatus; diff --git a/common/src/main/java/foundry/veil/mixin/client/quasar/EntityRendererMixin.java b/common/src/main/java/foundry/veil/mixin/client/quasar/EntityRendererMixin.java deleted file mode 100644 index 10696f7f..00000000 --- a/common/src/main/java/foundry/veil/mixin/client/quasar/EntityRendererMixin.java +++ /dev/null @@ -1,62 +0,0 @@ -package foundry.veil.mixin.client.quasar; - -import com.mojang.blaze3d.vertex.PoseStack; -import foundry.veil.api.client.render.VeilRenderSystem; -import foundry.veil.api.quasar.particle.ParticleEmitter; -import foundry.veil.api.quasar.particle.ParticleSystemManager; -import foundry.veil.ext.EntityExtension; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.entity.EntityRenderer; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.Entity; -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(EntityRenderer.class) -public abstract class EntityRendererMixin { - - @Inject(method = "render", at = @At("HEAD")) - public void render(T entity, float pEntityYaw, float pPartialTick, PoseStack pPoseStack, MultiBufferSource pBuffer, int pPackedLight, CallbackInfo ci) { - EntityExtension extension = (EntityExtension) entity; - if (entity.isOnFire()) { - if (extension.veil$getEmitters().isEmpty()) { - ParticleSystemManager particleManager = VeilRenderSystem.renderer().getParticleManager(); - ParticleEmitter instance = particleManager.createEmitter(new ResourceLocation("veil:basic_smoke")); - if (instance == null) { - return; - } - - instance.setAttachedEntity(entity); -// instance.getEmitterSettingsModule().emissionShapeSettings().setDimensions( -// new Vector3f( -// pEntity.getBbWidth(), -// pEntity.getBbHeight(), -// pEntity.getBbWidth() -// ) -// ); -// instance.setLoop(true); -// instance.setMaxLifetime(5); -// instance.getParticleData().getForces().forEach(force -> { -// if (force instanceof PointForce pf) { -// pf.setPoint(pEntity::position); -// } -// }); - // FIXME - extension.veil$addEmitter(instance); - particleManager.addParticleSystem(instance); - } else { -// ((EntityExtension) pEntity).getEmitters().stream().filter(emitter -> emitter.registryName.toString().equals("veil:basic_smoke")).forEach(emitter -> emitter.getEmitterModule().setMaxLifetime(5)); - } - } else { -// ((EntityExtension) pEntity).getEmitters().stream().filter(emitter -> emitter.registryName.toString().equals("veil:basic_smoke")).forEach(p -> p.getEmitterModule().setLoop(false)); - extension.veil$getEmitters().forEach(emitter -> { - if ("veil:basic_smoke".equals(String.valueOf(emitter.getRegistryName()))) { - emitter.remove(); - } - }); - extension.veil$getEmitters().removeIf(emitter -> "veil:basic_smoke".equals(String.valueOf(emitter.getRegistryName()))); - } - } -} diff --git a/common/src/main/java/foundry/veil/mixin/client/quasar/FireworkRocketEntityMixin.java b/common/src/main/java/foundry/veil/mixin/client/quasar/FireworkRocketEntityMixin.java deleted file mode 100644 index 2829b26d..00000000 --- a/common/src/main/java/foundry/veil/mixin/client/quasar/FireworkRocketEntityMixin.java +++ /dev/null @@ -1,20 +0,0 @@ -package foundry.veil.mixin.client.quasar; - -import net.minecraft.world.entity.projectile.FireworkRocketEntity; -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(FireworkRocketEntity.class) -public class FireworkRocketEntityMixin { - - @Inject(method = "handleEntityEvent", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;createFireworks(DDDDDDLnet/minecraft/nbt/CompoundTag;)V"), cancellable = true) - public void handleEntityEvent(byte pId, CallbackInfo ci) { -// FireworkRocketEntity self = (FireworkRocketEntity) (Object) this; -// Vec3 pos = self.position(); -//// ParticleRegistry.runFireworkParticles(new ParticleContext(self.position(), self.getDeltaMovement(), self)); -// self.level().playLocalSound(pos.x, pos.y, pos.z, SoundEvents.FIREWORK_ROCKET_LARGE_BLAST, SoundSource.AMBIENT, 20.0F, 0.95F + self.level().random.nextFloat() * 0.1F, true); -// ci.cancel(); - } -} diff --git a/common/src/main/resources/veil.mixins.json b/common/src/main/resources/veil.mixins.json index ff7459a6..97a4b4bd 100644 --- a/common/src/main/resources/veil.mixins.json +++ b/common/src/main/resources/veil.mixins.json @@ -47,8 +47,6 @@ "client.pipeline.RenderTargetMixin", "client.pipeline.VertexBufferMixin", "client.quasar.EntityMixin", - "client.quasar.EntityRendererMixin", - "client.quasar.FireworkRocketEntityMixin", "client.quasar.ParticleEngineMixin", "client.shader.EffectInstanceMixin", "client.shader.GameRendererMixin", From c06b15ae973edeb081763621971f102eca3ef669 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Fri, 22 Nov 2024 08:49:41 -0700 Subject: [PATCH 47/47] Fixed error while initializing cubemap --- .../veil/api/client/render/texture/DynamicCubemapTexture.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java b/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java index 6cda5481..ac5efb94 100644 --- a/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java +++ b/common/src/main/java/foundry/veil/api/client/render/texture/DynamicCubemapTexture.java @@ -34,7 +34,7 @@ private void init(int face, int width, int height) { this.width[face] = width; this.height[face] = height; RenderSystem.assertOnRenderThreadOrInit(); - glTexImage2D(face, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0L); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0L); } /**