[
  {
    "path": ".gitattributes",
    "content": "# Disable autocrlf on generated files, they always generate with LF\n# Add any extra files or paths here to make git stop saying they\n# are changed when only line endings change.\nsrc/generated/**/.cache/cache text eol=lf\nsrc/generated/**/*.json text eol=lf\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: Build\n\non: [push, pull_request, workflow_dispatch]\n\njobs:\n  build:\n    runs-on: ubuntu-22.04\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Setup Java 21\n        uses: actions/setup-java@v4\n        with:\n          distribution: 'temurin'\n          java-version: 21\n\n      - name: Get Short Identifier\n        uses: benjlevesque/short-sha@v2.2\n        id: short-sha\n\n      - name: Build\n        id: build\n        run: |\n          chmod +x ./gradlew\n          ./gradlew build\n          VERSION_IDENTIFIER=SNAPSHOT+${{ steps.short-sha.outputs.sha }}\n          FILE_NAME=\"$(ls ./build/libs -1 | head -n 1)\"\n          NEW_NAME=\"${FILE_NAME%.jar}-${VERSION_IDENTIFIER}.jar\"\n          mv \"./build/libs/$FILE_NAME\" \"./build/libs/$NEW_NAME\"\n          echo \"artifact_name=$NEW_NAME\" >> \"$GITHUB_OUTPUT\"\n          echo \"artifact_path=./build/libs/$NEW_NAME\" >> \"$GITHUB_OUTPUT\"\n\n      - name: GitHub Action Artifact\n        uses: actions/upload-artifact@v4\n        with:\n          name: ${{ steps.build.outputs.artifact_name }}\n          path: ${{ steps.build.outputs.artifact_path }}\n"
  },
  {
    "path": ".gitignore",
    "content": "# eclipse\nbin\n*.launch\n.settings\n.metadata\n.classpath\n.project\n\n# idea\nout\n*.ipr\n*.iws\n*.iml\n.idea\n\n# gradle\nbuild\n.gradle\n\n# other\neclipse\nrun\nruns\nrun-data\n\nrepo"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2023 Argon4W\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# 加速渲染 ([EN version](#english))\n\n加速渲染是一个客户端实体渲染优化MOD.\n目的是改善在渲染大量实体或拥有大量顶点的复杂MOD实体的情况下产生的渲染性能问题,\n与此同时尽可能与光影MOD和其他MOD及其自定义实体兼容.\n\n![Benchmark](images/benchmark.jpg)\n\n## 🍝赞助\n加速渲染基本由我一人完成, 花费了数千小时对其进行开发和测试, 才得以发布.\n来自广大玩家们的赞助将用于加速渲染后续的更快的开发, 创新和优化, 感谢所有支持者!\n如果你喜欢这个MOD, 并且想要支持加速渲染的开发, 请前往[爱发电](https://afdian.com/a/argon4w)为狐狸买一份意面\n\n## ✨为什么需要这个MOD\n\nMinecraft拥有一个羸弱的, 继承使用OpenGL立即模式的老版本的渲染系统以用来渲染实体和方块实体.\n这个渲染系统会在**CPU**上**单线程**每帧变换和上传实体渲染所需要的顶点.\n这就导致有巨量的时间被浪费在这些单线程执行的操作上, 导致了在渲染大量顶点时CPU其他核心和GPU空闲, 而FPS却十分低的奇异景象.\n\n## ⚙️工作原理\n\n加速渲染构建了一个独特的渲染管线, 将变换前的顶点缓存至模型中, 并在需要渲染时将其提交到GPU使用计算着色器进行多线程并行变换.\n之后使用原本渲染系统中所使用的着色器进行渲染绘制. 通过这个渲染管线, 加速渲染可以在将实体渲染效率大幅提升,\n将CPU压力转移的同时维持对光影MOD的兼容性 (当前兼容Iris Shaders). 并且所有渲染特性都可以被关闭以保证兼容性.\n\n## 🖥️硬件要求\n\n加速渲染因为使用了持久映射缓冲区(Persistently Mapped Buffer)和计算着色器, 因此需要OpenGL 4.6才能正常工作.\n理论上NVIDIA GT 400 Series, Intel HD Graphics 520/530及以上的显卡可以满足这个要求.\n加速渲染已经在发布前在NVIDIA GTX 1660Ti Max-Q, NVIDIA RTX 3070Ti Laptop, NVIDIA RTX 4090 Laptop, RX 580, RX 5600XT上经过测试.\n移动设备目前**不受支持**.\n\n## 🛠️配置\n配置文件可以在``<Minecraft安装位置>/.minecraft/config/acceleratedrendering-client.toml``找到. 你可以通过配置文件修改加速特性或在游戏内进行修改.\n部分特性可能需要重启游戏才能生效. 你可以在``模组 > Accelerated Rendering > 配置``找到游戏内配置编辑器.\n如要让加速物品渲染正常工作, 请在\"核心配置\" (Core Settings) 处开启\"强制加速半透明\" (Force Translucent Acceleration).\n\n<a id=\"english\"></a>\n# AcceleratedRendering\n\nThis is a client side only entity rendering optimization MOD, aiming at improving performance when rendering large amount of entities\nor complex modded entities with significant amount of vertices with compute shaders on GPU while being compatible with shader packs,\nother MODs and their entities.\n\n![Benchmark](images/benchmark.jpg)\n\n## 🍝Sponsorship\n\nThis MOD is almost fully done by myself and took thousands of hours of my own time working and testing on it to be released.\nSponsorships from players can ensure the future development, innovation and optimization of this MOD. Thanks for everyone\nthat support this MOD! If you like it and want to support my work on the development of AcceleratedRendering, please consider sponsoring me at [爱发电](https://afdian.com/a/argon4w)\n\n## ✨Why you need this MOD\n\nMinecraft has a poor immediate rendering system for rendering entities (including block entities) that is inherited from\nOpenGL immediate rendering mode that older versions of Minecraft uses. It transforms and uploads vertices on a **single render thread** on **CPU**\nevery frame the entities are rendered, which results in huge amount of time being spent on these operations and left CPU and GPU idle with a very low FPS\nwhen rendering large amount of vertices.\n\n## ⚙️How it works\n\nAcceleratedRendering constructs a unique rendering pipeline that caches the \"original\" vertices (vertices before the transform)\ninto meshes and transforms them to be parallel in GPU using compute shaders. Then it draws the transformed vertices with the original shader.\nIn this way, this MOD can make entity rendering much more efficient by shifting the transforming stress off from the CPU\nwhile still being compatible with shader packs (currently support Iris Shaders). All acceleration features can be disabled\nfor better compatibility.\n\n## 🖥️Hardware Requirements\n\nAcceleratedRendering requires OpenGL 4.6 to work properly for the usage of persistently mapped buffers and compute shaders.\nGraphics cards like NVIDIA GT 400 Series and Intel HD Graphics 520/530 or newer will fit this requirement.\nThis MOD has been tested on NVIDIA GTX 1660Ti Max-Q, NVIDIA RTX 3070Ti Laptop, NVIDIA RTX 4090 Laptop, RX 580, RX 5600XT.\nMobile devices currently are **not supported**.\n\n## 🛠️Configuration\n\nConfiguration file can be found in ``<your Minecraft>/.minecraft/config/acceleratedrendering-client.toml``. You can modify\nacceleration features in this file or in game (some specific configurations require a game restart to take effect).\nIn-game configuration editor can be found in ``Mods > Accelerated Rendering > Config``.\n\"Force Translucent Acceleration\" in \"Core Settings\" is required to be enabled for accelerated item rendering to work properly.\n"
  },
  {
    "path": "build.gradle",
    "content": "plugins {\n    id 'java-library'\n    id 'eclipse'\n    id 'idea'\n    id 'maven-publish'\n    id 'net.neoforged.gradle.userdev' version '7.0.189'\n}\n\ntasks.named('wrapper', Wrapper).configure {\n    // Define wrapper values here so as to not have to always do so when updating gradlew.properties.\n    // Switching this to Wrapper.DistributionType.ALL will download the full gradle sources that comes with\n    // documentation attached on cursor hover of gradle classes and methods. However, this comes with increased\n    // file size for Gradle. If you do switch this to ALL, run the Gradle wrapper task twice afterwards.\n    // (Verify by checking gradle/wrapper/gradle-wrapper.properties to see if distributionUrl now points to `-all`)\n    distributionType = Wrapper.DistributionType.BIN\n}\n\nversion = mod_version\ngroup = mod_group_id\n\nrepositories {\n    mavenLocal()\n\n    exclusiveContent {\n        forRepository {\n            maven {\n                name = \"Modrinth\"\n                url = \"https://api.modrinth.com/maven\"\n            }\n        }\n        filter {\n            includeGroup \"maven.modrinth\"\n        }\n    }\n\n    maven {\n        url 'https://jitpack.io'\n        content {\n            includeGroup \"com.github.TartaricAcid\"\n        }\n    }\n\n    maven {\n        url \"https://cursemaven.com\"\n        content {\n            includeGroup \"curse.maven\"\n        }\n    }\n}\n\nbase {\n    archivesName = mod_id\n}\n\n// Mojang ships Java 21 to end users starting in 1.20.5, so mods should target Java 21.\njava.toolchain.languageVersion = JavaLanguageVersion.of(21)\n\nminecraft.accessTransformers.file rootProject.file('src/main/resources/META-INF/accesstransformer.cfg')\n//minecraft.accessTransformers.entry public net.minecraft.client.Minecraft textureManager # textureManager\n\n// Default run configurations.\n// These can be tweaked, removed, or duplicated as needed.\nruns {\n    // applies to all the run configs below\n    configureEach {\n        // Recommended logging data for a userdev environment\n        // The markers can be added/remove as needed separated by commas.\n        // \"SCAN\": For mods scan.\n        // \"REGISTRIES\": For firing of registry events.\n        // \"REGISTRYDUMP\": For getting the contents of all registries.\n        systemProperty 'forge.logging.markers', 'REGISTRIES'\n\n        // Recommended logging level for the console\n        // You can set various levels here.\n        // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels\n        systemProperty 'forge.logging.console.level', 'debug'\n\n        modSource project.sourceSets.main\n    }\n\n    client {\n        // Comma-separated list of namespaces to load gametests from. Empty = all namespaces.\n        systemProperty 'forge.enabledGameTestNamespaces', project.mod_id\n    }\n\n    server {\n        systemProperty 'forge.enabledGameTestNamespaces', project.mod_id\n        programArgument '--nogui'\n    }\n\n    // This run config launches GameTestServer and runs all registered gametests, then exits.\n    // By default, the server will crash when no gametests are provided.\n    // The gametest system is also enabled by default for other run configs under the /test command.\n    gameTestServer {\n        systemProperty 'forge.enabledGameTestNamespaces', project.mod_id\n    }\n\n    data {\n        // example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it\n        // workingDirectory project.file('run-data')\n\n        // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.\n        programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()\n    }\n}\n\n// Include resources generated by data generators.\nsourceSets.main.resources { srcDir 'src/generated/resources' }\n\n// Sets up a dependency configuration called 'localRuntime'.\n// This configuration should be used instead of 'runtimeOnly' to declare\n// a dependency that will be present for runtime testing but that is\n// \"optional\", meaning it will not be pulled by dependents of this mod.\nconfigurations {\n    runtimeClasspath.extendsFrom localRuntime\n}\n\ndependencies {\n    // Specify the version of Minecraft to use.\n    // Depending on the plugin applied there are several options. We will assume you applied the userdev plugin as shown above.\n    // The group for userdev is net.neoforged, the module name is neoforge, and the version is the same as the neoforge version.\n    // You can however also use the vanilla plugin (net.neoforged.gradle.vanilla) to use a version of Minecraft without the neoforge loader.\n    // And its provides the option to then use net.minecraft as the group, and one of; client, server or joined as the module name, plus the game version as version.\n    // For all intends and purposes: You can treat this dependency as if it is a normal library you would use.\n    implementation \"net.neoforged:neoforge:${neo_version}\"\n\n    // Example optional mod dependency with JEI\n    // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime\n    // compileOnly \"mezz.jei:jei-${mc_version}-common-api:${jei_version}\"\n    // compileOnly \"mezz.jei:jei-${mc_version}-neoforge-api:${jei_version}\"\n    // We add the full version to localRuntime, not runtimeOnly, so that we do not publish a dependency on it\n    // localRuntime \"mezz.jei:jei-${mc_version}-neoforge:${jei_version}\"\n\n    // Example mod dependency using a mod jar from ./libs with a flat dir repository\n    // This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar\n    // The group id is ignored when searching -- in this case, it is \"blank\"\n    // implementation \"blank:coolmod-${mc_version}:${coolmod_version}\"\n\n    // Example mod dependency using a file as dependency\n    // implementation files(\"libs/coolmod-${mc_version}-${coolmod_version}.jar\")\n\n    // Example project dependency using a sister or child project:\n    // implementation project(\":myproject\")\n\n    // For more info:\n    // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html\n    // http://www.gradle.org/docs/current/userguide/dependency_management.html54\n    implementation \"maven.modrinth:sodium:mc1.21.1-0.6.13-neoforge\"\n    implementation \"maven.modrinth:iris:1.8.8+1.21.1-neoforge\"\n    implementation \"maven.modrinth:jei:YAcQ6elZ\"\n    implementation \"maven.modrinth:modern-ui:3.12.0.2\"\n\n    implementation \"curse.maven:architectury-api-419699:5786327\"\n    implementation \"curse.maven:ftb-teams-forge-404468:7369021\"\n    implementation \"curse.maven:ftb-quests-forge-289412:7429016\"\n    implementation \"curse.maven:certain-questing-additions-1372051:7450467\"\n\n    implementation \"maven.modrinth:kotlin-for-forge:5.11.0\"\n    implementation \"maven.modrinth:elytra-trims:3.9.3\"\n\n    implementation \"maven.modrinth:entitytexturefeatures:7.0.13-neoforge-1.21\"\n    implementation \"maven.modrinth:entity-model-features:3.0.17-neoforge-1.21\"\n    implementation \"maven.modrinth:touhou-little-maid:1.5.0-neoforge+mc1.21.1\"\n    compileOnly \"maven.modrinth:geckolib:QEqpUJ1G\"\n    implementation \"maven.modrinth:immediatelyfast:1.6.8+1.21.1-neoforge\"\n    compileOnly \"maven.modrinth:curios:9.5.1+1.21.1\"\n    implementation \"curse.maven:ftb-library-forge-404465:7420412\"\n    compileOnly \"org.projectlombok:lombok:1.18.38\"\n\n    annotationProcessor \"org.projectlombok:lombok:1.18.38\"\n}\n\n// This block of code expands all declared replace properties in the specified resource targets.\n// A missing property will result in an error. Properties are expanded using ${} Groovy notation.\n// When \"copyIdeResources\" is enabled, this will also run before the game launches in IDE environments.\n// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html\ntasks.withType(ProcessResources).configureEach {\n    var replaceProperties = [\n            minecraft_version      : minecraft_version,\n            minecraft_version_range: minecraft_version_range,\n            neo_version            : neo_version,\n            neo_version_range      : neo_version_range,\n            loader_version_range   : loader_version_range,\n            mod_id                 : mod_id,\n            mod_name               : mod_name,\n            mod_license            : mod_license,\n            mod_version            : mod_version,\n            mod_authors            : mod_authors,\n            mod_description        : mod_description\n    ]\n    inputs.properties replaceProperties\n\n    filesMatching(['META-INF/neoforge.mods.toml']) {\n        expand replaceProperties\n    }\n}\n\n// Example configuration to allow publishing using the maven-publish plugin\npublishing {\n    publications {\n        register('mavenJava', MavenPublication) {\n            from components.java\n        }\n    }\n    repositories {\n        maven {\n            url \"file://${project.projectDir}/repo\"\n        }\n    }\n}\n\ntasks.withType(JavaCompile).configureEach {\n    options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation\n}\n\n// IDEA no longer automatically downloads sources/javadoc jars for dependencies, so we need to explicitly enable the behavior.\nidea {\n    module {\n        downloadSources = true\n        downloadJavadoc = true\n    }\n}\n"
  },
  {
    "path": "changelogs/changelog-1.0.0.md",
    "content": "## 加速渲染 1.0.0-1.21.1 ALPHA\n- 支持加速原版/类原版MOD生物渲染.\n- 支持加速原版/类原版MOD方块实体渲染.\n- 支持加速物品模型渲染 **(需要开启``核心配置 > 强制加速半透明``)**.\n- 支持加速最新版车万女仆渲染.\n- 支持加速GeckoLib模型生物/方块实体渲染.\n\n## Accelerated Rendering 1.0.0-1.21.1 ALPHA\n- Supports acceleration for rendering vanilla entities/vanilla-like modded entities.\n- Supports acceleration for rendering vanilla block entities/vanilla-like modded block entities.\n- Supports acceleration for rendering item models **(``Core Settings > Force Translucent Acceleration`` is required to be enabled)**.\n- Supports acceleration for rendering maids in latest version of Touhou Little Maid.\n- Supports acceleration for rendering GeckoLib entities/block entities."
  },
  {
    "path": "changelogs/changelog-1.0.1.md",
    "content": "## 加速渲染 1.0.1-1.21.1 ALPHA\n- 添加了``核心配置 > 用立即上传模型``选项以保证绘制顺序, 提供更好的兼容性.\n- 添加了``Curios兼容性配置``以控制Curios饰品/装备的渲染加速.\n- 添加了``过滤器设置``以阻止部分在渲染加速后会导致需渲染异常的生物/方块实体被加速, 提供更好的兼容性.\n- 修复了在与Iris环境下将``视频设置... > 图像品质``设置为 ``极佳!``导致的渲染异常.\n\n## Accelerated Rendering 1.0.1-1.21.1 ALPHA\n- Adds ``Core Settings > Enable Uploading Mesh Immediately`` to ensure the draw order for better compatibility.\n- Adds ``Curios Compatibility Settings`` to control the acceleration of curios accessories/equipments.\n- Adds ``Filter Settings`` to filter entities/block entities that will cause glitches when accelerated.\n- Fixes rendering glitches when set ``Video Settings... > Graphics`` to ``Fabulous!`` with Iris installed."
  },
  {
    "path": "changelogs/changelog-1.0.2.md",
    "content": "## 加速渲染 1.0.2-1.21.1 ALPHA\n- 添加了新的Shader Overrides API功能, 以实现更好MOD兼容性.\n- 添加了新的Batching Layer API功能, 以实现更好的MOD兼容性.\n- 添加了``ModelBlockRenderer#renderModel``的渲染加速以支持展示实体渲染加速.\n- 添加了``加速物品渲染配置 > 启用手中物品加速``选项以支持加速在手中物品的渲染加速.\n- 添加了``加速物品渲染配置 > 启用GUI物品加速``选项以支持加速在GUI中物品的渲染加速.\n- 添加了``加速物品渲染配置 > 启用GUI物品合批``选项以支持合并GUI中物品的绘制, 更好的支持在GUI中物品的渲染加速.\n- 添加了``核心配置 > 合批层储存类型``选项以控制是否将半透明和不透明模型合并渲染\n- 添加了``过滤器设置 > 启用物品过滤器``选项以阻止部分在渲染加速后会导致需渲染异常的物品被加速, 提供更好的兼容性.\n- 修复了在Iris环境下开启部分光影包时半透明模型与不透明模型合并渲染导致的半透明模型渲染异常\n- 修复了在ImmediatelyFast环境下渲染HUD时导致的渲染异常.\n- 修复了在机械动力环境下实体与机械动力方块/结构一同出现时导致的渲染异常.\n\n## Accelerated Rendering 1.0.2-1.21.1 ALPHA\n- Adds Shader Overrides API to achieve better MODs compatibility.\n- Adds Batching Layer API to achieve better MODs compatibility.\n- Adds ``ModelBlockRenderer#renderModel`` acceleration support to accelerate rendering of display entities.\n- Adds ``Accelerated Item Rendering Settings > Enable Hand Acceleration`` to support the acceleration of items rendering in hands.\n- Adds ``Accelerated Item Rendering Settings > Enable GUI Acceleration`` to support the acceleration of items rendering in GUI.\n- Adds ``Accelerated Item Rendering Settings > Enable GUI Item Batching`` to support batching draw calls of items in GUI to ensure better acceleration of item rendering in GUI.\n- Adds ``Core Settings > Batching Layer Storage Type`` to control if the pipeline should combine the rendering of opaque and translucent geometries together.\n- Adds ``Filter Settings > Enable Item Filter`` to filter items that will cause glitches when accelerated.\n- Fixes visual glitches on translucent geometries with specific shader pack due to combined rendering of opaque and translucent geometries when Iris is installed.\n- Fixes visual glitches on HUD rendering when ImmediatelyFast is installed.\n- Fixes visual glitches when entities and flywheel accelerated geometries rendering on screen at the same time when Create is installed."
  },
  {
    "path": "changelogs/changelog-1.0.3.md",
    "content": "## 加速渲染 1.0.3-1.21.1 ALPHA\n- 修复了物品装饰 (如通用机械的等级标识) 加速没有正确还原帧缓冲状态导致的渲染异常.\n- 修复了四顶点同UV的面在静态剔除中被错误剔除导致的渲染异常.\n\n## Accelerated Rendering 1.0.3-1.21.1 ALPHA\n- Fixes visual glitches caused by item decoration (like tier in Mekanism) acceleration not restoring FBO state correctly.\n- Fixes visual glitches caused by static culler exceptionally culled quads with same UV on both four vertices."
  },
  {
    "path": "changelogs/changelog-1.0.4.md",
    "content": "## 加速渲染 1.0.4-1.21.1 ALPHA\n- 修复了与使用块缓冲的MOD和光影的兼容性.\n- 移植到1.20.1 Forge.\n\n## 注意事项\n- 1.20.1移植需要使用**Java 21**进行启动.\n- 1.20.1移植的游戏内配置节目需要安装Configured以启用.\n- 1.20.1移植的GeckoLib加速需要安装MixinBooster以启用.\n- 1.20.1移植的车万女仆加速需要安装MixinBooster以启用.\n\n## Accelerated Rendering 1.0.4-1.21.1 ALPHA\n- Fixes compatibility with mods and shaders that uses block buffers.\n- Ports to 1.20.1 Forge.\n\n## Important Notes\n- 1.20.1 port requires **Java 21** to boot.\n- 1.20.1 port requires Configured to modify configurations in game.\n- 1.20.1 port of GeckoLib acceleration requires MixinBooster to enable.\n- 1.20.1 port of TouhouLittleMaid acceleration requires MixinBooster to enable."
  },
  {
    "path": "changelogs/changelog-1.0.5.1.md",
    "content": "## 加速渲染 1.0.5.1-1.21.1 ALPHA\n- 修复了在模型面没有自定义颜色的情况下获取颜色导致崩溃.\n\n## Accelerated Rendering 1.0.5.1-1.21.1 ALPHA\n- Fixes crashes by requesting colors from BakedQuad when the quad is not tinted."
  },
  {
    "path": "changelogs/changelog-1.0.5.md",
    "content": "## 加速渲染 1.0.5-1.21.1 ALPHA\n- 修复了方块模型加速时从错误的位置获取RenderType导致崩溃.\n\n## Accelerated Rendering 1.0.5-1.21.1 ALPHA\n- Fixes crashes by requesting RenderType from wrong place when accelerating block models."
  },
  {
    "path": "changelogs/changelog-1.0.6.md",
    "content": "## 加速渲染 1.0.6-1.21.1 ALPHA\n- 添加了``核心配置 > 启用缓存动态RenderType``选项以支持对动态渲染类型的加速.\n- 添加了``核心配置 > 模型合并类型``选项以支持对完全一致模型的合并以改善显存占用.\n- 改善了过滤器的灵活性, 现在可以在过滤器列表中使用正则表达式.\n- 修复了GUI物品合批时没有正确还原帧缓冲状态导致的渲染异常.\n- 修复了自定义渲染阶段被错误加速导致的渲染异常.\n- 修复了物品附魔光效无法正确渲染导致的渲染异常.\n- 修复了可能的部分特殊物品渲染导致的内存泄漏问题.\n\n## Accelerated Rendering 1.0.6-1.21.1 ALPHA\n- Adds ``Core Settings > Enable Cache Dynamic Render Type`` to support the acceleration of dynamic render types.\n- Adds ``Core Settings > Mesh Merge Type`` to support reducing VRAM usage by merging duplicated meshes together.\n- Improves filter flexibility. Regular Expression can now be used in filter values.\n- Fixes visual glitches on container GUI rendering due to not correctly restoring framebuffer state.\n- Fixes visual glitches on geometries rendered in custom rendering stages due to incorrect acceleration.\n- Fixes visual glitches on item glints.\n- Fixes memory leaks due to acceleration on certain special items."
  },
  {
    "path": "changelogs/changelog-1.0.7.md",
    "content": "## 加速渲染 1.0.7-1.21.1 ALPHA\n- 添加了``过滤器配置 > 启用容器GUI过滤器``选项以阻止部分在渲染加速后会导致需渲染异常的容器GUI被加速, 提供更好的兼容性.\n- 修复了玩家在物品栏GUI中以错误光照渲染导致的渲染异常.\n- 修复了超出标准范围UV的面在静态剔除中被错误剔除导致的渲染异常.\n\n## Accelerated Rendering 1.0.7-1.21.1 ALPHA\n- Adds ``Filter Settings > Enable Menu Filter`` to filter menus that will cause glitches when accelerated.\n- Fixes visual glitches on players rendered with wrong light direction in inventory GUI.\n- Fixes visual glitches on static culler exceptionally culled geometries with UV outside regular range."
  },
  {
    "path": "changelogs/changelog-1.0.8.md",
    "content": "## 加速渲染 1.0.8-1.21.1 ALPHA\n- 添加了``核心配置 > 裁切区域还原类型``选项以提供对修改了容器GUI渲染的MOD更好的兼容性.\n- 添加了``加速物品渲染配置 > 启用合并GUI物品批次``选项以以提供对修改了容器GUI渲染的MOD更好的兼容性.\n- 添加了对FTB Library的GUI物品合批加速支持.\n- 修复了在``earlyWindowControl``不可用的情况下的导致的崩溃.\n- 修复了因为Minecraft因为其他错误没有正确启动导致的无关加速渲染的崩溃.\n- 修复了带状态的EMF模型在运行中修改状态导致的渲染异常.\n- 修复了OpenGL内存屏障被错误使用导致的潜在渲染异常.\n- 阻止MOD添加的自定义HUD进行加速, 防止过度调用着色器导致性能下降.\n\n## Accelerated Rendering 1.0.8-1.21.1 ALPHA\n- Adds ``Core Settings > Scissor Restoring Type`` to provide better compatibility with modified container GUI.\n- Adds ``Accelerated Item Rendering Settings > Enable Merge GUI Item Batches`` to provide better compatibility with modified container GUI.\n- Adds GUI item batching acceleration support to FTB Library.\n- Fixes crashes when ``earlyWindowControl`` is not available.\n- Fixes irrelevant crashes when Minecraft is crashed by other MODs when starting up.\n- Fixes visual glitches when EMF models with states modifying its state at runtime.\n- Fixes potential visual glitches due to incorrect OpenGL memory barrier usages.\n- Prevent custom HUDs by MODs from being accelerated to reduce shader overhead."
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.14.2-bin.zip\nnetworkTimeout=10000\nvalidateDistributionUrl=true\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Sets default memory used for gradle commands. Can be overridden by user or command line properties.\norg.gradle.jvmargs=-Xmx1G\norg.gradle.daemon=false\norg.gradle.debug=false\n\n#read more on this at https://github.com/neoforged/NeoGradle/blob/NG_7.0/README.md#apply-parchment-mappings\n# you can also find the latest versions at: https://parchmentmc.org/docs/getting-started\nneogradle.subsystems.parchment.minecraftVersion=1.21.1\nneogradle.subsystems.parchment.mappingsVersion=2024.11.17\n# Environment Properties\n# You can find the latest versions here: https://projects.neoforged.net/neoforged/neoforge\n# The Minecraft version must agree with the Neo version to get a valid artifact\nminecraft_version=1.21.1\n# The Minecraft version range can use any release version of Minecraft as bounds.\n# Snapshots, pre-releases, and release candidates are not guaranteed to sort properly\n# as they do not follow standard versioning conventions.\nminecraft_version_range=[1.21,1.21.2)\n# The Neo version must agree with the Minecraft version to get a valid artifact\nneo_version=21.1.192\n# The Neo version range can use any version of Neo as bounds\nneo_version_range=[21.0.0,)\n# The loader version range can only use the major version of FML as bounds\nloader_version_range=[4,)\n\n## Mod Properties\n\n# The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63}\n# Must match the String constant located in the main mod class annotated with @Mod.\nmod_id=acceleratedrendering\n# The human-readable display name for the mod.\nmod_name=Accelerated Rendering\n# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.\nmod_license=MIT\n# The mod version. See https://semver.org/\nmod_version=1.0.8-1.21.1-alpha\n# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.\n# This should match the base package used for the mod sources.\n# See https://maven.apache.org/guides/mini/guide-naming-conventions.html\nmod_group_id=com.github.argon4w\n# The authors of the mod. This is a simple text string that is used for display purposes in the mod list.\nmod_authors=Argon4W\n# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list.\nmod_description=Fast vertex transform and caching using compute shader.\n"
  },
  {
    "path": "gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n# SPDX-License-Identifier: Apache-2.0\n#\n\n##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\n# This is normally unused\n# shellcheck disable=SC2034\nAPP_BASE_NAME=${0##*/}\n# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)\nAPP_HOME=$( cd -P \"${APP_HOME:-./}\" > /dev/null && printf '%s\n' \"$PWD\" ) || exit\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    if ! command -v java >/dev/null 2>&1\n    then\n        die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Collect all arguments for the java command:\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,\n#     and any embedded shellness will be escaped.\n#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be\n#     treated as '${Hostname}' itself on the command line.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\n@rem you may not use this file except in compliance with the License.\n@rem You may obtain a copy of the License at\n@rem\n@rem      https://www.apache.org/licenses/LICENSE-2.0\n@rem\n@rem Unless required by applicable law or agreed to in writing, software\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n@rem See the License for the specific language governing permissions and\n@rem limitations under the License.\n@rem\n@rem SPDX-License-Identifier: Apache-2.0\n@rem\n\n@if \"%DEBUG%\"==\"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\n@rem This is normally unused\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif %ERRORLEVEL% equ 0 goto execute\n\necho. 1>&2\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2\necho. 1>&2\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\necho location of your Java installation. 1>&2\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto execute\n\necho. 1>&2\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2\necho. 1>&2\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\necho location of your Java installation. 1>&2\n\ngoto fail\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\n\n:end\n@rem End local scope for the variables with windows NT shell\nif %ERRORLEVEL% equ 0 goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nset EXIT_CODE=%ERRORLEVEL%\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\nexit /b %EXIT_CODE%\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "settings.gradle",
    "content": "pluginManagement {\n    repositories {\n        gradlePluginPortal()\n        maven { url = 'https://maven.neoforged.net/releases' }\n    }\n}\n\nplugins {\n    id 'org.gradle.toolchains.foojay-resolver-convention' version '0.9.0'\n}"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/AcceleratedRenderingModEntry.java",
    "content": "package com.github.argon4w.acceleratedrendering;\n\nimport com.github.argon4w.acceleratedrendering.configs.FeatureConfig;\nimport com.mojang.logging.LogUtils;\nimport net.neoforged.api.distmarker.Dist;\nimport net.neoforged.bus.api.IEventBus;\nimport net.neoforged.fml.ModContainer;\nimport net.neoforged.fml.common.Mod;\nimport net.neoforged.fml.config.ModConfig;\nimport net.neoforged.neoforge.client.gui.ConfigurationScreen;\nimport net.neoforged.neoforge.client.gui.IConfigScreenFactory;\nimport org.slf4j.Logger;\n\n@Mod(\n\t\tvalue\t= AcceleratedRenderingModEntry\t.MOD_ID,\n\t\tdist\t= Dist\t\t\t\t\t\t\t.CLIENT\n)\npublic class AcceleratedRenderingModEntry {\n\n\tpublic static final String MOD_ID = \"acceleratedrendering\";\n\tpublic static final Logger LOGGER = LogUtils.getLogger();\n\n\tpublic AcceleratedRenderingModEntry(IEventBus modEventBus, ModContainer modContainer) {\n\t\tmodContainer.registerConfig\t\t\t(ModConfig.Type.CLIENT,\t\t\tFeatureConfig.SPEC);\n\t\tmodContainer.registerExtensionPoint\t(IConfigScreenFactory.class,\tConfigurationScreen::new);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/AbstractCompatMixinPlugin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat;\n\nimport net.neoforged.fml.loading.LoadingModList;\nimport org.objectweb.asm.tree.ClassNode;\nimport org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;\nimport org.spongepowered.asm.mixin.extensibility.IMixinInfo;\n\nimport java.util.List;\nimport java.util.Set;\n\npublic abstract class AbstractCompatMixinPlugin implements IMixinConfigPlugin {\n\n\tprivate final boolean shouldApply;\n\n\tpublic AbstractCompatMixinPlugin() {\n\t\tvar shouldApply\t= false;\n\n\t\tfor (var id : getModIDs()) {\n\t\t\tif (LoadingModList.get().getModFileById(id) != null) {\n\t\t\t\tshouldApply = true;\n\t\t\t}\n\t\t}\n\n\t\tthis.shouldApply = shouldApply;\n\t}\n\n\tprotected abstract List<String> getModIDs();\n\n\t@Override\n\tpublic boolean shouldApplyMixin(String targetClassName, String mixinClassName) {\n\t\treturn shouldApply;\n\t}\n\n\t@Override\n\tpublic String getRefMapperConfig() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic List<String> getMixins() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void onLoad(String mixinPackage) {\n\n\t}\n\n\t@Override\n\tpublic void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {\n\n\t}\n\n\t@Override\n\tpublic void preApply(\n\t\t\tString\t\ttargetClassName,\n\t\t\tClassNode\ttargetClass,\n\t\t\tString\t\tmixinClassName,\n\t\t\tIMixinInfo\tmixinInfo\n\t) {\n\n\t}\n\n\t@Override\n\tpublic void postApply(\n\t\t\tString\t\ttargetClassName,\n\t\t\tClassNode\ttargetClass,\n\t\t\tString\t\tmixinClassName,\n\t\t\tIMixinInfo\tmixinInfo\n\t) {\n\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/curios/CuriosCompatFeature.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.curios;\n\nimport com.github.argon4w.acceleratedrendering.configs.FeatureConfig;\nimport com.github.argon4w.acceleratedrendering.configs.FeatureStatus;\nimport com.github.argon4w.acceleratedrendering.core.utils.RegistryFilter;\nimport com.github.argon4w.acceleratedrendering.features.filter.FilterType;\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\n\nimport java.util.ArrayDeque;\nimport java.util.Deque;\nimport java.util.Set;\n\npublic class CuriosCompatFeature {\n\n\tpublic\tstatic final Deque\t<FeatureStatus> LAYER_ACCELERATION_CONTROLLER_STACK\t= new ArrayDeque<>();\n\tpublic\tstatic final Deque\t<FeatureStatus> CURIOS_ITEM_FILTER_CONTROLLER_STACK\t= new ArrayDeque<>();\n\tprivate\tstatic final Set\t<Item>\t\t\tCURIOS_ITEM_FILTER_VALUES;\n\n\tstatic {\n\t\tCURIOS_ITEM_FILTER_VALUES = RegistryFilter.filterValues(BuiltInRegistries.ITEM, FeatureConfig.CONFIG.curiosItemFilterValues.get());\n\t}\n\n\tpublic static boolean isEnabled() {\n\t\treturn FeatureConfig.CONFIG.curiosCompatFeatureStatus.get() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean testCuriosItem(ItemStack itemStack) {\n\t\treturn getCuriosItemFilterType().test(CURIOS_ITEM_FILTER_VALUES, itemStack.getItem());\n\t}\n\n\tpublic static boolean shouldAccelerateCurios() {\n\t\treturn getLayerAccelerationSetting() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean shouldFilterCuriosItems() {\n\t\treturn getCuriosItemFilterSetting() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static FilterType getCuriosItemFilterType() {\n\t\treturn FeatureConfig.CONFIG.curiosItemFilterType.get();\n\t}\n\n\tpublic static void disableLayerAcceleration() {\n\t\tLAYER_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.DISABLED);\n\t}\n\n\tpublic static void disableCuriosItemFilter() {\n\t\tCURIOS_ITEM_FILTER_CONTROLLER_STACK.push(FeatureStatus.DISABLED);\n\t}\n\n\tpublic static void forceEnableLayerAcceleration() {\n\t\tLAYER_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.ENABLED);\n\t}\n\n\tpublic static void forceEnableCuriosItemFilter() {\n\t\tCURIOS_ITEM_FILTER_CONTROLLER_STACK.push(FeatureStatus.ENABLED);\n\t}\n\n\tpublic static void forceSetLayerAcceleration(FeatureStatus status) {\n\t\tLAYER_ACCELERATION_CONTROLLER_STACK.push(status);\n\t}\n\n\tpublic static void forceSetCuriosItemFilter(FeatureStatus status) {\n\t\tCURIOS_ITEM_FILTER_CONTROLLER_STACK.push(status);\n\t}\n\n\tpublic static void resetLayerAcceleration() {\n\t\tLAYER_ACCELERATION_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static void resetCuriosItemFilter() {\n\t\tCURIOS_ITEM_FILTER_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static FeatureStatus getLayerAccelerationSetting() {\n\t\treturn LAYER_ACCELERATION_CONTROLLER_STACK.isEmpty() ? getDefaultLayerAccelerationSettings() : LAYER_ACCELERATION_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static FeatureStatus getCuriosItemFilterSetting() {\n\t\treturn CURIOS_ITEM_FILTER_CONTROLLER_STACK.isEmpty() ? getDefaultCuriosItemFilterSetting() : CURIOS_ITEM_FILTER_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static FeatureStatus getDefaultLayerAccelerationSettings() {\n\t\treturn FeatureConfig.CONFIG.curiosCompatLayerAcceleration.get();\n\t}\n\n\tpublic static FeatureStatus getDefaultCuriosItemFilterSetting() {\n\t\treturn FeatureConfig.CONFIG.curiosItemFilter.get();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/curios/mixins/CuriosLayerMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.curios.mixins;\n\nimport com.github.argon4w.acceleratedrendering.compat.curios.CuriosCompatFeature;\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.filter.FilterFeature;\nimport com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport net.minecraft.client.renderer.MultiBufferSource;\nimport net.minecraft.client.renderer.entity.RenderLayerParent;\nimport net.minecraft.world.entity.LivingEntity;\nimport net.minecraft.world.item.ItemStack;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Pseudo;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\nimport top.theillusivec4.curios.api.SlotContext;\nimport top.theillusivec4.curios.api.client.ICurioRenderer;\nimport top.theillusivec4.curios.client.render.CuriosLayer;\n\n@Pseudo\n@Mixin(CuriosLayer.class)\npublic class CuriosLayerMixin {\n\n\t@Inject(\n\t\t\tmethod\t= \"render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/world/entity/LivingEntity;FFFFFF)V\",\n\t\t\tat\t\t= @At(\"HEAD\")\n\t)\n\tpublic void startRenderCuriosLayer(\n\t\t\tPoseStack\t\t\tmatrixStack,\n\t\t\tMultiBufferSource\trenderTypeBuffer,\n\t\t\tint\t\t\t\t\tlight,\n\t\t\tLivingEntity\t\tlivingEntity,\n\t\t\tfloat\t\t\t\tlimbSwing,\n\t\t\tfloat\t\t\t\tlimbSwingAmount,\n\t\t\tfloat\t\t\t\tpartialTicks,\n\t\t\tfloat\t\t\t\tageInTicks,\n\t\t\tfloat\t\t\t\tnetHeadYaw,\n\t\t\tfloat\t\t\t\theadPitch,\n\t\t\tCallbackInfo\t\tci\n\t) {\n\t\tif (\t\t\tCuriosCompatFeature.isEnabled\t\t\t\t()\n\t\t\t\t&&\t!\tCuriosCompatFeature.shouldAccelerateCurios\t()\n\t\t) {\n\t\t\tAcceleratedEntityRenderingFeature\t.useVanillaPipeline();\n\t\t\tAcceleratedItemRenderingFeature\t\t.useVanillaPipeline();\n\t\t\tAcceleratedTextRenderingFeature\t\t.useVanillaPipeline();\n\t\t}\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/world/entity/LivingEntity;FFFFFF)V\",\n\t\t\tat\t\t= @At(\"RETURN\")\n\t)\n\tpublic void stopRenderCuriosLayer(\n\t\t\tPoseStack\t\t\tmatrixStack,\n\t\t\tMultiBufferSource\trenderTypeBuffer,\n\t\t\tint\t\t\t\t\tlight,\n\t\t\tLivingEntity\t\tlivingEntity,\n\t\t\tfloat\t\t\t\tlimbSwing,\n\t\t\tfloat\t\t\t\tlimbSwingAmount,\n\t\t\tfloat\t\t\t\tpartialTicks,\n\t\t\tfloat\t\t\t\tageInTicks,\n\t\t\tfloat\t\t\t\tnetHeadYaw,\n\t\t\tfloat\t\t\t\theadPitch,\n\t\t\tCallbackInfo\t\tci\n\t) {\n\t\tif (\t\t\tCuriosCompatFeature.isEnabled\t\t\t\t()\n\t\t\t\t&&\t!\tCuriosCompatFeature.shouldAccelerateCurios\t()\n\t\t) {\n\t\t\tAcceleratedEntityRenderingFeature\t.resetPipeline();\n\t\t\tAcceleratedItemRenderingFeature\t\t.resetPipeline();\n\t\t\tAcceleratedTextRenderingFeature\t\t.resetPipeline();\n\t\t}\n\t}\n\n\t@WrapOperation(\n\t\t\tmethod\t= \"lambda$render$0\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Ltop/theillusivec4/curios/api/client/ICurioRenderer;render(Lnet/minecraft/world/item/ItemStack;Ltop/theillusivec4/curios/api/SlotContext;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/entity/RenderLayerParent;Lnet/minecraft/client/renderer/MultiBufferSource;IFFFFFF)V\"\n\t\t\t)\n\t)\n\tpublic void filterCuriosItem(\n\t\t\tICurioRenderer\t\t\tinstance,\n\t\t\tItemStack\t\t\t\titemStack,\n\t\t\tSlotContext\t\t\t\tslotContext,\n\t\t\tPoseStack\t\t\t\tposeStack,\n\t\t\tRenderLayerParent<?, ?>\trenderLayerParent,\n\t\t\tMultiBufferSource\t\tbufferSource,\n\t\t\tint\t\t\t\t\t\tlight,\n\t\t\tfloat\t\t\t\t\tlimbSwing,\n\t\t\tfloat\t\t\t\t\tlimbSwingAmount,\n\t\t\tfloat\t\t\t\t\tpartialTicks,\n\t\t\tfloat\t\t\t\t\tageInTicks,\n\t\t\tfloat\t\t\t\t\tnetHeadYaw,\n\t\t\tfloat\t\t\t\t\theadPitch,\n\t\t\tOperation<Void>\t\t\toriginal\n\t) {\n\t\tvar pass =\t!\tFilterFeature\t\t.isEnabled\t\t\t\t()\n\t\t\t\t||\t!\tCuriosCompatFeature\t.isEnabled\t\t\t\t()\n\t\t\t\t||\t!\tCuriosCompatFeature\t.shouldFilterCuriosItems()\n\t\t\t\t||\t\tCuriosCompatFeature\t.testCuriosItem\t\t\t(itemStack);\n\n\t\tif (!pass) {\n\t\t\tAcceleratedEntityRenderingFeature\t.useVanillaPipeline();\n\t\t\tAcceleratedItemRenderingFeature\t\t.useVanillaPipeline();\n\t\t\tAcceleratedTextRenderingFeature\t\t.useVanillaPipeline();\n\t\t}\n\n\t\toriginal.call(\n\t\t\t\tinstance,\n\t\t\t\titemStack,\n\t\t\t\tslotContext,\n\t\t\t\tposeStack,\n\t\t\t\trenderLayerParent,\n\t\t\t\tbufferSource,\n\t\t\t\tlight,\n\t\t\t\tlimbSwing,\n\t\t\t\tlimbSwingAmount,\n\t\t\t\tpartialTicks,\n\t\t\t\tageInTicks,\n\t\t\t\tnetHeadYaw,\n\t\t\t\theadPitch\n\t\t);\n\n\t\tif (!pass) {\n\t\t\tAcceleratedEntityRenderingFeature\t.resetPipeline();\n\t\t\tAcceleratedItemRenderingFeature\t\t.resetPipeline();\n\t\t\tAcceleratedTextRenderingFeature\t\t.resetPipeline();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/immediatelyfast/mixins/BatchableBufferSourceMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.immediatelyfast.mixins;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratableBufferSource;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.llamalad7.mixinextras.injector.ModifyReturnValue;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.RenderType;\nimport net.raphimc.immediatelyfast.feature.core.BatchableBufferSource;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Pseudo;\nimport org.spongepowered.asm.mixin.injection.At;\n\n@Pseudo\n@ExtensionMethod(VertexConsumerExtension.class)\n@Mixin\t\t\t(BatchableBufferSource\t.class)\npublic abstract class BatchableBufferSourceMixin implements IAcceleratableBufferSource {\n\n\t@ModifyReturnValue(\n\t\t\tmethod\t= \"getBuffer\",\n\t\t\tat\t\t= @At(\"RETURN\")\n\t)\n\tpublic VertexConsumer initAcceleration(VertexConsumer original, RenderType renderType) {\n\t\treturn original\n\t\t\t\t.getHolder\t\t\t()\n\t\t\t\t.initAcceleration\t(renderType, getBoundAcceleratedBufferSource());\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/immediatelyfast/mixins/BatchingBuffersMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.immediatelyfast.mixins;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreBuffersProvider;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.BufferSourceExtension;\nimport com.llamalad7.mixinextras.injector.ModifyReturnValue;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.MultiBufferSource;\nimport net.raphimc.immediatelyfast.feature.batching.BatchingBuffers;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Pseudo;\nimport org.spongepowered.asm.mixin.injection.At;\n\n@Pseudo\n@ExtensionMethod(BufferSourceExtension\t.class)\n@Mixin\t\t\t(BatchingBuffers\t\t.class)\npublic class BatchingBuffersMixin {\n\n\t@ModifyReturnValue(\n\t\t\tmethod\t= \"getNonBatchingEntityVertexConsumers\",\n\t\t\tat\t\t= @At(\"RETURN\")\n\t)\n\tprivate static MultiBufferSource.BufferSource bindAcceleratableBufferSourceCore1(MultiBufferSource.BufferSource original) {\n\t\toriginal\n\t\t\t\t.getAcceleratable\t\t\t()\n\t\t\t\t.bindAcceleratedBufferSource(CoreBuffersProvider.CORE);\n\n\t\treturn original;\n\t}\n\n\t@ModifyReturnValue(\n\t\t\tmethod\t= \"getHudBatchingVertexConsumers\",\n\t\t\tat\t\t= @At(\"RETURN\")\n\t)\n\tprivate static MultiBufferSource.BufferSource bindAcceleratableBufferSourceCore2(MultiBufferSource.BufferSource original) {\n\t\toriginal\n\t\t\t\t.getAcceleratable\t\t\t()\n\t\t\t\t.bindAcceleratedBufferSource(CoreBuffersProvider.CORE);\n\n\t\treturn original;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/immediatelyfast/mixins/WrappedRenderLayerMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.immediatelyfast.mixins;\n\nimport lombok.EqualsAndHashCode;\nimport net.minecraft.client.renderer.RenderType;\nimport net.raphimc.immediatelyfast.feature.batching.BatchingBuffers;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Pseudo;\nimport org.spongepowered.asm.mixin.Unique;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@Pseudo\n@EqualsAndHashCode\n@Mixin(BatchingBuffers.WrappedRenderLayer.class)\npublic class WrappedRenderLayerMixin {\n\n\t@Unique private RenderType original;\n\n\t@Inject(\n\t\t\tmethod\t= \"<init>\",\n\t\t\tat\t\t= @At(\"TAIL\")\n\t)\n\tpublic void saveOriginal(\n\t\t\tRenderType\t\trenderLayer,\n\t\t\tRunnable\t\tadditionalStartAction,\n\t\t\tRunnable\t\tadditionalEndAction,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tthis.original = renderLayer;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/IrisCompatBuffers.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.AcceleratedBufferSources;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.AcceleratedBufferSource;\nimport com.github.argon4w.acceleratedrendering.core.buffers.environments.IBufferEnvironment;\nimport com.mojang.blaze3d.vertex.VertexFormat;\n\npublic class IrisCompatBuffers {\n\n\tpublic static final AcceleratedBufferSource BLOCK_SHADOW\t\t\t\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.BLOCK);\n\tpublic static final AcceleratedBufferSource ENTITY_SHADOW\t\t\t\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.ENTITY);\n\tpublic static final AcceleratedBufferSource GLYPH_SHADOW\t\t\t\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_COLOR_TEX_LIGHT);\n\tpublic static final AcceleratedBufferSource POS_TEX_SHADOW\t\t\t\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_TEX);\n\tpublic static final AcceleratedBufferSource POS_TEX_COLOR_SHADOW\t\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_TEX_COLOR);\n\n\tpublic static final AcceleratedBufferSource BLOCK_HAND\t\t\t\t\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.BLOCK);\n\tpublic static final AcceleratedBufferSource ENTITY_HAND\t\t\t\t\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.ENTITY);\n\tpublic static final AcceleratedBufferSource\tPOS_HAND\t\t\t\t\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.POS);\n\tpublic static final AcceleratedBufferSource\tPOS_COLOR_HAND\t\t\t\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_COLOR);\n\tpublic static final AcceleratedBufferSource POS_TEX_HAND\t\t\t\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_TEX);\n\tpublic static final AcceleratedBufferSource POS_TEX_COLOR_HAND\t\t\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_TEX_COLOR);\n\tpublic static final AcceleratedBufferSource POS_COLOR_TEX_LIGHT_HAND\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_COLOR_TEX_LIGHT);\n\n\tpublic static final AcceleratedBufferSources HAND = AcceleratedBufferSources\n\t\t\t.builder()\n\t\t\t.source\t(IrisCompatBuffers\t.BLOCK_HAND)\n\t\t\t.source\t(IrisCompatBuffers\t.ENTITY_HAND)\n\t\t\t.source\t(IrisCompatBuffers\t.POS_HAND)\n\t\t\t.source\t(IrisCompatBuffers\t.POS_COLOR_HAND)\n\t\t\t.source\t(IrisCompatBuffers\t.POS_TEX_HAND)\n\t\t\t.source\t(IrisCompatBuffers\t.POS_TEX_COLOR_HAND)\n\t\t\t.source\t(IrisCompatBuffers\t.POS_COLOR_TEX_LIGHT_HAND)\n\t\t\t.mode\t(VertexFormat.Mode\t.QUADS)\n\t\t\t.mode\t(VertexFormat.Mode\t.TRIANGLES)\n\t\t\t.build\t();\n\n\tpublic static final AcceleratedBufferSources SHADOW = AcceleratedBufferSources\n\t\t\t.builder()\n\t\t\t.source\t(IrisCompatBuffers.BLOCK_SHADOW)\n\t\t\t.source\t(IrisCompatBuffers.ENTITY_SHADOW)\n\t\t\t.source\t(IrisCompatBuffers.GLYPH_SHADOW)\n\t\t\t.source\t(IrisCompatBuffers.POS_TEX_SHADOW)\n\t\t\t.source\t(IrisCompatBuffers.POS_TEX_COLOR_SHADOW)\n\t\t\t.mode\t(VertexFormat.Mode.QUADS)\n\t\t\t.mode\t(VertexFormat.Mode.TRIANGLES)\n\t\t\t.build\t();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/IrisCompatBuffersProvider.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAcceleratedBufferSource;\n\nimport java.util.function.Supplier;\n\npublic class IrisCompatBuffersProvider {\n\n\tpublic static final Supplier<IAcceleratedBufferSource> SHADOW\t= () -> IrisCompatBuffers.SHADOW;\n\tpublic static final Supplier<IAcceleratedBufferSource> HAND\t\t= () -> IrisCompatBuffers.HAND;\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/IrisCompatFeature.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris;\n\nimport com.github.argon4w.acceleratedrendering.configs.FeatureConfig;\nimport com.github.argon4w.acceleratedrendering.configs.FeatureStatus;\n\nimport java.util.ArrayDeque;\nimport java.util.Deque;\n\npublic class IrisCompatFeature {\n\n\tpublic static final Deque<FeatureStatus> SHADOW_CULLING_CONTROLLER_STACK\t\t= new ArrayDeque<>();\n\tpublic static final Deque<FeatureStatus> POLYGON_PROCESSING_CONTROLLER_STACK\t= new ArrayDeque<>();\n\n\tpublic static boolean isEnabled() {\n\t\treturn FeatureConfig.CONFIG.irisCompatFeatureStatus.get() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean isIrisCompatCullingEnabled() {\n\t\treturn FeatureConfig.CONFIG.irisCompatOrientationCullingCompat.get() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean isShadowCullingEnabled() {\n\t\treturn getShadowCullingSetting() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean isPolygonProcessingEnabled() {\n\t\treturn getPolygonProcessingSetting() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static void disableShadowCulling() {\n\t\tSHADOW_CULLING_CONTROLLER_STACK.push(FeatureStatus.DISABLED);\n\t}\n\n\tpublic static void disablePolygonProcessing() {\n\t\tPOLYGON_PROCESSING_CONTROLLER_STACK.push(FeatureStatus.DISABLED);\n\t}\n\n\tpublic static void forceEnableShadowCulling() {\n\t\tSHADOW_CULLING_CONTROLLER_STACK.push(FeatureStatus.ENABLED);\n\t}\n\n\tpublic static void forceEnablePolygonProcessing() {\n\t\tPOLYGON_PROCESSING_CONTROLLER_STACK.push(FeatureStatus.ENABLED);\n\t}\n\n\tpublic static void forceSetShadowCulling(FeatureStatus status) {\n\t\tSHADOW_CULLING_CONTROLLER_STACK.push(status);\n\t}\n\n\tpublic static void forceSetIrisPolygonProcessing(FeatureStatus status) {\n\t\tPOLYGON_PROCESSING_CONTROLLER_STACK.push(status);\n\t}\n\n\tpublic static void resetShadowCulling() {\n\t\tSHADOW_CULLING_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static void resetPolygonProcessing() {\n\t\tPOLYGON_PROCESSING_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static FeatureStatus getShadowCullingSetting() {\n\t\treturn SHADOW_CULLING_CONTROLLER_STACK.isEmpty() ? getDefaultShadowCullingSetting() : SHADOW_CULLING_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static FeatureStatus getPolygonProcessingSetting() {\n\t\treturn POLYGON_PROCESSING_CONTROLLER_STACK.isEmpty() ? getDefaultPolygonProcessingSetting() : POLYGON_PROCESSING_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static FeatureStatus getDefaultShadowCullingSetting() {\n\t\treturn FeatureConfig.CONFIG.irisCompatShadowCulling.get();\n\t}\n\n\tpublic static FeatureStatus getDefaultPolygonProcessingSetting() {\n\t\treturn FeatureConfig.CONFIG.irisCompatPolygonProcessing.get();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/environments/IrisBufferEnvironment.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.environments;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.buffers.IServerBuffer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.environments.IBufferEnvironment;\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout;\nimport com.github.argon4w.acceleratedrendering.core.meshes.ServerMesh;\nimport com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramSelector;\nimport com.github.argon4w.acceleratedrendering.core.programs.culling.LoadCullingProgramSelectorEvent;\nimport com.github.argon4w.acceleratedrendering.core.programs.dispatchers.IPolygonProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.programs.dispatchers.MeshUploadingProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.programs.dispatchers.TransformProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.programs.overrides.IShaderProgramOverrides;\nimport com.github.argon4w.acceleratedrendering.core.programs.overrides.ITransformShaderProgramOverride;\nimport com.github.argon4w.acceleratedrendering.core.programs.overrides.IUploadingShaderProgramOverride;\nimport com.github.argon4w.acceleratedrendering.core.programs.overrides.LoadShaderProgramOverridesEvent;\nimport com.github.argon4w.acceleratedrendering.core.programs.processing.IPolygonProcessor;\nimport com.github.argon4w.acceleratedrendering.core.programs.processing.LoadPolygonProcessorEvent;\nimport com.mojang.blaze3d.vertex.VertexFormat;\nimport net.irisshaders.iris.api.v0.IrisApi;\nimport net.irisshaders.iris.vertices.ImmediateState;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.fml.ModLoader;\n\nimport java.util.Set;\n\npublic class IrisBufferEnvironment implements IBufferEnvironment {\n\n\tprivate final IBufferEnvironment vanillaSubSet;\n\tprivate final IBufferEnvironment irisSubSet;\n\n\tpublic IrisBufferEnvironment(\n\t\t\tIBufferEnvironment\tvanillaSubSet,\n\t\t\tVertexFormat\t\tvanillaVertexFormat,\n\t\t\tVertexFormat\t\tirisVertexFormat,\n\t\t\tResourceLocation\tmeshUploadingProgramKey,\n\t\t\tResourceLocation\ttransformProgramKey\n\t) {\n\t\tthis.vanillaSubSet\t= vanillaSubSet;\n\t\tthis.irisSubSet\t\t= new IrisSubSet(\n\t\t\t\tvanillaVertexFormat,\n\t\t\t\tirisVertexFormat,\n\t\t\t\tmeshUploadingProgramKey,\n\t\t\t\ttransformProgramKey\n\t\t);\n\t}\n\n\tprivate IBufferEnvironment getSubSet() {\n\t\treturn IrisApi.getInstance().isShaderPackInUse() && ImmediateState.isRenderingLevel ? irisSubSet : vanillaSubSet;\n\t}\n\n\t@Override\n\tpublic void setupBufferState() {\n\t\tgetSubSet().setupBufferState();\n\t}\n\n\t@Override\n\tpublic Set<VertexFormat> getVertexFormats() {\n\t\treturn irisSubSet.getVertexFormats();\n\t}\n\n\t@Override\n\tpublic VertexLayout getLayout() {\n\t\treturn getSubSet().getLayout();\n\t}\n\n\t@Override\n\tpublic IServerBuffer getImmediateMeshBuffer() {\n\t\treturn getSubSet().getImmediateMeshBuffer();\n\t}\n\n\t@Override\n\tpublic ITransformShaderProgramOverride getTransformProgramOverride(RenderType renderType) {\n\t\treturn getSubSet().getTransformProgramOverride(renderType);\n\t}\n\n\t@Override\n\tpublic IUploadingShaderProgramOverride getUploadingProgramOverride(RenderType renderType) {\n\t\treturn getSubSet().getUploadingProgramOverride(renderType);\n\t}\n\n\t@Override\n\tpublic MeshUploadingProgramDispatcher selectMeshUploadingProgramDispatcher() {\n\t\treturn getSubSet().selectMeshUploadingProgramDispatcher();\n\t}\n\n\t@Override\n\tpublic TransformProgramDispatcher selectTransformProgramDispatcher() {\n\t\treturn getSubSet().selectTransformProgramDispatcher();\n\t}\n\n\t@Override\n\tpublic ICullingProgramDispatcher selectCullingProgramDispatcher(RenderType renderType) {\n\t\treturn getSubSet().selectCullingProgramDispatcher(renderType);\n\t}\n\n\t@Override\n\tpublic IPolygonProgramDispatcher selectProcessingProgramDispatcher(VertexFormat.Mode mode) {\n\t\treturn getSubSet().selectProcessingProgramDispatcher(mode);\n\t}\n\n\t@Override\n\tpublic boolean isAccelerated(VertexFormat vertexFormat) {\n\t\treturn getSubSet().isAccelerated(vertexFormat);\n\t}\n\n\t@Override\n\tpublic int getVertexSize() {\n\t\treturn getSubSet().getVertexSize();\n\t}\n\n\tpublic static class IrisSubSet implements IBufferEnvironment {\n\n\t\tprivate final VertexFormat\t\t\t\t\t\tvanillaVertexFormat;\n\t\tprivate final VertexFormat\t\t\t\t\t\tirisVertexFormat;\n\t\tprivate final VertexLayout\t\t\t\t\t\tlayout;\n\n\t\tprivate final IShaderProgramOverrides\t\t\tshaderProgramOverrides;\n\t\tprivate final MeshUploadingProgramDispatcher\tmeshUploadingProgramDispatcher;\n\t\tprivate final TransformProgramDispatcher\t\ttransformProgramDispatcher;\n\t\tprivate final ICullingProgramSelector\t\t\tcullingProgramSelector;\n\t\tprivate final IPolygonProcessor\t\t\t\t\tpolygonProcessor;\n\n\t\tpublic IrisSubSet(\n\t\t\t\tVertexFormat\t\tvanillaVertexFormat,\n\t\t\t\tVertexFormat\t\tirisVertexFormat,\n\t\t\t\tResourceLocation\tuploadingProgramKey,\n\t\t\t\tResourceLocation\ttransformProgramKey\n\t\t) {\n\t\t\tvar defaultTransformOverride\t\t= new TransformProgramDispatcher\t.Default(transformProgramKey, 4L * 4L);\n\t\t\tvar defaultUploadingOverride\t\t= new MeshUploadingProgramDispatcher.Default(uploadingProgramKey, 7L * 4L);\n\n\t\t\tthis.vanillaVertexFormat\t\t\t= vanillaVertexFormat;\n\t\t\tthis.irisVertexFormat\t\t\t\t= irisVertexFormat;\n\t\t\tthis.layout\t\t\t\t\t\t\t= new VertexLayout(this.irisVertexFormat);\n\n\t\t\tthis.shaderProgramOverrides\t\t\t= ModLoader.postEventWithReturn(new LoadShaderProgramOverridesEvent\t(this.irisVertexFormat)).getOverrides\t(defaultTransformOverride, defaultUploadingOverride);\n\t\t\tthis.cullingProgramSelector\t\t\t= ModLoader.postEventWithReturn(new LoadCullingProgramSelectorEvent\t(this.irisVertexFormat)).getSelector\t();\n\t\t\tthis.polygonProcessor\t\t\t\t= ModLoader.postEventWithReturn(new LoadPolygonProcessorEvent\t\t(this.irisVertexFormat)).getProcessor\t();\n\n\t\t\tthis.meshUploadingProgramDispatcher\t= new MeshUploadingProgramDispatcher();\n\t\t\tthis.transformProgramDispatcher\t\t= new TransformProgramDispatcher\t();\n\t\t}\n\n\t\t@Override\n\t\tpublic void setupBufferState() {\n\t\t\tirisVertexFormat.setupBufferState();\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isAccelerated(VertexFormat vertexFormat) {\n\t\t\treturn this.vanillaVertexFormat == vertexFormat || this.irisVertexFormat == vertexFormat;\n\t\t}\n\n\t\t@Override\n\t\tpublic Set<VertexFormat> getVertexFormats() {\n\t\t\treturn Set.of(vanillaVertexFormat, irisVertexFormat);\n\t\t}\n\n\t\t@Override\n\t\tpublic VertexLayout getLayout() {\n\t\t\treturn layout;\n\t\t}\n\n\t\t@Override\n\t\tpublic IServerBuffer getImmediateMeshBuffer() {\n\t\t\treturn ServerMesh.Builder.BUFFERS.get(layout).getFirst();\n\t\t}\n\n\t\t@Override\n\t\tpublic ITransformShaderProgramOverride getTransformProgramOverride(RenderType renderType) {\n\t\t\treturn shaderProgramOverrides.getTransformOverrides().get(renderType);\n\t\t}\n\n\t\t@Override\n\t\tpublic IUploadingShaderProgramOverride getUploadingProgramOverride(RenderType renderType) {\n\t\t\treturn shaderProgramOverrides.getUploadingOverrides().get(renderType);\n\t\t}\n\n\t\t@Override\n\t\tpublic MeshUploadingProgramDispatcher selectMeshUploadingProgramDispatcher() {\n\t\t\treturn meshUploadingProgramDispatcher;\n\t\t}\n\n\t\t@Override\n\t\tpublic TransformProgramDispatcher selectTransformProgramDispatcher() {\n\t\t\treturn transformProgramDispatcher;\n\t\t}\n\n\t\t@Override\n\t\tpublic ICullingProgramDispatcher selectCullingProgramDispatcher(RenderType renderType) {\n\t\t\treturn cullingProgramSelector.select(renderType);\n\t\t}\n\n\t\t@Override\n\t\tpublic IPolygonProgramDispatcher selectProcessingProgramDispatcher(VertexFormat.Mode mode) {\n\t\t\treturn polygonProcessor.select(mode);\n\t\t}\n\n\t\t@Override\n\t\tpublic int getVertexSize() {\n\t\t\treturn irisVertexFormat.getVertexSize();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/interfaces/IIrisAcceleratedBufferBuilder.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.interfaces;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.IMemoryInterface;\n\npublic interface IIrisAcceleratedBufferBuilder {\n\n\tIMemoryInterface getEntityIdOffset\t();\n\tIMemoryInterface getEntityOffset\t();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/interfaces/IIrisMeshInfo.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.interfaces;\n\npublic interface IIrisMeshInfo {\n\n\tshort getRenderedEntity\t\t();\n\tshort getRenderedBlockEntity();\n\tshort getRenderedItem\t\t();\n}"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/interfaces/IIrisMeshInfoCache.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.interfaces;\n\npublic interface IIrisMeshInfoCache {\n\n\tshort getRenderedEntity\t\t(int i);\n\tshort getRenderedBlockEntity(int i);\n\tshort getRenderedItem\t\t(int i);\n}"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/AcceleratedBufferBuilderMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering;\n\nimport com.github.argon4w.acceleratedrendering.compat.iris.interfaces.IIrisAcceleratedBufferBuilder;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.AcceleratedRingBuffers;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.functions.ILayerFunction;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.ElementBufferPool;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.StagingBufferPool;\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.IMemoryInterface;\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout;\nimport com.llamalad7.mixinextras.sugar.Local;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport com.mojang.blaze3d.vertex.VertexFormatElement;\nimport net.irisshaders.iris.uniforms.CapturedRenderingState;\nimport net.irisshaders.iris.vertices.IrisVertexFormats;\nimport net.minecraft.client.renderer.RenderType;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.Unique;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;\n\n@Mixin(AcceleratedBufferBuilder.class)\npublic class AcceleratedBufferBuilderMixin implements IIrisAcceleratedBufferBuilder {\n\n\t@Shadow @Final private\tVertexLayout\t\tlayout;\n\t@Shadow private\t\t\tlong\t\t\t\tvertexAddress;\n\n\t@Unique private\t\t\tIMemoryInterface\tentityIdOffset;\n\t@Unique private\t\t\tIMemoryInterface\tentityOffset;\n\n\t@Inject(\n\t\t\tmethod\t= \"<init>\",\n\t\t\tat\t\t= @At(\"TAIL\")\n\t)\n\tpublic void constructor(\n\t\t\tStagingBufferPool\t\t.StagingBuffer\tvertexBuffer,\n\t\t\tStagingBufferPool\t\t.StagingBuffer\tvaryingBuffer,\n\t\t\tElementBufferPool\t\t.ElementSegment\telementSegment,\n\t\t\tAcceleratedRingBuffers\t.Buffers\t\tbuffers,\n\t\t\tILayerFunction\t\t\t\t\t\t\tlayerFunction,\n\t\t\tRenderType\t\t\t\t\t\t\t\trenderType,\n\t\t\tCallbackInfo\t\t\t\t\t\t\tci\n\t) {\n\t\tentityIdOffset\t= layout.getElement(IrisVertexFormats.ENTITY_ID_ELEMENT);\n\t\tentityOffset\t= layout.getElement(IrisVertexFormats.ENTITY_ELEMENT);\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"addVertex(FFFIFFIIFFF)V\",\n\t\t\tat\t\t= @At(\"TAIL\")\n\t)\n\tpublic void addIrisVertex(\n\t\t\tfloat\t\t\t\t\t\t\t\tpX,\n\t\t\tfloat\t\t\t\t\t\t\t\tpY,\n\t\t\tfloat\t\t\t\t\t\t\t\tpZ,\n\t\t\tint\t\t\t\t\t\t\t\t\tpColor,\n\t\t\tfloat\t\t\t\t\t\t\t\tpU,\n\t\t\tfloat\t\t\t\t\t\t\t\tpV,\n\t\t\tint\t\t\t\t\t\t\t\t\tpPackedOverlay,\n\t\t\tint\t\t\t\t\t\t\t\t\tpPackedLight,\n\t\t\tfloat\t\t\t\t\t\t\t\tpNormalX,\n\t\t\tfloat\t\t\t\t\t\t\t\tpNormalY,\n\t\t\tfloat\t\t\t\t\t\t\t\tpNormalZ,\n\t\t\tCallbackInfo\t\t\t\t\t\tci,\n\t\t\t@Local(name = \"vertexAddress\") long\tvertexAddress\n\t) {\n\t\taddIrisData(vertexAddress);\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"addVertex(FFF)Lcom/mojang/blaze3d/vertex/VertexConsumer;\",\n\t\t\tat\t\t= @At(\"TAIL\")\n\t)\n\tpublic void addIrisVertex(\n\t\t\tfloat\t\t\t\t\t\t\t\t\tpX,\n\t\t\tfloat\t\t\t\t\t\t\t\t\tpY,\n\t\t\tfloat \t\t\t\t\t\t\t\t\tpZ,\n\t\t\tCallbackInfoReturnable<VertexConsumer>\tcir) {\n\t\taddIrisData(vertexAddress);\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= {\n\t\t\t\t\t\"addServerMesh\",\n\t\t\t\t\t\"addClientMesh\"\n\t\t\t},\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lcom/github/argon4w/acceleratedrendering/core/buffers/memory/IMemoryInterface;putInt(JI)V\",\n\t\t\t\t\tordinal\t= 2,\n\t\t\t\t\tshift\t= At.Shift.AFTER\n\t\t\t)\n\t)\n\tpublic void addIrisMesh(CallbackInfo ci, @Local(name = \"vertexAddress\") long vertexAddress) {\n\t\taddIrisData(vertexAddress);\n\t}\n\n\t@Unique\n\tprivate void addIrisData(long vertexAddress) {\n\t\tentityOffset\t.putShort(vertexAddress + 0L, (short) -1);\n\t\tentityOffset\t.putShort(vertexAddress + 2L, (short) -1);\n\t\tentityIdOffset\t.putShort(vertexAddress + 0L, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedEntity\t\t());\n\t\tentityIdOffset\t.putShort(vertexAddress + 2L, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedBlockEntity\t());\n\t\tentityIdOffset\t.putShort(vertexAddress + 4L, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedItem\t\t());\n\t}\n\n\t@Unique\n\t@Override\n\tpublic IMemoryInterface getEntityIdOffset() {\n\t\treturn entityIdOffset;\n\t}\n\n\t@Unique\n\t@Override\n\tpublic IMemoryInterface getEntityOffset() {\n\t\treturn entityOffset;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/AcceleratedBufferSourceMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.AcceleratedBufferSource;\nimport net.irisshaders.batchedentityrendering.impl.WrappableRenderType;\nimport net.irisshaders.iris.vertices.ImmediateState;\nimport net.minecraft.client.renderer.RenderType;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.ModifyArg;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@Mixin(AcceleratedBufferSource.class)\npublic class AcceleratedBufferSourceMixin {\n\n\t@ModifyArg(\n\t\t\tmethod\t= \"getBuffer\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lcom/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/AcceleratedBufferBuilder;<init>(Lcom/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/StagingBufferPool$StagingBuffer;Lcom/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/StagingBufferPool$StagingBuffer;Lcom/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/ElementBufferPool$ElementSegment;Lcom/github/argon4w/acceleratedrendering/core/buffers/accelerated/AcceleratedRingBuffers$Buffers;Lcom/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/functions/ILayerFunction;Lnet/minecraft/client/renderer/RenderType;)V\"\n\t\t\t),\n\t\t\tindex\t= 5\n\t)\n\tpublic RenderType unwrapIrisRenderType(RenderType renderType) {\n\t\treturn renderType instanceof WrappableRenderType wrapped ? wrapped.unwrap() : renderType;\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"drawBuffers\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lcom/github/argon4w/acceleratedrendering/core/buffers/accelerated/AcceleratedRingBuffers$Buffers;bindDrawBuffers()V\",\n\t\t\t\t\tshift\t= At.Shift.BEFORE\n\t\t\t)\n\t)\n\tprivate void beforeBindDrawBuffers(CallbackInfo ci) {\n\t\tif (!ImmediateState.isRenderingLevel) {\n\t\t\tImmediateState.renderWithExtendedVertexFormat = false;\n\t\t}\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"drawBuffers\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lcom/github/argon4w/acceleratedrendering/core/buffers/accelerated/AcceleratedRingBuffers$Buffers;bindDrawBuffers()V\",\n\t\t\t\t\tshift\t= At.Shift.AFTER\n\t\t\t)\n\t)\n\tprivate void afterBindDrawBuffers(CallbackInfo ci) {\n\t\tif (!ImmediateState.isRenderingLevel) {\n\t\t\tImmediateState.renderWithExtendedVertexFormat = true;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/AcceleratedRenderingModEntryMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering;\n\nimport com.github.argon4w.acceleratedrendering.AcceleratedRenderingModEntry;\nimport com.github.argon4w.acceleratedrendering.compat.iris.programs.IrisPrograms;\nimport net.neoforged.bus.api.IEventBus;\nimport net.neoforged.fml.ModContainer;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@Mixin(AcceleratedRenderingModEntry.class)\npublic class AcceleratedRenderingModEntryMixin {\n\n\t@Inject(\n\t\t\tmethod\t= \"<init>\",\n\t\t\tat\t\t= @At(\"TAIL\")\n\t)\n\tpublic void registerIrisEvents(\n\t\t\tIEventBus\t\tmodEventBus,\n\t\t\tModContainer\tmodContainer,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tmodEventBus.register(IrisPrograms.class);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/CoreBuffersProviderMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreBuffersProvider;\nimport com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport net.irisshaders.batchedentityrendering.impl.RenderBuffersExt;\nimport net.minecraft.client.renderer.RenderBuffers;\nimport org.spongepowered.asm.mixin.Mixin;\n\n@Mixin(CoreBuffersProvider.class)\npublic class CoreBuffersProviderMixin {\n\n\t@WrapMethod(method = \"bindAcceleratedBufferSources\")\n\tprivate static void bindAcceleratedBufferSourcesForIris(RenderBuffers renderBuffers, Operation<Void> original) {\n\t\tvar extension = (RenderBuffersExt) renderBuffers;\n\n\t\textension\t.beginLevelRendering();\n\t\toriginal\t.call\t\t\t\t(renderBuffers);\n\t\textension\t.endLevelRendering\t();\n\t\toriginal\t.call\t\t\t\t(renderBuffers);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/FlattenMeshInfoCacheMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering;\n\nimport com.github.argon4w.acceleratedrendering.compat.iris.interfaces.IIrisMeshInfoCache;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.FlattenMeshInfoCache;\nimport com.llamalad7.mixinextras.sugar.Local;\nimport net.irisshaders.iris.uniforms.CapturedRenderingState;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.Unique;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Constant;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.ModifyConstant;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\nimport java.lang.invoke.VarHandle;\n\n@Mixin(FlattenMeshInfoCache.class)\npublic class FlattenMeshInfoCacheMixin implements IIrisMeshInfoCache {\n\n\t@Shadow @Final public\tstatic\t\t\tVarHandle\tHANDLE;\n\n\t@Shadow private\t\t\t\t\t\t\tint[]\t\tcache;\n\n\t@Unique private\t\t\tstatic final\tint\t\t\tIRIS_MESH_INFO_SIZE\t\t\t\t= 8;\n\t@Unique private\t\t\tstatic final\tint\t\t\tRENDERED_ENTITY_OFFSET\t\t\t= 5;\n\t@Unique private\t\t\tstatic final\tint\t\t\tRENDERED_BLOCK_ENTITY_OFFSET\t= 6;\n\t@Unique private\t\t\tstatic final\tint\t\t\tRENDERED_ITEM_OFFSET\t\t\t= 7;\n\n\t@ModifyConstant(\n\t\t\tmethod\t\t= {\n\t\t\t\t\t\"<init>\",\n\t\t\t\t\t\"setup\",\n\t\t\t\t\t\"getSharing\",\n\t\t\t\t\t\"getShouldCull\",\n\t\t\t\t\t\"getColor\",\n\t\t\t\t\t\"getLight\",\n\t\t\t\t\t\"getOverlay\"\n\t\t\t},\n\t\t\tconstant\t= @Constant(intValue = 5)\n\t)\n\tpublic int modifySize(int constant) {\n\t\treturn IRIS_MESH_INFO_SIZE;\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"setup\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Ljava/lang/invoke/VarHandle;set([III)V\",\n\t\t\t\t\tordinal\t= 4,\n\t\t\t\t\tshift\t= At.Shift.AFTER\n\t\t\t)\n\t)\n\tpublic void addIrisData(\n\t\t\tint\t\t\t\t\t\t\t\t\tcolor,\n\t\t\tint\t\t\t\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\t\t\t\t\tsharing,\n\t\t\tint\t\t\t\t\t\t\t\t\tshouldCull,\n\t\t\tCallbackInfo\t\t\t\t\t\tci,\n\t\t\t@Local(name = \"infoIndex\") int\t\tinfoIndex\n\t) {\n\t\tHANDLE.set(cache, infoIndex + RENDERED_ENTITY_OFFSET,\t\tCapturedRenderingState.INSTANCE.getCurrentRenderedEntity\t\t());\n\t\tHANDLE.set(cache, infoIndex + RENDERED_BLOCK_ENTITY_OFFSET,\tCapturedRenderingState.INSTANCE.getCurrentRenderedBlockEntity\t());\n\t\tHANDLE.set(cache, infoIndex + RENDERED_ITEM_OFFSET,\t\t\tCapturedRenderingState.INSTANCE.getCurrentRenderedItem\t\t\t());\n\t}\n\n\t@Override\n\tpublic short getRenderedEntity(int i) {\n\t\treturn (short) (int) HANDLE.get(cache, i * IRIS_MESH_INFO_SIZE + RENDERED_ENTITY_OFFSET);\n\t}\n\n\t@Override\n\tpublic short getRenderedBlockEntity(int i) {\n\t\treturn (short) (int) HANDLE.get(cache, i * IRIS_MESH_INFO_SIZE + RENDERED_BLOCK_ENTITY_OFFSET);\n\t}\n\n\t@Override\n\tpublic short getRenderedItem(int i) {\n\t\treturn (short) (int) HANDLE.get(cache, i * IRIS_MESH_INFO_SIZE + RENDERED_ITEM_OFFSET);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/IBufferEnvironmentPresetsMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering;\n\nimport com.github.argon4w.acceleratedrendering.compat.iris.environments.IrisBufferEnvironment;\nimport com.github.argon4w.acceleratedrendering.compat.iris.programs.IrisPrograms;\nimport com.github.argon4w.acceleratedrendering.core.buffers.environments.IBufferEnvironment;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;\nimport com.mojang.blaze3d.vertex.DefaultVertexFormat;\nimport net.irisshaders.iris.vertices.IrisVertexFormats;\nimport org.objectweb.asm.Opcodes;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Mutable;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.injection.At;\n\n@Mixin(IBufferEnvironment.Presets.class)\npublic class IBufferEnvironmentPresetsMixin {\n\n\t@Mutable @Shadow @Final public static IBufferEnvironment BLOCK;\n\t@Mutable @Shadow @Final public static IBufferEnvironment ENTITY;\n\t@Mutable @Shadow @Final public static IBufferEnvironment POS_COLOR_TEX_LIGHT;\n\n\t@WrapOperation(\n\t\t\tmethod\t= \"<clinit>\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"FIELD\",\n\t\t\t\t\ttarget\t= \"Lcom/github/argon4w/acceleratedrendering/core/buffers/environments/IBufferEnvironment$Presets;BLOCK:Lcom/github/argon4w/acceleratedrendering/core/buffers/environments/IBufferEnvironment;\",\n\t\t\t\t\topcode\t= Opcodes.PUTSTATIC\n\t\t\t)\n\t)\n\tprivate static void useIrisBloockEnvironment(IBufferEnvironment value, Operation<Void> original) {\n\t\toriginal.call(new IrisBufferEnvironment(\n\t\t\t\tvalue,\n\t\t\t\tDefaultVertexFormat\t.BLOCK,\n\t\t\t\tIrisVertexFormats\t.TERRAIN,\n\t\t\t\tIrisPrograms\t\t.IRIS_BLOCK_MESH_UPLOADING_KEY,\n\t\t\t\tIrisPrograms\t\t.IRIS_BLOCK_VERTEX_TRANSFORM_KEY\n\t\t));\n\t}\n\n\t@WrapOperation(\n\t\t\tmethod\t= \"<clinit>\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"FIELD\",\n\t\t\t\t\ttarget\t= \"Lcom/github/argon4w/acceleratedrendering/core/buffers/environments/IBufferEnvironment$Presets;ENTITY:Lcom/github/argon4w/acceleratedrendering/core/buffers/environments/IBufferEnvironment;\",\n\t\t\t\t\topcode\t= Opcodes.PUTSTATIC\n\t\t\t)\n\t)\n\tprivate static void useIrisEntityEnvironment(IBufferEnvironment value, Operation<Void> original) {\n\t\toriginal.call(new IrisBufferEnvironment(\n\t\t\t\tvalue,\n\t\t\t\tDefaultVertexFormat\t.NEW_ENTITY,\n\t\t\t\tIrisVertexFormats\t.ENTITY,\n\t\t\t\tIrisPrograms\t\t.IRIS_ENTITY_MESH_UPLOADING_KEY,\n\t\t\t\tIrisPrograms\t\t.IRIS_ENTITY_VERTEX_TRANSFORM_KEY\n\t\t));\n\t}\n\n\t@WrapOperation(\n\t\t\tmethod\t= \"<clinit>\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"FIELD\",\n\t\t\t\t\ttarget\t= \"Lcom/github/argon4w/acceleratedrendering/core/buffers/environments/IBufferEnvironment$Presets;POS_COLOR_TEX_LIGHT:Lcom/github/argon4w/acceleratedrendering/core/buffers/environments/IBufferEnvironment;\",\n\t\t\t\t\topcode\t= Opcodes.PUTSTATIC\n\t\t\t)\n\t)\n\tprivate static void useIrisGlyphEnvironment(IBufferEnvironment value, Operation<Void> original) {\n\t\toriginal.call(new IrisBufferEnvironment(\n\t\t\t\tvalue,\n\t\t\t\tDefaultVertexFormat\t.POSITION_COLOR_TEX_LIGHTMAP,\n\t\t\t\tIrisVertexFormats\t.GLYPH,\n\t\t\t\tIrisPrograms\t\t.IRIS_GLYPH_MESH_UPLOADING_KEY,\n\t\t\t\tIrisPrograms\t\t.IRIS_GLYPH_VERTEX_TRANSFORM_KEY\n\t\t));\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/MeshUploaderMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering;\n\nimport com.github.argon4w.acceleratedrendering.compat.iris.interfaces.IIrisMeshInfoCache;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.IMeshInfoCache;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.MeshUploaderPool;\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.IMemoryInterface;\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.SimpleDynamicMemoryInterface;\nimport com.llamalad7.mixinextras.sugar.Local;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.Unique;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@Mixin(MeshUploaderPool.MeshUploader.class)\npublic abstract class MeshUploaderMixin {\n\n\t@Shadow @Final private\tIMeshInfoCache meshInfos;\n\n\t@Unique private final\tIMemoryInterface IRIS_INFO_ENTITY\t\t= new SimpleDynamicMemoryInterface(5L * 4L + 0L * 2L, (MeshUploaderPool.MeshUploader) (Object) this);\n\t@Unique private final\tIMemoryInterface IRIS_INFO_BLOCK_ENTITY\t= new SimpleDynamicMemoryInterface(5L * 4L + 1L * 2L, (MeshUploaderPool.MeshUploader) (Object) this);\n\t@Unique private final\tIMemoryInterface IRIS_INFO_ITEM\t\t\t= new SimpleDynamicMemoryInterface(5L * 4L + 2L * 2L, (MeshUploaderPool.MeshUploader) (Object) this);\n\n\t@Inject(\n\t\t\tmethod\t= \"upload\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lcom/github/argon4w/acceleratedrendering/core/buffers/memory/IMemoryInterface;putInt(JI)V\",\n\t\t\t\t\tordinal\t= 4,\n\t\t\t\t\tshift\t= At.Shift.AFTER\n\t\t\t)\n\t)\n\tpublic void uploadIrisData(\n\t\t\tCallbackInfo\t\t\t\t\t\t\t\tci,\n\t\t\t@Local(name = \"meshInfoAddress\")\tlong\tmeshInfoAddress,\n\t\t\t@Local(name = \"i\")\t\t\t\t\tint\t\toffset\n\t) {\n\t\tIRIS_INFO_ENTITY\t\t.at(offset).putShort(meshInfoAddress, ((IIrisMeshInfoCache) meshInfos).getRenderedEntity\t\t(offset));\n\t\tIRIS_INFO_BLOCK_ENTITY\t.at(offset).putShort(meshInfoAddress, ((IIrisMeshInfoCache) meshInfos).getRenderedBlockEntity\t(offset));\n\t\tIRIS_INFO_ITEM\t\t\t.at(offset).putShort(meshInfoAddress, ((IIrisMeshInfoCache) meshInfos).getRenderedItem\t\t\t(offset));\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/MeshUploadingProgramDispatcherMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering;\n\nimport com.github.argon4w.acceleratedrendering.compat.iris.interfaces.IIrisAcceleratedBufferBuilder;\nimport com.github.argon4w.acceleratedrendering.compat.iris.interfaces.IIrisMeshInfoCache;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.AcceleratedRingBuffers;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.IMeshInfoCache;\nimport com.github.argon4w.acceleratedrendering.core.programs.dispatchers.MeshUploadingProgramDispatcher;\nimport com.llamalad7.mixinextras.sugar.Local;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\nimport java.util.Collection;\n\n@Mixin(MeshUploadingProgramDispatcher.class)\npublic class MeshUploadingProgramDispatcherMixin {\n\n\t@Inject(\n\t\t\tmethod\t= \"dispatch\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lcom/github/argon4w/acceleratedrendering/core/buffers/memory/IMemoryInterface;putInt(JI)V\",\n\t\t\t\t\tordinal\t= 2,\n\t\t\t\t\tshift\t= At.Shift.AFTER\n\t\t\t)\n\t)\n\tpublic void addIrisData(\n\t\t\tCollection<AcceleratedBufferBuilder>\t\t\t\t\t\tbuilders,\n\t\t\tAcceleratedRingBuffers.Buffers\t\t\t\t\t\t\t\tbuffers,\n\t\t\tCallbackInfo\t\t\t\t\t\t\t\t\t\t\t\tci,\n\t\t\t@Local(name = \"meshInfos\")\t\tIMeshInfoCache\t\t\t\tmeshInfos,\n\t\t\t@Local(name = \"builder\")\t\tAcceleratedBufferBuilder\tbuilder,\n\t\t\t@Local(name = \"offset\")\t\t\tint\t\t\t\t\t\t\toffset,\n\t\t\t@Local(name = \"i\")\t\t\t\tint\t\t\t\t\t\t\ti,\n\t\t\t@Local(name = \"vertexAddress\")\tlong\t\t\t\t\t\tvertexAddress\n\t) {\n\t\t((IIrisAcceleratedBufferBuilder) builder).getEntityIdOffset()\t.at(offset).putShort(vertexAddress + 0L, ((IIrisMeshInfoCache) meshInfos).getRenderedEntity\t\t(i));\n\t\t((IIrisAcceleratedBufferBuilder) builder).getEntityIdOffset()\t.at(offset).putShort(vertexAddress + 2L, ((IIrisMeshInfoCache) meshInfos).getRenderedEntity\t\t(i));\n\t\t((IIrisAcceleratedBufferBuilder) builder).getEntityIdOffset()\t.at(offset).putShort(vertexAddress + 4L, ((IIrisMeshInfoCache) meshInfos).getRenderedEntity\t\t(i));\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/RenderTypeUtilsMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType;\nimport com.github.argon4w.acceleratedrendering.core.utils.RenderTypeUtils;\nimport net.irisshaders.batchedentityrendering.impl.BlendingStateHolder;\nimport net.irisshaders.batchedentityrendering.impl.TransparencyType;\nimport net.irisshaders.batchedentityrendering.impl.WrappableRenderType;\nimport net.minecraft.client.renderer.RenderType;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.ModifyVariable;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;\n\n@Mixin(RenderTypeUtils.class)\npublic class RenderTypeUtilsMixin {\n\n\t@ModifyVariable(\n\t\t\tmethod\t\t= \"getTextureLocation\",\n\t\t\tat\t\t\t= @At(\"HEAD\"),\n\t\t\tordinal\t\t= 0,\n\t\t\targsOnly\t= true\n\t)\n\tprivate static RenderType unwrapIrisRenderType1(RenderType renderType) {\n\t\treturn renderType instanceof WrappableRenderType wrapped ? wrapped.unwrap() : renderType;\n\t}\n\n\t@ModifyVariable(\n\t\t\tmethod\t\t= \"isCulled\",\n\t\t\tat\t\t\t= @At(\"HEAD\"),\n\t\t\tordinal\t\t= 0,\n\t\t\targsOnly\t= true\n\t)\n\tprivate static RenderType unwrapIrisRenderType2(RenderType renderType) {\n\t\treturn renderType instanceof WrappableRenderType wrapped ? wrapped.unwrap() : renderType;\n\t}\n\n\t@ModifyVariable(\n\t\t\tmethod\t\t= \"isDynamic\",\n\t\t\tat\t\t\t= @At(\"HEAD\"),\n\t\t\tordinal\t\t= 0,\n\t\t\targsOnly\t= true\n\t)\n\tprivate static RenderType unwrapIrisRenderType3(RenderType renderType) {\n\t\treturn renderType instanceof WrappableRenderType wrapped ? wrapped.unwrap() : renderType;\n\t}\n\n\t@ModifyVariable(\n\t\t\tmethod\t\t= \"hasDepth\",\n\t\t\tat\t\t\t= @At(\"HEAD\"),\n\t\t\tordinal\t\t= 0,\n\t\t\targsOnly\t= true\n\t)\n\tprivate static RenderType unwrapIrisRenderType4(RenderType renderType) {\n\t\treturn renderType instanceof WrappableRenderType wrapped ? wrapped.unwrap() : renderType;\n\t}\n\n\t@ModifyVariable(\n\t\t\tmethod\t\t= \"withDepth\",\n\t\t\tat\t\t\t= @At(\"HEAD\"),\n\t\t\tordinal\t\t= 0,\n\t\t\targsOnly\t= true\n\t)\n\tprivate static RenderType unwrapIrisRenderType5(RenderType renderType) {\n\t\treturn renderType instanceof WrappableRenderType wrapped ? wrapped.unwrap() : renderType;\n\t}\n\n\t@Inject(\n\t\t\tmethod\t\t= \"getDrawType\",\n\t\t\tat\t\t\t= @At(\"HEAD\"),\n\t\t\tcancellable\t= true\n\t)\n\tprivate static void getIrisRenderTypeDrawType(RenderType renderType, CallbackInfoReturnable<LayerDrawType> cir) {\n\t\tvar holder = (BlendingStateHolder) renderType;\n\n\t\tcir.setReturnValue(\tholder.getTransparencyType() == TransparencyType.GENERAL_TRANSPARENT\n\t\t\t\t||\t\t\tholder.getTransparencyType() == TransparencyType.DECAL\n\t\t\t\t? LayerDrawType.TRANSLUCENT\n\t\t\t\t: LayerDrawType.OPAQUE\n\t\t);\n\t}\n\n\t@Inject(\n\t\t\tmethod\t\t= \"isTranslucent\",\n\t\t\tat\t\t\t= @At(\"HEAD\"),\n\t\t\tcancellable\t= true\n\t)\n\tprivate static void checkIrisTransparency(RenderType renderType, CallbackInfoReturnable<Boolean> cir) {\n\t\tvar holder = (BlendingStateHolder) renderType;\n\n\t\tcir.setReturnValue(\tholder.getTransparencyType() == TransparencyType.GENERAL_TRANSPARENT\n\t\t\t\t||\t\t\tholder.getTransparencyType() == TransparencyType.DECAL\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/SimpleMeshInfoCacheMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering;\n\nimport com.github.argon4w.acceleratedrendering.compat.iris.interfaces.IIrisMeshInfo;\nimport com.github.argon4w.acceleratedrendering.compat.iris.interfaces.IIrisMeshInfoCache;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.SimpleMeshInfo;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.SimpleMeshInfoCache;\nimport com.github.argon4w.acceleratedrendering.core.utils.SimpleCachedArray;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\n\n@Mixin(SimpleMeshInfoCache.class)\npublic class SimpleMeshInfoCacheMixin implements IIrisMeshInfoCache {\n\n\t@Shadow @Final private SimpleCachedArray<SimpleMeshInfo> meshInfos;\n\n\t@Override\n\tpublic short getRenderedEntity(int i) {\n\t\treturn ((IIrisMeshInfo) meshInfos.at(i)).getRenderedEntity();\n\t}\n\n\t@Override\n\tpublic short getRenderedBlockEntity(int i) {\n\t\treturn ((IIrisMeshInfo) meshInfos.at(i)).getRenderedBlockEntity();\n\t}\n\n\t@Override\n\tpublic short getRenderedItem(int i) {\n\t\treturn ((IIrisMeshInfo) meshInfos.at(i)).getRenderedItem();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/SimpleMeshInfoMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering;\n\nimport com.github.argon4w.acceleratedrendering.compat.iris.interfaces.IIrisMeshInfo;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.SimpleMeshInfo;\nimport net.irisshaders.iris.uniforms.CapturedRenderingState;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Unique;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@Mixin(SimpleMeshInfo.class)\npublic class SimpleMeshInfoMixin implements IIrisMeshInfo {\n\n\t@Unique private short renderedEntity;\n\t@Unique private short renderedBlockEntity;\n\t@Unique private short renderedItem;\n\n\t@Inject(method = \"setupMeshInfo\", at = @At(\"TAIL\"))\n\tpublic void setIrisData(\n\t\t\tint\t\t\t\tcolor,\n\t\t\tint\t\t\t\tlight,\n\t\t\tint\t\t\t\toverlay,\n\t\t\tint\t\t\t\tsharing,\n\t\t\tint\t\t\t\tshouldCull,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\trenderedEntity\t\t= (short) CapturedRenderingState.INSTANCE.getCurrentRenderedEntity\t\t();\n\t\trenderedBlockEntity\t= (short) CapturedRenderingState.INSTANCE.getCurrentRenderedBlockEntity\t();\n\t\trenderedItem\t\t= (short) CapturedRenderingState.INSTANCE.getCurrentRenderedItem\t\t();\n\t}\n\n\t@Unique\n\t@Override\n\tpublic short getRenderedEntity() {\n\t\treturn renderedEntity;\n\t}\n\n\t@Unique\n\t@Override\n\tpublic short getRenderedBlockEntity() {\n\t\treturn renderedBlockEntity;\n\t}\n\n\t@Unique\n\t@Override\n\tpublic short getRenderedItem() {\n\t\treturn renderedItem;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/UnsafeMemoryMeshInfoCacheMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering;\n\nimport com.github.argon4w.acceleratedrendering.compat.iris.interfaces.IIrisMeshInfoCache;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.UnsafeMemoryMeshInfoCache;\nimport com.llamalad7.mixinextras.sugar.Local;\nimport net.irisshaders.iris.uniforms.CapturedRenderingState;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.Unique;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Constant;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.ModifyConstant;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\nimport sun.misc.Unsafe;\n\n@Mixin(UnsafeMemoryMeshInfoCache.class)\npublic class UnsafeMemoryMeshInfoCacheMixin implements IIrisMeshInfoCache {\n\n\t@Shadow @Final public\tstatic\t\t\tUnsafe\t\tUNSAFE;\n\n\t@Shadow private\t\t\t\t\t\t\tlong\t\taddress;\n\n\t@Unique private\t\t\tstatic final\tlong\t\tIRIS_MESH_INFO_SIZE\t\t\t\t= 8L * 4L;\n\t@Unique private\t\t\tstatic final\tlong\t\tRENDERED_ENTITY_OFFSET\t\t\t= 5L * 4L;\n\t@Unique private\t\t\tstatic final\tlong\t\tRENDERED_BLOCK_ENTITY_OFFSET\t= 6L * 4L;\n\t@Unique private\t\t\tstatic final\tlong\t\tRENDERED_ITEM_OFFSET\t\t\t= 7L * 4L;\n\n\t@ModifyConstant(\n\t\t\tmethod\t\t= {\n\t\t\t\t\t\"<init>\",\n\t\t\t\t\t\"setup\",\n\t\t\t\t\t\"getSharing\",\n\t\t\t\t\t\"getShouldCull\",\n\t\t\t\t\t\"getColor\",\n\t\t\t\t\t\"getLight\",\n\t\t\t\t\t\"getOverlay\"\n\t\t\t},\n\t\t\tconstant\t= @Constant(longValue = 20L)\n\t)\n\tpublic long modifySize(long constant) {\n\t\treturn IRIS_MESH_INFO_SIZE;\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"setup\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue = \"INVOKE\",\n\t\t\t\t\ttarget = \"Lsun/misc/Unsafe;putInt(JI)V\",\n\t\t\t\t\tordinal\t= 4,\n\t\t\t\t\tshift\t= At.Shift.AFTER\n\t\t\t)\n\t)\n\tpublic void addIrisData(\n\t\t\tint\t\t\t\t\t\t\t\t\tcolor,\n\t\t\tint\t\t\t\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\t\t\t\t\tsharing,\n\t\t\tint\t\t\t\t\t\t\t\t\tshouldCull,\n\t\t\tCallbackInfo\t\t\t\t\t\tci,\n\t\t\t@Local(name = \"infoAddress\") long\tinfoAddress\n\t) {\n\t\tUNSAFE.putInt(infoAddress + RENDERED_ENTITY_OFFSET,\t\t\tCapturedRenderingState.INSTANCE.getCurrentRenderedEntity\t\t());\n\t\tUNSAFE.putInt(infoAddress + RENDERED_BLOCK_ENTITY_OFFSET,\tCapturedRenderingState.INSTANCE.getCurrentRenderedBlockEntity\t());\n\t\tUNSAFE.putInt(infoAddress + RENDERED_ITEM_OFFSET,\t\t\tCapturedRenderingState.INSTANCE.getCurrentRenderedItem\t\t\t());\n\t}\n\n\t@Override\n\tpublic short getRenderedEntity(int i) {\n\t\treturn (short) UNSAFE.getInt(address + i * IRIS_MESH_INFO_SIZE + RENDERED_ENTITY_OFFSET);\n\t}\n\n\t@Override\n\tpublic short getRenderedBlockEntity(int i) {\n\t\treturn (short) UNSAFE.getInt(address + i * IRIS_MESH_INFO_SIZE + RENDERED_BLOCK_ENTITY_OFFSET);\n\t}\n\n\t@Override\n\tpublic short getRenderedItem(int i) {\n\t\treturn (short) UNSAFE.getInt(address + i * IRIS_MESH_INFO_SIZE + RENDERED_ITEM_OFFSET);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/iris/FullyBufferedMultiBufferSourceMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.mixins.iris;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratableBufferSource;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.llamalad7.mixinextras.injector.ModifyReturnValue;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.experimental.ExtensionMethod;\nimport net.irisshaders.batchedentityrendering.impl.FullyBufferedMultiBufferSource;\nimport net.minecraft.client.renderer.RenderType;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Pseudo;\nimport org.spongepowered.asm.mixin.injection.At;\n\n@Pseudo\n@ExtensionMethod(VertexConsumerExtension\t\t.class)\n@Mixin\t\t\t(FullyBufferedMultiBufferSource\t.class)\npublic abstract class FullyBufferedMultiBufferSourceMixin implements IAcceleratableBufferSource {\n\n\t@ModifyReturnValue(\n\t\t\tmethod\t= \"getBuffer\",\n\t\t\tat\t\t= @At(\"RETURN\")\n\t)\n\tpublic VertexConsumer initAcceleration(VertexConsumer original, RenderType renderType) {\n\t\treturn original\n\t\t\t\t.getHolder\t\t\t()\n\t\t\t\t.initAcceleration\t(renderType, getBoundAcceleratedBufferSource());\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/iris/HandRendererMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.mixins.iris;\n\nimport com.github.argon4w.acceleratedrendering.compat.iris.IrisCompatBuffers;\nimport com.github.argon4w.acceleratedrendering.compat.iris.IrisCompatBuffersProvider;\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.CoreStates;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.BufferSourceExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;\nimport lombok.experimental.ExtensionMethod;\nimport net.irisshaders.batchedentityrendering.impl.FullyBufferedMultiBufferSource;\nimport net.irisshaders.iris.pathways.HandRenderer;\nimport net.irisshaders.iris.pipeline.WorldRenderingPipeline;\nimport net.minecraft.client.Camera;\nimport net.minecraft.client.renderer.GameRenderer;\nimport org.joml.Matrix4fc;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Pseudo;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@Pseudo\n@ExtensionMethod(BufferSourceExtension\t.class)\n@Mixin\t\t\t(HandRenderer\t\t\t.class)\npublic class HandRendererMixin {\n\n\n\t@Shadow\n\t@Final\n\tprivate FullyBufferedMultiBufferSource bufferSource;\n\n\t@Inject(\n\t\t\tmethod\t= \"<init>\",\n\t\t\tat\t\t= @At(\"TAIL\")\n\t)\n\tpublic void bindAcceleratedBufferSourceHand(CallbackInfo ci) {\n\t\tbufferSource\n\t\t\t\t.getAcceleratable\t\t\t()\n\t\t\t\t.bindAcceleratedBufferSource(IrisCompatBuffersProvider.HAND);\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"renderSolid\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/minecraft/client/renderer/ItemInHandRenderer;renderHandsWithItems(FLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/player/LocalPlayer;I)V\",\n\t\t\t\t\tshift\t= At.Shift.BEFORE\n\t\t\t)\n\t)\n\tpublic void startRenderSolidFast(\n\t\t\tMatrix4fc\t\t\t\tmodelMatrix,\n\t\t\tfloat\t\t\t\t\ttickDelta,\n\t\t\tCamera\t\t\t\t\tcamera,\n\t\t\tGameRenderer\t\t\tgameRenderer,\n\t\t\tWorldRenderingPipeline\tpipeline,\n\t\t\tCallbackInfo\t\t\tci\n\t) {\n\t\tCoreFeature.setRenderingHand();\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"renderSolid\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/minecraft/client/renderer/ItemInHandRenderer;renderHandsWithItems(FLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/player/LocalPlayer;I)V\",\n\t\t\t\t\tshift\t= At.Shift.AFTER\n\t\t\t)\n\t)\n\tpublic void stopRenderSolidFast(\n\t\t\tMatrix4fc\t\t\t\tmodelMatrix,\n\t\t\tfloat\t\t\t\t\ttickDelta,\n\t\t\tCamera\t\t\t\t\tcamera,\n\t\t\tGameRenderer\t\t\tgameRenderer,\n\t\t\tWorldRenderingPipeline\tpipeline,\n\t\t\tCallbackInfo\t\t\tci\n\t) {\n\t\tCoreFeature\t\t\t\t\t\t\t\t\t.resetRenderingHand\t();\n\n\t\tCoreStates\t\t\t\t\t\t\t\t\t.recordBuffers\t\t();\n\t\tIrisCompatBuffers.ENTITY_HAND\t\t\t\t.prepareBuffers\t\t();\n\t\tIrisCompatBuffers.BLOCK_HAND\t\t\t\t.prepareBuffers\t\t();\n\t\tIrisCompatBuffers.POS_HAND\t\t\t\t\t.prepareBuffers\t\t();\n\t\tIrisCompatBuffers.POS_COLOR_HAND\t\t\t.prepareBuffers\t\t();\n\t\tIrisCompatBuffers.POS_TEX_HAND\t\t\t\t.prepareBuffers\t\t();\n\t\tIrisCompatBuffers.POS_TEX_COLOR_HAND\t\t.prepareBuffers\t\t();\n\t\tIrisCompatBuffers.POS_COLOR_TEX_LIGHT_HAND\t.prepareBuffers\t\t();\n\t\tCoreStates\t\t\t\t\t\t\t\t\t.restoreBuffers\t\t();\n\n\t\tIrisCompatBuffers.ENTITY_HAND\t\t\t\t.drawBuffers\t\t(LayerDrawType.ALL);\n\t\tIrisCompatBuffers.BLOCK_HAND\t\t\t\t.drawBuffers\t\t(LayerDrawType.ALL);\n\t\tIrisCompatBuffers.POS_HAND\t\t\t\t\t.drawBuffers\t\t(LayerDrawType.ALL);\n\t\tIrisCompatBuffers.POS_COLOR_HAND\t\t\t.drawBuffers\t\t(LayerDrawType.ALL);\n\t\tIrisCompatBuffers.POS_TEX_HAND\t\t\t\t.drawBuffers\t\t(LayerDrawType.ALL);\n\t\tIrisCompatBuffers.POS_TEX_COLOR_HAND\t\t.drawBuffers\t\t(LayerDrawType.ALL);\n\t\tIrisCompatBuffers.POS_COLOR_TEX_LIGHT_HAND\t.drawBuffers\t\t(LayerDrawType.ALL);\n\n\t\tIrisCompatBuffers.ENTITY_HAND\t\t\t\t.clearBuffers\t\t();\n\t\tIrisCompatBuffers.BLOCK_HAND\t\t\t\t.clearBuffers\t\t();\n\t\tIrisCompatBuffers.POS_HAND\t\t\t\t\t.clearBuffers\t\t();\n\t\tIrisCompatBuffers.POS_COLOR_HAND\t\t\t.clearBuffers\t\t();\n\t\tIrisCompatBuffers.POS_TEX_HAND\t\t\t\t.clearBuffers\t\t();\n\t\tIrisCompatBuffers.POS_TEX_COLOR_HAND\t\t.clearBuffers\t\t();\n\t\tIrisCompatBuffers.POS_COLOR_TEX_LIGHT_HAND\t.clearBuffers\t\t();\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"renderTranslucent\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/minecraft/client/renderer/ItemInHandRenderer;renderHandsWithItems(FLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/player/LocalPlayer;I)V\",\n\t\t\t\t\tshift\t= At.Shift.BEFORE\n\t\t\t)\n\t)\n\tpublic void startRenderTranslucentFast(\n\t\t\tMatrix4fc\t\t\t\tmodelMatrix,\n\t\t\tfloat\t\t\t\t\ttickDelta,\n\t\t\tCamera\t\t\t\t\tcamera,\n\t\t\tGameRenderer\t\t\tgameRenderer,\n\t\t\tWorldRenderingPipeline\tpipeline,\n\t\t\tCallbackInfo\t\t\tci\n\t) {\n\t\tCoreFeature.setRenderingHand();\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"renderTranslucent\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/minecraft/client/renderer/ItemInHandRenderer;renderHandsWithItems(FLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/player/LocalPlayer;I)V\",\n\t\t\t\t\tshift\t= At.Shift.AFTER\n\t\t\t)\n\t)\n\tpublic void stopRenderTranslucentFast(\n\t\t\tMatrix4fc\t\t\t\tmodelMatrix,\n\t\t\tfloat\t\t\t\t\ttickDelta,\n\t\t\tCamera\t\t\t\t\tcamera,\n\t\t\tGameRenderer\t\t\tgameRenderer,\n\t\t\tWorldRenderingPipeline\tpipeline,\n\t\t\tCallbackInfo\t\t\tci\n\t) {\n\t\tCoreFeature\t\t\t\t\t\t\t\t\t.resetRenderingHand\t();\n\n\t\tCoreStates\t\t\t\t\t\t\t\t\t.recordBuffers\t\t();\n\t\tIrisCompatBuffers.ENTITY_HAND\t\t\t\t.prepareBuffers\t\t();\n\t\tIrisCompatBuffers.BLOCK_HAND\t\t\t\t.prepareBuffers\t\t();\n\t\tIrisCompatBuffers.POS_HAND\t\t\t\t\t.prepareBuffers\t\t();\n\t\tIrisCompatBuffers.POS_COLOR_HAND\t\t\t.prepareBuffers\t\t();\n\t\tIrisCompatBuffers.POS_TEX_HAND\t\t\t\t.prepareBuffers\t\t();\n\t\tIrisCompatBuffers.POS_TEX_COLOR_HAND\t\t.prepareBuffers\t\t();\n\t\tIrisCompatBuffers.POS_COLOR_TEX_LIGHT_HAND\t.prepareBuffers\t\t();\n\t\tCoreStates\t\t\t\t\t\t\t\t\t.restoreBuffers\t\t();\n\n\t\tIrisCompatBuffers.ENTITY_HAND\t\t\t\t.drawBuffers\t\t(LayerDrawType.ALL);\n\t\tIrisCompatBuffers.BLOCK_HAND\t\t\t\t.drawBuffers\t\t(LayerDrawType.ALL);\n\t\tIrisCompatBuffers.POS_HAND\t\t\t\t\t.drawBuffers\t\t(LayerDrawType.ALL);\n\t\tIrisCompatBuffers.POS_COLOR_HAND\t\t\t.drawBuffers\t\t(LayerDrawType.ALL);\n\t\tIrisCompatBuffers.POS_TEX_HAND\t\t\t\t.drawBuffers\t\t(LayerDrawType.ALL);\n\t\tIrisCompatBuffers.POS_TEX_COLOR_HAND\t\t.drawBuffers\t\t(LayerDrawType.ALL);\n\t\tIrisCompatBuffers.POS_COLOR_TEX_LIGHT_HAND\t.drawBuffers\t\t(LayerDrawType.ALL);\n\n\t\tIrisCompatBuffers.ENTITY_HAND\t\t\t\t.clearBuffers\t\t();\n\t\tIrisCompatBuffers.BLOCK_HAND\t\t\t\t.clearBuffers\t\t();\n\t\tIrisCompatBuffers.POS_HAND\t\t\t\t\t.clearBuffers\t\t();\n\t\tIrisCompatBuffers.POS_COLOR_HAND\t\t\t.clearBuffers\t\t();\n\t\tIrisCompatBuffers.POS_TEX_HAND\t\t\t\t.clearBuffers\t\t();\n\t\tIrisCompatBuffers.POS_TEX_COLOR_HAND\t\t.clearBuffers\t\t();\n\t\tIrisCompatBuffers.POS_COLOR_TEX_LIGHT_HAND\t.clearBuffers\t\t();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/iris/IrisVertexFormatsMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.mixins.iris;\n\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;\nimport com.mojang.blaze3d.vertex.VertexFormat;\nimport com.mojang.blaze3d.vertex.VertexFormatElement;\nimport net.irisshaders.iris.vertices.IrisVertexFormats;\nimport org.objectweb.asm.Opcodes;\nimport org.spongepowered.asm.mixin.*;\nimport org.spongepowered.asm.mixin.injection.At;\n\n@Pseudo\n@Mixin(\n\t\tvalue\t\t= IrisVertexFormats.class,\n\t\tpriority\t= Integer.MAX_VALUE\n)\npublic class IrisVertexFormatsMixin {\n\n\t@Shadow @Final @Mutable\tpublic static VertexFormat\t\t\tENTITY;\n\t@Shadow @Final @Mutable\tpublic static VertexFormat\t\t\tGLYPH;\n\t@Shadow @Final\t\t\tpublic static VertexFormatElement\tENTITY_ID_ELEMENT;\n\t@Shadow @Final\t\t\tpublic static VertexFormatElement\tMID_TEXTURE_ELEMENT;\n\t@Shadow @Final\t\t\tpublic static VertexFormatElement\tTANGENT_ELEMENT;\n\n\t@WrapOperation(\n\t\t\tmethod\t= \"<clinit>\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"FIELD\",\n\t\t\t\t\ttarget\t= \"Lnet/irisshaders/iris/vertices/IrisVertexFormats;ENTITY:Lcom/mojang/blaze3d/vertex/VertexFormat;\",\n\t\t\t\t\topcode\t= Opcodes.PUTSTATIC\n\t\t\t)\n\t)\n\tprivate static void addPaddingForEntityFormat(VertexFormat value, Operation<Void> original) {\n\t\toriginal.call\t(VertexFormat\n\t\t\t\t.builder()\n\t\t\t\t.add\t(\"Position\",\t\tVertexFormatElement.POSITION)\n\t\t\t\t.add\t(\"Color\",\t\t\tVertexFormatElement.COLOR)\n\t\t\t\t.add\t(\"UV0\",\t\t\t\tVertexFormatElement.UV0)\n\t\t\t\t.add\t(\"UV1\",\t\t\t\tVertexFormatElement.UV1)\n\t\t\t\t.add\t(\"UV2\",\t\t\t\tVertexFormatElement.UV2)\n\t\t\t\t.add\t(\"Normal\",\t\t\tVertexFormatElement.NORMAL)\n\t\t\t\t.padding(1)\n\t\t\t\t.add\t(\"iris_Entity\",\t\tENTITY_ID_ELEMENT)\n\t\t\t\t.padding(2)\n\t\t\t\t.add\t(\"mc_midTexCoord\",\tMID_TEXTURE_ELEMENT)\n\t\t\t\t.add\t(\"at_tangent\",\t\tTANGENT_ELEMENT)\n\t\t\t\t.build\t()\n\t\t);\n\t}\n\n\t@WrapOperation(\n\t\t\tmethod\t= \"<clinit>\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"FIELD\",\n\t\t\t\t\ttarget\t= \"Lnet/irisshaders/iris/vertices/IrisVertexFormats;GLYPH:Lcom/mojang/blaze3d/vertex/VertexFormat;\",\n\t\t\t\t\topcode\t= Opcodes.PUTSTATIC\n\t\t\t)\n\t)\n\tprivate static void addPaddingForGlyphFormat(VertexFormat value, Operation<Void> original) {\n\t\toriginal.call\t(VertexFormat\n\t\t\t\t.builder()\n\t\t\t\t.add\t(\"Position\",\t\tVertexFormatElement.POSITION)\n\t\t\t\t.add\t(\"Color\",\t\t\tVertexFormatElement.COLOR)\n\t\t\t\t.add\t(\"UV0\",\t\t\t\tVertexFormatElement.UV0)\n\t\t\t\t.add\t(\"UV2\",\t\t\t\tVertexFormatElement.UV2)\n\t\t\t\t.add\t(\"Normal\",\t\t\tVertexFormatElement.NORMAL)\n\t\t\t\t.padding(1)\n\t\t\t\t.add\t(\"iris_Entity\",\t\tENTITY_ID_ELEMENT)\n\t\t\t\t.padding(2)\n\t\t\t\t.add\t(\"mc_midTexCoord\",\tMID_TEXTURE_ELEMENT)\n\t\t\t\t.add\t(\"at_tangent\",\t\tTANGENT_ELEMENT)\n\t\t\t\t.build\t()\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/iris/ModelToEntityVertexSerializerMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.mixins.iris;\n\nimport net.irisshaders.iris.vertices.sodium.ModelToEntityVertexSerializer;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Pseudo;\nimport org.spongepowered.asm.mixin.injection.Constant;\nimport org.spongepowered.asm.mixin.injection.ModifyConstant;\n\n@Pseudo\n@Mixin(ModelToEntityVertexSerializer.class)\npublic class ModelToEntityVertexSerializerMixin {\n\n\t@ModifyConstant(\n\t\t\tmethod\t\t= \"serialize\",\n\t\t\tconstant\t= @Constant(longValue = 42L)\n\t)\n\tpublic long modifyMidU(long constant) {\n\t\treturn 44L;\n\t}\n\n\t@ModifyConstant(\n\t\t\tmethod\t\t= \"serialize\",\n\t\t\tconstant\t= @Constant(longValue = 46L)\n\t)\n\tpublic long modifyMidV(long constant) {\n\t\treturn 48L;\n\t}\n\n\t@ModifyConstant(\n\t\t\tmethod\t\t= \"serialize\",\n\t\t\tconstant\t= @Constant(longValue = 50L)\n\t)\n\tpublic long modifyTangent(long constant) {\n\t\treturn 52L;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/iris/ShadowRendererMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.mixins.iris;\n\nimport com.github.argon4w.acceleratedrendering.compat.iris.IrisCompatBuffers;\nimport com.github.argon4w.acceleratedrendering.compat.iris.IrisCompatBuffersProvider;\nimport com.github.argon4w.acceleratedrendering.core.CoreStates;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.BufferSourceExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType;\nimport lombok.experimental.ExtensionMethod;\nimport net.irisshaders.batchedentityrendering.impl.RenderBuffersExt;\nimport net.irisshaders.iris.mixin.LevelRendererAccessor;\nimport net.irisshaders.iris.pipeline.IrisRenderingPipeline;\nimport net.irisshaders.iris.shaderpack.programs.ProgramSource;\nimport net.irisshaders.iris.shaderpack.properties.PackDirectives;\nimport net.irisshaders.iris.shadows.ShadowCompositeRenderer;\nimport net.irisshaders.iris.shadows.ShadowRenderTargets;\nimport net.irisshaders.iris.shadows.ShadowRenderer;\nimport net.irisshaders.iris.uniforms.custom.CustomUniforms;\nimport net.minecraft.client.Camera;\nimport net.minecraft.client.renderer.RenderBuffers;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Pseudo;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@Pseudo\n@ExtensionMethod(BufferSourceExtension\t.class)\n@Mixin\t\t\t(ShadowRenderer\t\t\t.class)\npublic class ShadowRendererMixin {\n\n\t@Shadow @Final private RenderBuffers\tbuffers;\n\t@Shadow @Final private RenderBuffersExt\trenderBuffersExt;\n\n\t@Inject(method = \"<init>\", at = @At(\"TAIL\"))\n\tpublic void bindAcceleratedShadowBufferSources(\n\t\t\tIrisRenderingPipeline\tpipeline,\n\t\t\tProgramSource\t\t\tshadow,\n\t\t\tPackDirectives\t\t\tdirectives,\n\t\t\tShadowRenderTargets\t\tshadowRenderTargets,\n\t\t\tShadowCompositeRenderer\tcompositeRenderer,\n\t\t\tCustomUniforms\t\t\tcustomUniforms,\n\t\t\tboolean\t\t\t\t\tseparateHardwareSamplers,\n\t\t\tCallbackInfo\t\t\tci\n\t) {\n\t\trenderBuffersExt.beginLevelRendering();\n\n\t\tbuffers.bufferSource\t\t\t().getAcceleratable().bindAcceleratedBufferSource(IrisCompatBuffersProvider.SHADOW);\n\t\tbuffers.crumblingBufferSource\t().getAcceleratable().bindAcceleratedBufferSource(IrisCompatBuffersProvider.SHADOW);\n\t\tbuffers.outlineBufferSource\t\t().getAcceleratable().bindAcceleratedBufferSource(IrisCompatBuffersProvider.SHADOW);\n\n\t\trenderBuffersExt.endLevelRendering();\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"renderShadows\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;endBatch()V\"\n\t\t\t)\n\t)\n\tpublic void endAllBatches(\n\t\t\tLevelRendererAccessor\tlevelRenderer,\n\t\t\tCamera\t\t\t\t\tplayerCamera,\n\t\t\tCallbackInfo\t\t\tci\n\t) {\n\t\tCoreStates\t\t\t\t\t\t\t\t.recordBuffers\t();\n\t\tIrisCompatBuffers.BLOCK_SHADOW\t\t\t.prepareBuffers\t();\n\t\tIrisCompatBuffers.ENTITY_SHADOW\t\t\t.prepareBuffers\t();\n\t\tIrisCompatBuffers.GLYPH_SHADOW\t\t\t.prepareBuffers\t();\n\t\tIrisCompatBuffers.POS_TEX_SHADOW\t\t.prepareBuffers\t();\n\t\tIrisCompatBuffers.POS_TEX_COLOR_SHADOW\t.prepareBuffers\t();\n\t\tCoreStates\t\t\t\t\t\t\t\t.restoreBuffers\t();\n\n\t\tIrisCompatBuffers.BLOCK_SHADOW\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tIrisCompatBuffers.ENTITY_SHADOW\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tIrisCompatBuffers.GLYPH_SHADOW\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tIrisCompatBuffers.POS_TEX_SHADOW\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tIrisCompatBuffers.POS_TEX_COLOR_SHADOW\t.drawBuffers\t(LayerDrawType.ALL);\n\n\t\tIrisCompatBuffers.BLOCK_SHADOW\t\t\t.clearBuffers\t();\n\t\tIrisCompatBuffers.ENTITY_SHADOW\t\t\t.clearBuffers\t();\n\t\tIrisCompatBuffers.GLYPH_SHADOW\t\t\t.clearBuffers\t();\n\t\tIrisCompatBuffers.POS_TEX_SHADOW\t\t.clearBuffers\t();\n\t\tIrisCompatBuffers.POS_TEX_COLOR_SHADOW\t.clearBuffers\t();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/plugin/IrisCompatMixinPlugin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.mixins.plugin;\n\nimport com.github.argon4w.acceleratedrendering.compat.AbstractCompatMixinPlugin;\n\nimport java.util.List;\n\npublic class IrisCompatMixinPlugin extends AbstractCompatMixinPlugin {\n\n\t@Override\n\tprotected List<String> getModIDs() {\n\t\treturn List.of(\"iris\");\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/vanilla/LevelRendererMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.mixins.vanilla;\n\nimport com.github.argon4w.acceleratedrendering.compat.iris.IrisCompatBuffers;\nimport com.github.argon4w.acceleratedrendering.core.CoreBuffers;\nimport com.github.argon4w.acceleratedrendering.core.CoreStates;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;\nimport net.minecraft.client.Camera;\nimport net.minecraft.client.DeltaTracker;\nimport net.minecraft.client.renderer.GameRenderer;\nimport net.minecraft.client.renderer.LevelRenderer;\nimport net.minecraft.client.renderer.LightTexture;\nimport net.minecraft.client.renderer.MultiBufferSource;\nimport org.joml.Matrix4f;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@Mixin(\n\t\tvalue\t\t= LevelRenderer.class,\n\t\tpriority\t= 999\n)\npublic class LevelRendererMixin {\n\n\t@Inject(\n\t\t\tmethod\t= \"renderLevel\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;endBatch()V\",\n\t\t\t\t\tordinal = 1\n\t\t\t)\n\t)\n\tpublic void drawIrisAllCoreBuffers(\n\t\t\tDeltaTracker\tpDeltaTracker,\n\t\t\tboolean\t\t\tpRenderBlockOutline,\n\t\t\tCamera\t\t\tpCamera,\n\t\t\tGameRenderer\tpGameRenderer,\n\t\t\tLightTexture\tpLightTexture,\n\t\t\tMatrix4f\t\tpFrustumMatrix,\n\t\t\tMatrix4f\t\tpProjectionMatrix,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tCoreStates\t\t\t\t\t\t.recordBuffers\t();\n\t\tCoreBuffers.ENTITY\t\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.BLOCK\t\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS\t\t\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS_COLOR\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS_TEX\t\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS_TEX_COLOR\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.prepareBuffers\t();\n\t\tCoreStates\t\t\t\t\t\t.restoreBuffers\t();\n\n\t\tCoreBuffers.ENTITY\t\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tCoreBuffers.BLOCK\t\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS\t\t\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS_COLOR\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS_TEX\t\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS_TEX_COLOR\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.drawBuffers\t(LayerDrawType.ALL);\n\n\t\tCoreBuffers.ENTITY\t\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.BLOCK\t\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS\t\t\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS_COLOR\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS_TEX\t\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS_TEX_COLOR\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.clearBuffers\t();\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"renderLevel\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"CONSTANT\",\n\t\t\t\t\targs\t= \"stringValue=translucent\",\n\t\t\t\t\tordinal\t= 1\n\t\t\t)\n\t)\n\tpublic void drawIrisOpaqueCoreBuffers(\n\t\t\tDeltaTracker\tpDeltaTracker,\n\t\t\tboolean\t\t\tpRenderBlockOutline,\n\t\t\tCamera\t\t\tpCamera,\n\t\t\tGameRenderer\tpGameRenderer,\n\t\t\tLightTexture\tpLightTexture,\n\t\t\tMatrix4f\t\tpFrustumMatrix,\n\t\t\tMatrix4f\t\tpProjectionMatrix,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tCoreStates\t\t\t\t\t\t.recordBuffers\t();\n\t\tCoreBuffers.ENTITY\t\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.BLOCK\t\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS\t\t\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS_COLOR\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS_TEX\t\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS_TEX_COLOR\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.prepareBuffers\t();\n\t\tCoreStates\t\t\t\t\t\t.restoreBuffers\t();\n\n\t\tCoreBuffers.ENTITY\t\t\t\t.drawBuffers\t(LayerDrawType.OPAQUE);\n\t\tCoreBuffers.BLOCK\t\t\t\t.drawBuffers\t(LayerDrawType.OPAQUE);\n\t\tCoreBuffers.POS\t\t\t\t\t.drawBuffers\t(LayerDrawType.OPAQUE);\n\t\tCoreBuffers.POS_COLOR\t\t\t.drawBuffers\t(LayerDrawType.OPAQUE);\n\t\tCoreBuffers.POS_TEX\t\t\t\t.drawBuffers\t(LayerDrawType.OPAQUE);\n\t\tCoreBuffers.POS_TEX_COLOR\t\t.drawBuffers\t(LayerDrawType.OPAQUE);\n\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.drawBuffers\t(LayerDrawType.OPAQUE);\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"renderLevel\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"CONSTANT\",\n\t\t\t\t\targs\t= \"stringValue=translucent\",\n\t\t\t\t\tordinal\t= 1,\n\t\t\t\t\tshift\t= At.Shift.AFTER\n\t\t\t)\n\t)\n\tpublic void drawIrisTranslucentCoreBuffers(\n\t\t\tDeltaTracker\tpDeltaTracker,\n\t\t\tboolean\t\t\tpRenderBlockOutline,\n\t\t\tCamera\t\t\tpCamera,\n\t\t\tGameRenderer\tpGameRenderer,\n\t\t\tLightTexture\tpLightTexture,\n\t\t\tMatrix4f\t\tpFrustumMatrix,\n\t\t\tMatrix4f\t\tpProjectionMatrix,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tCoreBuffers.ENTITY\t\t\t\t.drawBuffers\t(LayerDrawType.TRANSLUCENT);\n\t\tCoreBuffers.BLOCK\t\t\t\t.drawBuffers\t(LayerDrawType.TRANSLUCENT);\n\t\tCoreBuffers.POS\t\t\t\t\t.drawBuffers\t(LayerDrawType.TRANSLUCENT);\n\t\tCoreBuffers.POS_COLOR\t\t\t.drawBuffers\t(LayerDrawType.TRANSLUCENT);\n\t\tCoreBuffers.POS_TEX\t\t\t\t.drawBuffers\t(LayerDrawType.TRANSLUCENT);\n\t\tCoreBuffers.POS_TEX_COLOR\t\t.drawBuffers\t(LayerDrawType.TRANSLUCENT);\n\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.drawBuffers\t(LayerDrawType.TRANSLUCENT);\n\n\t\tCoreBuffers.ENTITY\t\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.BLOCK\t\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS\t\t\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS_COLOR\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS_TEX\t\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS_TEX_COLOR\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.clearBuffers\t();\n\t}\n\n\t@WrapOperation(\n\t\t\tmethod\t= \"renderLevel\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;endLastBatch()V\"\n\t\t\t)\n\t)\n\tpublic void preventDrawVanillaCoreBuffers(MultiBufferSource.BufferSource instance, Operation<Void> original) {\n\t\tinstance.endLastBatch();\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"close\",\n\t\t\tat\t\t= @At(\"TAIL\")\n\t)\n\tpublic void deleteIrisBuffers(CallbackInfo ci) {\n\t\tIrisCompatBuffers.BLOCK_SHADOW\t\t\t\t.delete();\n\t\tIrisCompatBuffers.ENTITY_SHADOW\t\t\t\t.delete();\n\t\tIrisCompatBuffers.GLYPH_SHADOW\t\t\t\t.delete();\n\t\tIrisCompatBuffers.POS_TEX_SHADOW\t\t\t.delete();\n\t\tIrisCompatBuffers.POS_TEX_COLOR_SHADOW\t\t.delete();\n\n\t\tIrisCompatBuffers.ENTITY_HAND\t\t\t\t.delete();\n\t\tIrisCompatBuffers.BLOCK_HAND\t\t\t\t.delete();\n\t\tIrisCompatBuffers.POS_HAND\t\t\t\t\t.delete();\n\t\tIrisCompatBuffers.POS_COLOR_HAND\t\t\t.delete();\n\t\tIrisCompatBuffers.POS_TEX_HAND\t\t\t\t.delete();\n\t\tIrisCompatBuffers.POS_TEX_COLOR_HAND\t\t.delete();\n\t\tIrisCompatBuffers.POS_COLOR_TEX_LIGHT_HAND\t.delete();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/programs/IrisPrograms.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.programs;\n\nimport com.github.argon4w.acceleratedrendering.compat.iris.programs.culling.IrisCullingProgramSelector;\nimport com.github.argon4w.acceleratedrendering.compat.iris.programs.processing.IrisPolygonProcessor;\nimport com.github.argon4w.acceleratedrendering.core.backends.programs.BarrierFlags;\nimport com.github.argon4w.acceleratedrendering.core.programs.LoadComputeShaderEvent;\nimport com.github.argon4w.acceleratedrendering.core.programs.culling.LoadCullingProgramSelectorEvent;\nimport com.github.argon4w.acceleratedrendering.core.programs.processing.LoadPolygonProcessorEvent;\nimport com.github.argon4w.acceleratedrendering.core.utils.ResourceLocationUtils;\nimport net.irisshaders.iris.vertices.IrisVertexFormats;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.bus.api.SubscribeEvent;\n\npublic class IrisPrograms {\n\n\tpublic static final ResourceLocation IRIS_BLOCK_VERTEX_TRANSFORM_KEY\t\t= ResourceLocationUtils.create(\"compat_block_vertex_transform_iris\");\n\tpublic static final ResourceLocation IRIS_ENTITY_VERTEX_TRANSFORM_KEY\t\t= ResourceLocationUtils.create(\"compat_entity_vertex_transform_iris\");\n\tpublic static final ResourceLocation IRIS_GLYPH_VERTEX_TRANSFORM_KEY\t\t= ResourceLocationUtils.create(\"compat_glyph_vertex_transform_iris\");\n\tpublic static final ResourceLocation IRIS_BLOCK_QUAD_CULLING_KEY\t\t\t= ResourceLocationUtils.create(\"compat_block_quad_cull_iris\");\n\tpublic static final ResourceLocation IRIS_BLOCK_TRIANGLE_CULLING_KEY\t\t= ResourceLocationUtils.create(\"compat_block_triangle_cull_iris\");\n\tpublic static final ResourceLocation IRIS_ENTITY_QUAD_CULLING_KEY\t\t\t= ResourceLocationUtils.create(\"compat_entity_quad_cull_iris\");\n\tpublic static final ResourceLocation IRIS_ENTITY_TRIANGLE_CULLING_KEY\t\t= ResourceLocationUtils.create(\"compat_entity_triangle_cull_iris\");\n\tpublic static final ResourceLocation IRIS_BLOCK_QUAD_PROCESSING_KEY\t\t\t= ResourceLocationUtils.create(\"compat_block_quad_processing_iris\");\n\tpublic static final ResourceLocation IRIS_BLOCK_TRIANGLE_PROCESSING_KEY\t\t= ResourceLocationUtils.create(\"compat_block_triangle_processing_iris\");\n\tpublic static final ResourceLocation IRIS_ENTITY_QUAD_PROCESSING_KEY\t\t= ResourceLocationUtils.create(\"compat_entity_quad_processing_iris\");\n\tpublic static final ResourceLocation IRIS_ENTITY_TRIANGLE_PROCESSING_KEY\t= ResourceLocationUtils.create(\"compat_entity_triangle_processing_iris\");\n\tpublic static final ResourceLocation IRIS_GLYPH_QUAD_PROCESSING_KEY\t\t\t= ResourceLocationUtils.create(\"compat_glyph_quad_processing_iris\");\n\tpublic static final ResourceLocation IRIS_GLYPH_TRIANGLE_PROCESSING_KEY\t\t= ResourceLocationUtils.create(\"compat_glyph_triangle_processing_iris\");\n\tpublic static final ResourceLocation IRIS_BLOCK_MESH_UPLOADING_KEY\t\t\t= ResourceLocationUtils.create(\"compat_block_mesh_uploading_iris\");\n\tpublic static final ResourceLocation IRIS_ENTITY_MESH_UPLOADING_KEY\t\t\t= ResourceLocationUtils.create(\"compat_entity_mesh_uploading_iris\");\n\tpublic static final ResourceLocation IRIS_GLYPH_MESH_UPLOADING_KEY\t\t\t= ResourceLocationUtils.create(\"compat_glyph_mesh_uploading_iris\");\n\n\t@SubscribeEvent\n\tpublic static void onLoadComputeShaders(LoadComputeShaderEvent event) {\n\t\tevent.loadComputeShader(\n\t\t\t\tIRIS_BLOCK_VERTEX_TRANSFORM_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/compat/transform/iris_block_vertex_transform_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tIRIS_ENTITY_VERTEX_TRANSFORM_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/compat/transform/iris_entity_vertex_transform_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tIRIS_GLYPH_VERTEX_TRANSFORM_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/compat/transform/iris_glyph_vertex_transform_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tIRIS_BLOCK_QUAD_CULLING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/compat/culling/iris_block_quad_culling_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE,\n\t\t\t\tBarrierFlags\t\t\t.ATOMIC_COUNTER\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tIRIS_BLOCK_TRIANGLE_CULLING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/compat/culling/iris_block_triangle_culling_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE,\n\t\t\t\tBarrierFlags\t\t\t.ATOMIC_COUNTER\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tIRIS_ENTITY_QUAD_CULLING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/compat/culling/iris_entity_quad_culling_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE,\n\t\t\t\tBarrierFlags\t\t\t.ATOMIC_COUNTER\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tIRIS_ENTITY_TRIANGLE_CULLING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/compat/culling/iris_entity_triangle_culling_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE,\n\t\t\t\tBarrierFlags\t\t\t.ATOMIC_COUNTER\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tIRIS_BLOCK_QUAD_PROCESSING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/compat/processing/iris_block_quad_processing_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tIRIS_BLOCK_TRIANGLE_PROCESSING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/compat/processing/iris_block_triangle_processing_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tIRIS_ENTITY_QUAD_PROCESSING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/compat/processing/iris_entity_quad_processing_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tIRIS_ENTITY_TRIANGLE_PROCESSING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/compat/processing/iris_entity_triangle_processing_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tIRIS_GLYPH_QUAD_PROCESSING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/compat/processing/iris_glyph_quad_processing_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tIRIS_GLYPH_TRIANGLE_PROCESSING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/compat/processing/iris_glyph_triangle_processing_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tIRIS_BLOCK_MESH_UPLOADING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/compat/uploading/iris_block_mesh_uploading_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tIRIS_ENTITY_MESH_UPLOADING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/compat/uploading/iris_entity_mesh_uploading_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tIRIS_GLYPH_MESH_UPLOADING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/compat/uploading/iris_glyph_mesh_uploading_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\t}\n\n\t@SubscribeEvent\n\tpublic static void onLoadCullingPrograms(LoadCullingProgramSelectorEvent event) {\n\t\tevent.loadFor(IrisVertexFormats.TERRAIN, parent -> new IrisCullingProgramSelector(\n\t\t\t\tparent,\n\t\t\t\tIRIS_BLOCK_QUAD_CULLING_KEY,\n\t\t\t\tIRIS_BLOCK_TRIANGLE_CULLING_KEY\n\t\t));\n\n\t\tevent.loadFor(IrisVertexFormats.ENTITY, parent -> new IrisCullingProgramSelector(\n\t\t\t\tparent,\n\t\t\t\tIRIS_ENTITY_QUAD_CULLING_KEY,\n\t\t\t\tIRIS_ENTITY_TRIANGLE_CULLING_KEY\n\t\t));\n\t}\n\n\t@SubscribeEvent\n\tpublic static void onLoadPolygonProcessors(LoadPolygonProcessorEvent event) {\n\t\tevent.loadFor(IrisVertexFormats.TERRAIN, parent -> new IrisPolygonProcessor(\n\t\t\t\tparent,\n\t\t\t\tIRIS_BLOCK_QUAD_PROCESSING_KEY,\n\t\t\t\tIRIS_BLOCK_TRIANGLE_PROCESSING_KEY\n\t\t));\n\n\t\tevent.loadFor(IrisVertexFormats.ENTITY, parent -> new IrisPolygonProcessor(\n\t\t\t\tparent,\n\t\t\t\tIRIS_ENTITY_QUAD_PROCESSING_KEY,\n\t\t\t\tIRIS_ENTITY_TRIANGLE_PROCESSING_KEY\n\t\t));\n\n\t\tevent.loadFor(IrisVertexFormats.GLYPH, parent -> new IrisPolygonProcessor(\n\t\t\t\tparent,\n\t\t\t\tIRIS_GLYPH_QUAD_PROCESSING_KEY,\n\t\t\t\tIRIS_GLYPH_TRIANGLE_PROCESSING_KEY\n\t\t));\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/programs/culling/IrisCullingProgramDispatcher.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.programs.culling;\n\nimport com.github.argon4w.acceleratedrendering.compat.iris.IrisCompatFeature;\nimport com.github.argon4w.acceleratedrendering.core.backends.programs.ComputeProgram;\nimport com.github.argon4w.acceleratedrendering.core.backends.programs.Uniform;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder;\nimport com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderProgramLoader;\nimport com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.features.culling.OrientationCullingFeature;\nimport com.mojang.blaze3d.systems.RenderSystem;\nimport com.mojang.blaze3d.vertex.VertexFormat;\nimport net.irisshaders.iris.shadows.ShadowRenderer;\nimport net.irisshaders.iris.shadows.ShadowRenderingState;\nimport net.minecraft.resources.ResourceLocation;\n\npublic class IrisCullingProgramDispatcher implements ICullingProgramDispatcher {\n\n\tprivate static\tfinal int\t\t\t\tGROUP_SIZE \t\t\t= 128;\n\tprivate static\tfinal int\t\t\t\tDISPATCH_COUNT_Y_Z\t= 1;\n\n\tprivate\t\t\tfinal VertexFormat.Mode\tmode;\n\tprivate\t\t\tfinal ComputeProgram\tprogram;\n\tprivate\t\t\tfinal Uniform\t\t\tviewMatrixUniform;\n\tprivate\t\t\tfinal Uniform\t\t\tprojectMatrixUniform;\n\tprivate\t\t\tfinal Uniform\t\t\tpolygonCountUniform;\n\tprivate\t\t\tfinal Uniform\t\t\tvertexOffsetUniform;\n\tprivate\t\t\tfinal Uniform\t\t\tvaryingOffsetUniform;\n\n\tpublic IrisCullingProgramDispatcher(VertexFormat.Mode mode, ResourceLocation key) {\n\t\tthis.mode\t\t\t\t\t= mode;\n\t\tthis.program\t\t\t\t= ComputeShaderProgramLoader.getProgram(key);\n\t\tthis.viewMatrixUniform\t\t= this.program\t\t\t\t.getUniform(\"viewMatrix\");\n\t\tthis.projectMatrixUniform\t= this.program\t\t\t\t.getUniform(\"projectMatrix\");\n\t\tthis.polygonCountUniform\t= this.program\t\t\t\t.getUniform(\"polygonCount\");\n\t\tthis.vertexOffsetUniform\t= this.program\t\t\t\t.getUniform(\"vertexOffset\");\n\t\tthis.varyingOffsetUniform\t= this.program\t\t\t\t.getUniform(\"varyingOffset\");\n\t}\n\n\t@Override\n\tpublic int dispatch(AcceleratedBufferBuilder builder) {\n\t\tvar shadowState\t\t= ShadowRenderingState\t.areShadowsCurrentlyBeingRendered\t();\n\t\tvar vertexCount\t\t= builder\t\t\t\t.getTotalVertexCount\t\t\t\t();\n\t\tvar polygonCount\t= vertexCount / mode\t.primitiveLength;\n\n\t\tviewMatrixUniform\t.uploadMatrix4f\t\t(shadowState ? ShadowRenderer.MODELVIEW\t\t: RenderSystem.getModelViewMatrix\t());\n\t\tprojectMatrixUniform.uploadMatrix4f\t\t(shadowState ? ShadowRenderer.PROJECTION\t: RenderSystem.getProjectionMatrix\t());\n\n\t\tpolygonCountUniform\t.uploadUnsignedInt\t(polygonCount);\n\t\tvertexOffsetUniform\t.uploadUnsignedInt\t((int) (builder.getVertexBuffer\t().getOffset() / builder.getVertexSize\t()));\n\t\tvaryingOffsetUniform.uploadUnsignedInt\t((int) (builder.getVaryingBuffer().getOffset() / builder.getVaryingSize\t()));\n\n\t\tprogram.useProgram\t();\n\t\tprogram.dispatch\t(\n\t\t\t\t(polygonCount + GROUP_SIZE - 1) / GROUP_SIZE,\n\t\t\t\tDISPATCH_COUNT_Y_Z,\n\t\t\t\tDISPATCH_COUNT_Y_Z\n\t\t);\n\n\t\treturn program.getBarrierFlags();\n\t}\n\n\t@Override\n\tpublic boolean shouldCull() {\n\t\treturn \t\t\tOrientationCullingFeature.shouldCull()\n\t\t\t\t&& (\tIrisCompatFeature.isShadowCullingEnabled() || !ShadowRenderingState.areShadowsCurrentlyBeingRendered());\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/programs/culling/IrisCullingProgramSelector.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.programs.culling;\n\nimport com.github.argon4w.acceleratedrendering.compat.iris.IrisCompatFeature;\nimport com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramSelector;\nimport com.github.argon4w.acceleratedrendering.core.utils.RenderTypeUtils;\nimport com.github.argon4w.acceleratedrendering.features.culling.OrientationCullingFeature;\nimport com.mojang.blaze3d.vertex.VertexFormat;\nimport net.irisshaders.iris.shadows.ShadowRenderingState;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.resources.ResourceLocation;\n\npublic class IrisCullingProgramSelector implements ICullingProgramSelector {\n\n\tprivate\t\t\tfinal ICullingProgramSelector\tparent;\n\tprivate\t\t\tfinal ICullingProgramDispatcher\tquadDispatcher;\n\tprivate\t\t\tfinal ICullingProgramDispatcher\ttriangleDispatcher;\n\n\tpublic IrisCullingProgramSelector(\n\t\t\tICullingProgramSelector\tparent,\n\t\t\tResourceLocation\t\tquadProgramKey,\n\t\t\tResourceLocation\t\ttriangleProgramKey\n\t) {\n\t\tthis.parent\t\t\t\t= parent;\n\t\tthis.quadDispatcher\t\t= new IrisCullingProgramDispatcher(VertexFormat.Mode.QUADS,\t\tquadProgramKey);\n\t\tthis.triangleDispatcher\t= new IrisCullingProgramDispatcher(VertexFormat.Mode.TRIANGLES,\ttriangleProgramKey);\n\t}\n\n\t@Override\n\tpublic ICullingProgramDispatcher select(RenderType renderType) {\n\t\tif (\t\t\tIrisCompatFeature\t\t\t.isEnabled\t\t\t\t\t()\n\t\t\t\t&&\t\tIrisCompatFeature\t\t\t.isIrisCompatCullingEnabled\t()\n\t\t\t\t&&\t(\tIrisCompatFeature\t\t\t.isShadowCullingEnabled\t\t()\t|| !\tShadowRenderingState.areShadowsCurrentlyBeingRendered())\n\t\t\t\t&&\t\tOrientationCullingFeature\t.isEnabled\t\t\t\t\t()\n\t\t\t\t&&\t(\tOrientationCullingFeature\t.shouldIgnoreCullState\t\t()\t|| \t\tRenderTypeUtils\t\t.isCulled(renderType))\n\t\t) {\n\t\t\treturn switch (renderType.mode) {\n\t\t\t\tcase QUADS\t\t-> quadDispatcher;\n\t\t\t\tcase TRIANGLES\t-> triangleDispatcher;\n\t\t\t\tdefault\t\t\t-> parent.select(renderType);\n\t\t\t};\n\t\t}\n\n\t\treturn parent.select(renderType);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/programs/processing/IrisPolygonProcessor.java",
    "content": "package com.github.argon4w.acceleratedrendering.compat.iris.programs.processing;\n\nimport com.github.argon4w.acceleratedrendering.compat.iris.IrisCompatFeature;\nimport com.github.argon4w.acceleratedrendering.core.programs.dispatchers.FixedPolygonProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.programs.dispatchers.IPolygonProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.programs.processing.IPolygonProcessor;\nimport com.mojang.blaze3d.vertex.VertexFormat;\nimport net.minecraft.resources.ResourceLocation;\n\npublic class IrisPolygonProcessor implements IPolygonProcessor {\n\n\tprivate final IPolygonProcessor\t\t\tparent;\n\tprivate final IPolygonProgramDispatcher\tquadDispatcher;\n\tprivate final IPolygonProgramDispatcher\ttriangleDispatcher;\n\n\tpublic IrisPolygonProcessor(\n\t\t\tIPolygonProcessor\tparent,\n\t\t\tResourceLocation\tquadProgramKey,\n\t\t\tResourceLocation\ttriangleProgramKey\n\t) {\n\t\tthis.parent\t\t\t\t= parent;\n\t\tthis.quadDispatcher\t\t= new FixedPolygonProgramDispatcher\t(VertexFormat.Mode.QUADS,\t\tquadProgramKey);\n\t\tthis.triangleDispatcher\t= new FixedPolygonProgramDispatcher\t(VertexFormat.Mode.TRIANGLES,\ttriangleProgramKey);\n\t}\n\n\t@Override\n\tpublic IPolygonProgramDispatcher select(VertexFormat.Mode mode) {\n\t\tif (\t\tIrisCompatFeature\t.isEnabled\t\t\t\t\t()\n\t\t\t\t&&\tIrisCompatFeature\t.isPolygonProcessingEnabled\t()\n\t\t) {\n\t\t\treturn switch (mode) {\n\t\t\t\tcase QUADS\t\t-> quadDispatcher;\n\t\t\t\tcase TRIANGLES\t-> triangleDispatcher;\n\t\t\t\tdefault\t\t\t-> parent.select(mode);\n\t\t\t};\n\t\t}\n\n\t\treturn parent.select(mode);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/configs/FeatureConfig.java",
    "content": "package com.github.argon4w.acceleratedrendering.configs;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.states.buffers.BlockBufferBindingStateType;\nimport com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache.BlockBufferBindingCacheType;\nimport com.github.argon4w.acceleratedrendering.core.backends.states.scissors.ScissorBindingStateType;\nimport com.github.argon4w.acceleratedrendering.core.backends.states.viewports.ViewportBindingStateType;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.LayerStorageType;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.MeshInfoCacheType;\nimport com.github.argon4w.acceleratedrendering.core.meshes.MeshType;\nimport com.github.argon4w.acceleratedrendering.core.meshes.data.cache.MeshDataCacheType;\nimport com.github.argon4w.acceleratedrendering.features.filter.FilterType;\nimport it.unimi.dsi.fastutil.objects.ObjectArrayList;\nimport net.neoforged.neoforge.common.ModConfigSpec;\nimport org.apache.commons.lang3.tuple.Pair;\n\nimport java.util.List;\n\npublic class FeatureConfig {\n\n\tpublic static\tfinal\tFeatureConfig\t\t\t\t\t\t\t\t\t\t\tCONFIG;\n\tpublic static\tfinal\tModConfigSpec\t\t\t\t\t\t\t\t\t\t\tSPEC;\n\n\tpublic\t\t\tfinal\tModConfigSpec.IntValue\t\t\t\t\t\t\t\t\tcorePooledRingBufferSize;\n\tpublic\t\t\tfinal\tModConfigSpec.IntValue\t\t\t\t\t\t\t\t\tcorePooledBatchingSize;\n\tpublic\t\t\tfinal\tModConfigSpec.IntValue\t\t\t\t\t\t\t\t\tcoreCachedImageSize;\n\tpublic\t\t\tfinal\tModConfigSpec.IntValue\t\t\t\t\t\t\t\t\tcoreDynamicUVResolution;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tcoreDebugContextEnabled;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tcoreForceTranslucentAcceleration;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tcoreCacheIdenticalPose;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<MeshInfoCacheType>\t\t\tcoreMeshInfoCacheType;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<LayerStorageType>\t\t\t\tcoreLayerStorageType;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<MeshDataCacheType>\t\t\t\tcoreMeshMergeType;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tcoreUploadMeshImmediately;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tcoreCacheDynamicRenderType;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<ViewportBindingStateType>\t\tcoreViewportBindingType;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<ScissorBindingStateType>\t\tcoreScissorBindingType;\n\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\trestoringFeatureStatus;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<BlockBufferBindingCacheType>\trestoringBindingCacheType;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<BlockBufferBindingStateType>\trestoringShaderStorageType;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<BlockBufferBindingStateType>\trestoringAtomicCounterType;\n\tpublic\t\t\tfinal\tModConfigSpec.IntValue\t\t\t\t\t\t\t\t\trestoringShaderStorageRange;\n\tpublic\t\t\tfinal\tModConfigSpec.IntValue\t\t\t\t\t\t\t\t\trestoringAtomicCounterRange;\n\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tacceleratedEntityRenderingFeatureStatus;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<PipelineSetting>\t\t\t\tacceleratedEntityRenderingDefaultPipeline;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<MeshType>\t\t\t\t\t\tacceleratedEntityRenderingMeshType;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tacceleratedEntityRenderingGuiAcceleration;\n\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tacceleratedTextRenderingFeatureStatus;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<PipelineSetting>\t\t\t\tacceleratedTextRenderingDefaultPipeline;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<MeshType>\t\t\t\t\t\tacceleratedTextRenderingMeshType;\n\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tacceleratedItemRenderingFeatureStatus;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tacceleratedItemRenderingBakeMeshForQuads;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<PipelineSetting>\t\t\t\tacceleratedItemRenderingDefaultPipeline;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<MeshType>\t\t\t\t\t\tacceleratedItemRenderingMeshType;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tacceleratedItemRenderingHandAcceleration;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tacceleratedItemRenderingGuiAcceleration;\n\tpublic \t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tacceleratedItemRenderingGuiItemBatching;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tacceleratedItemRenderingMergeGuiItemBatches;\n\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\torientationCullingFeatureStatus;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\torientationCullingDefaultCulling;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\torientationCullingIgnoreCullState;\n\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tfilterFeatureStatus;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tfilterMenuFilter;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tfilterEntityFilter;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tfilterBlockEntityFilter;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tfilterItemFilter;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tfilterStageFilter;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FilterType>\t\t\t\t\tfilterMenuFilterType;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FilterType>\t\t\t\t\tfilterEntityFilterType;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FilterType>\t\t\t\t\tfilterBlockEntityFilterType;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FilterType>\t\t\t\t\tfilterItemFilterType;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FilterType>\t\t\t\t\tfilterStageFilterType;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<List<? extends String>>\t\tfilterMenuFilterValues;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<List<? extends String>>\t\tfilterEntityFilterValues;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<List<? extends String>>\t\tfilterBlockEntityFilterValues;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<List<? extends String>>\t\tfilterItemFilterValues;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<List<? extends String>>\t\tfilterStageFilterValues;\n\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tirisCompatFeatureStatus;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tirisCompatOrientationCullingCompat;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tirisCompatShadowCulling;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tirisCompatPolygonProcessing;\n\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tcuriosCompatFeatureStatus;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tcuriosCompatLayerAcceleration;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FeatureStatus>\t\t\t\tcuriosItemFilter;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<FilterType>\t\t\t\t\tcuriosItemFilterType;\n\tpublic\t\t\tfinal\tModConfigSpec.ConfigValue<List<? extends String>>\t\tcuriosItemFilterValues;\n\n\tstatic {\n\t\tPair<FeatureConfig, ModConfigSpec> pair\t= new ModConfigSpec.Builder()\t.configure\t(FeatureConfig::new);\n\t\tCONFIG\t\t\t\t\t\t\t\t\t= pair\t\t\t\t\t\t\t.getLeft\t();\n\t\tSPEC\t\t\t\t\t\t\t\t\t= pair\t\t\t\t\t\t\t.getRight\t();\n\t}\n\n\tprivate FeatureConfig(ModConfigSpec.Builder builder) {\n\t\tbuilder\n\t\t\t\t.comment\t\t\t\t(\"Core Settings\")\n\t\t\t\t.comment\t\t\t\t(\"Core Settings allows you to change setting that are related to all rendering features.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings\")\n\t\t\t\t.push\t\t\t\t\t(\"core_settings\");\n\n\t\tcorePooledRingBufferSize\t\t\t\t\t\t= builder\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.comment\t\t\t\t(\"Count of buffer sets that holds data for in-flight frame rendering.\")\n\t\t\t\t.comment\t\t\t\t(\"Changing this value may affects your FPS. Smaller value means less in-flight frames, while larger values means more in-flight frames. More in-flight frames means more FPS but more VRAM.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.pooled_ring_buffer_size\")\n\t\t\t\t.defineInRange\t\t\t(\"pooled_ring_buffer_size\",\t\t\t\t8,\t1,\tInteger.MAX_VALUE);\n\n\t\tcorePooledBatchingSize\t\t\t\t\t\t\t= builder\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.comment\t\t\t\t(\"Count of batches of RenderTypes that is allowed in a draw call.\")\n\t\t\t\t.comment\t\t\t\t(\"Changing this value may affects your FPS. Smaller value means less batches allowed in a draw call, while larger values means more batches. More batches means more FPS but more VRAM and more CPU pressure on handling RenderTypes.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.pooled_batching_size\")\n\t\t\t\t.defineInRange\t\t\t(\"pooled_batching_size\",\t\t\t\t32,\t1,\tInteger.MAX_VALUE);\n\n\t\tcoreCachedImageSize\t\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"Count of images that cached for static mesh culling.\")\n\t\t\t\t.comment\t\t\t\t(\"Changing this value may affects your FPS. Smaller value means less images allowed to be cached, while larger means more cached images. More cached images means more FPS but more RAM pressure.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.cached_image_size\")\n\t\t\t\t.defineInRange\t\t\t(\"cached_image_size\",\t\t\t\t\t32,\t1,\tInteger.MAX_VALUE);\n\n\t\tcoreDynamicUVResolution\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"Resolution of UV scrolling in caching dynamic render types.\")\n\t\t\t\t.comment\t\t\t\t(\"Changing this value may affects your visual effects and VRAM usage. Smaller value means lower resolution in UV scrolling and less cached render types, while larger means higher resolution and more cached render types. Higher resolution means smoother animations on charged creepers and breezes but more VRAM usage.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.dynamic_uv_resolution\")\n\t\t\t\t.defineInRange\t\t\t(\"dynamic_uv_resolution\",\t\t\t\t64,\t1,\tInteger.MAX_VALUE);\n\n\t\tcoreDebugContextEnabled\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Debug context will be disabled, which may cause significant rendering glitches on some NVIDIA cards because of the \\\"theaded optimization\\\".\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Debug context will be enabled, which can prevent NVIDIA driver from applying the \\\"threaded optimization\\\" that causes the glitches.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.debug_context\")\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.defineEnum\t\t\t\t(\"debug_context\",\t\t\t\t\t\tFeatureStatus.ENABLED);\n\n\t\tcoreForceTranslucentAcceleration\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Translucent RenderType will fallback to vanilla rendering pipeline if the accelerated pipeline does not support translucent sorting unless mods explicitly enable force translucent acceleration temporarily when rendering their own faces.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Translucent RenderType will still be rendered in accelerated pipeline even if the pipeline does not support translucent sorting unless mods explicitly disable force translucent acceleration temporarily when rendering their own faces.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.force_translucent_acceleration\")\n\t\t\t\t.defineEnum\t\t\t\t(\"force_translucent_acceleration\",\t\tFeatureStatus.ENABLED);\n\n\t\tcoreCacheIdenticalPose\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Poses with identical transform matrix and normal matrix that used to transform vertices will not be cached in buffer which slightly decreases CPU pressure but increase VRAM usage unless mods explicitly disable it when rendering.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Poses with identical transform matrix and normal matrix that used to transform vertices will be cached in buffer which save VRAM but slightly increase CPU pressure unless mods explicitly disable it when rendering.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.cache_identical_pose\")\n\t\t\t\t.defineEnum\t\t\t\t(\"cache_identical_pose\",\t\t\t\tFeatureStatus.ENABLED);\n\n\t\tcoreMeshInfoCacheType\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- SIMPLE: The most basic implementation of cache. Usually used for testing if other cache types are working correctly.\")\n\t\t\t\t.comment\t\t\t\t(\"- HANDLE: Faster implementation of cache using VarHandle and flatten values to improve performance on read/write operations.\")\n\t\t\t\t.comment\t\t\t\t(\"- UNSAFE: Fastest implementation of cache using unsafe memory operations that skip multiple safety checks to read/write.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.mesh_info_cache_type\")\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.defineEnum\t\t\t\t(\"mesh_info_cache_type\",\t\t\t\tMeshInfoCacheType.HANDLE);\n\n\t\tcoreLayerStorageType\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- SORTED: The basic implementation of batching layer storage that renders opaque and translucent geometries together in a single stage with better performance but slight visual glitches on translucent geometries.\")\n\t\t\t\t.comment\t\t\t\t(\"- SEPARATED: The visually-precise implementation of batching layer storage that separates opaque and translucent geometries into two rendering stages to prevent visual glitches, slightly slower than basic implementation.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.layer_storage_type\")\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.defineEnum\t\t\t\t(\"layer_storage_type\",\t\t\t\t\tLayerStorageType.SEPARATED);\n\n\t\tcoreMeshMergeType\t\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- IGNORED: Meshes with identical vertices will not be merged, which will use less RAM but more VRAM in storing duplicated meshes.\")\n\t\t\t\t.comment\t\t\t\t(\"- MERGED: Meshes with identical vertices will be merged together, which will use less VRAM more RAM in storing the data of meshes used in merging.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.mesh_merge_type\")\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.defineEnum\t\t\t\t(\"mesh_merge_type\",\t\t\t\t\t\tMeshDataCacheType.MERGED);\n\n\t\tcoreUploadMeshImmediately\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Meshes that is going to be accelerated will be collected and uploaded together at the end for choosing better uploading method and increasing memory access efficiency to reach the best performance. Also this method allows mesh cache with bigger capacity (up to VRAM limit), but it may not follow the correct draw order.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Meshes that is going to be accelerated will be uploaded immediately after the draw command. It is less efficient and only have about 2GB mesh cache (generally enough) but will follow the original draw order to get the most compatibility.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.upload_mesh_immediately\")\n\t\t\t\t.defineEnum\t\t\t\t(\"upload_mesh_immediately\",\t\t\t\tFeatureStatus.DISABLED);\n\n\t\tcoreCacheDynamicRenderType\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Dynamic render types like lightning on charged creepers and winds on breezes will not be accelerated for less VRAM usage and smoother animations, but may exceptionally skip acceleration in modded geometries using these render types.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Dynamic render types like lightning on charged creepers and winds on breezes will be accelerated to accelerate modded geometries using these render types, but may have more VRAM usage and less smooth animations based on resolution settings.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.cache_dynamic_render_type\")\n\t\t\t\t.defineEnum\t\t\t\t(\"cache_dynamic_render_type\",\t\t\tFeatureStatus.ENABLED);\n\n\t\tcoreViewportBindingType\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- IGNORED: Viewport settings that will be modified by other mods will not be restored after the acceleration, which is faster but reduces compatibility with them.\")\n\t\t\t\t.comment\t\t\t\t(\"- MOJANG: Viewport settings that will be modified by other mods will be recorded and restored using Mojang's GLStateManager to work correctly with them.\")\n\t\t\t\t.comment\t\t\t\t(\"- OPENGL: Viewport settings that will be modified by other mods will be recorded and restored using OpenGL to work correctly with them even if they don't set viewport using Mojang's GLStateManager, which is slower but has most compatibility.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.viewport_binding_state\")\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.defineEnum\t\t\t\t(\"viewport_binding_state\",\t\t\t\tViewportBindingStateType.IGNORED);\n\n\t\tcoreScissorBindingType\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- IGNORED: Scissor settings that will be modified by other mods will not be restored after the acceleration, which is faster but reduces compatibility with them.\")\n\t\t\t\t.comment\t\t\t\t(\"- MOJANG: Scissor settings that will be modified by other mods will be recorded and restored using Mojang's GuiGraphics to work correctly with them.\")\n\t\t\t\t.comment\t\t\t\t(\"- OPENGL: Scissor settings that will be modified by other mods will be recorded and restored using OpenGL to work correctly with them even if they don't set viewport using Mojang's GuiGraphics, which is slower but has most compatibility.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.scissor_binding_state\")\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.defineEnum\t\t\t\t(\"scissor_binding_state\",\t\t\t\tScissorBindingStateType.MOJANG);\n\n\t\tbuilder\n\t\t\t\t.comment\t\t\t\t(\"Block Buffer Restoring Settings\")\n\t\t\t\t.comment\t\t\t\t(\"A few mods and shader packs will use their on block buffers when rendering, which may introduce conflicts when working with Accelerated Rendering that also uses block buffers.\")\n\t\t\t\t.comment\t\t\t\t(\"Block Buffer Restoring can record the binding of block buffers before the acceleration and restore them after the acceleration to work correctly with them.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring\")\n\t\t\t\t.push\t\t\t\t\t(\"block_buffer_binding_restoring\");\n\n\t\trestoringFeatureStatus\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Disable block buffer restoring, which is faster but may cause visual glitches with mods and shaders that uses block buffers.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Enable block buffer restoring, which may be slower due to recording and restoring block buffer bindings that ensures working correctly with mods and shaders that use block buffers.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.feature_status\")\n\t\t\t\t.defineEnum\t\t\t\t(\"feature_status\",\t\t\t\t\t\tFeatureStatus.ENABLED);\n\n\t\trestoringBindingCacheType\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- SIMPLE: The most basic implementation of cache. Usually used for testing if other cache types are working properly.\")\n\t\t\t\t.comment\t\t\t\t(\"- HANDLE: Faster implementation of cache using VarHandle and flatten values to improve performance on read/write operations.\")\n\t\t\t\t.comment\t\t\t\t(\"- UNSAFE: Fastest implementation of cache using unsafe memory operations that skip multiple safety checks to read/write.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.binding_cache_type\")\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.defineEnum\t\t\t\t(\"binding_cache_type\",\t\t\t\t\tBlockBufferBindingCacheType.HANDLE);\n\n\t\trestoringShaderStorageType\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- IGNORED: Shader storage buffers will not be restored which improves FPS but reduces compatibility with mods and shaders that ues shader storage buffers.\")\n\t\t\t\t.comment\t\t\t\t(\"- RESTORED: Shader storage buffers will be restored, which is slight slower but has better compatibility with mods and shaders that ues shader storage buffers.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.shader_storage_type\")\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.defineEnum\t\t\t\t(\"shader_storage_type\",\t\t\t\t\tBlockBufferBindingStateType.RESTORED);\n\n\t\trestoringAtomicCounterType\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- IGNORED: Atomic counter buffers will not be restored which improves FPS but reduces compatibility with mods and shaders that ues atomic counter buffers.\")\n\t\t\t\t.comment\t\t\t\t(\"- RESTORED: Atomic counter buffers will be restored, which is slight slower but has better compatibility with mods and shaders that ues atomic counter buffers.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.atomic_counter_type\")\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.defineEnum\t\t\t\t(\"atomic_counter_type\",\t\t\t\t\tBlockBufferBindingStateType.RESTORED);\n\n\t\trestoringShaderStorageRange\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"Range of shader storage buffer bindings that will be restored.\")\n\t\t\t\t.comment\t\t\t\t(\"Changing this value may affects your FPS. Smaller value means less shader storage buffer restored but less compatibility, while larger values means more shader storage buffer restored and better compatibility. More shader storage buffers means less FPS.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.shader_storage_range\")\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.defineInRange\t\t\t(\"shader_storage_range\",\t\t\t\t9,\t0,\t9);\n\n\t\trestoringAtomicCounterRange\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"Range of atomic counter buffer bindings that will be restored.\")\n\t\t\t\t.comment\t\t\t\t(\"Changing this value may affects your FPS. Smaller value means less atomic counter buffer restored but less compatibility, while larger values means more atomic counter buffer restored and better compatibility. More atomic counter buffers means less FPS.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.atomic_counter_range\")\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.defineInRange\t\t\t(\"atomic_counter_range\",\t\t\t\t1,\t0,\t1);\n\n\t\tbuilder.pop();\n\n\t\tbuilder.pop();\n\n\t\tbuilder\n\t\t\t\t.comment\t\t\t\t(\"Accelerated Entity Rendering Settings\")\n\t\t\t\t.comment\t\t\t\t(\"Accelerated Entity Rendering uses GPU to cache and transform vertices while rendering entities, instead of generating and transforming vertices every time the entities are rendered in CPU.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.accelerated_entity_rendering\")\n\t\t\t\t.push\t\t\t\t\t(\"accelerated_entity_rendering\");\n\n\t\tacceleratedEntityRenderingFeatureStatus\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Disable accelerated entity rendering.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Enable accelerated entity rendering.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.accelerated_entity_rendering.feature_status\")\n\t\t\t\t.defineEnum\t\t\t\t(\"feature_status\",\t\t\t\t\t\tFeatureStatus.ENABLED);\n\n\t\tacceleratedEntityRenderingDefaultPipeline\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- VANILLA: Entities will not be rendered into the accelerated pipeline unless mods explicitly enable it temporarily when rendering their own entities.\")\n\t\t\t\t.comment\t\t\t\t(\"- ACCELERATED: All entities will be rendered in the accelerated pipeline unless mods explicitly disable it temporarily when rendering their own entities.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.accelerated_entity_rendering.default_pipeline\")\n\t\t\t\t.defineEnum\t\t\t\t(\"default_pipeline\",\t\t\t\t\tPipelineSetting.ACCELERATED);\n\n\t\tacceleratedEntityRenderingMeshType\t\t\t\t= builder\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.comment\t\t\t\t(\"- CLIENT: Cached mesh will be stored on the client side (CPU), which will use less VRAM but take more time to upload to the server side (GPU) during rendering.\")\n\t\t\t\t.comment\t\t\t\t(\"- SERVER: Cached mesh will be stored on the server side (GPU), which may speed up rendering but will use more VRAM to store the mesh.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.accelerated_entity_rendering.mesh_type\")\n\t\t\t\t.defineEnum\t\t\t\t(\"mesh_type\",\t\t\t\t\t\t\tMeshType.SERVER);\n\n\t\tacceleratedEntityRenderingGuiAcceleration\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Accelerated Rendering will not accelerate entities when rendering it in a GUI unless mods explicitly enable it temporarily when rendering their own entities.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Accelerated Rendering will still accelerate entities when rendering it in a GUI unless mods explicitly disable it temporarily when rendering their own entities.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.accelerated_entity_rendering.gui_acceleration\")\n\t\t\t\t.defineEnum\t\t\t\t(\"gui_acceleration\",\t\t\t\t\tFeatureStatus.ENABLED);\n\n\t\tbuilder.pop();\n\n\t\tbuilder\n\t\t\t\t.comment\t\t\t\t(\"Accelerated Item Rendering Settings\")\n\t\t\t\t.comment\t\t\t\t(\"Accelerated Item Rendering uses GPU to cache and transform vertices while rendering item models, instead of generating and transforming vertices every time the item models are rendered in CPU.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.accelerated_item_rendering\")\n\t\t\t\t.push\t\t\t\t\t(\"accelerated_item_rendering\");\n\n\t\tacceleratedItemRenderingFeatureStatus\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Disable accelerated item rendering.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Enable accelerated item rendering.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.accelerated_item_rendering.feature_status\")\n\t\t\t\t.defineEnum\t\t\t\t(\"feature_status\",\t\t\t\t\t\tFeatureStatus.ENABLED);\n\n\t\tacceleratedItemRenderingBakeMeshForQuads\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Accelerated Rendering will not bake mesh for quads provided by dynamic item models (something that is not SimpleBakedModel) unless mods explicitly enable it temporarily when rendering their own item models.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Accelerated Rendering will bake mesh for all quads provided by dynamic item models (something that is not SimpleBakedModel) unless mods explicitly disable it temporarily when rendering their own item models, which will accelerate the rendering of these models but will crash if they keep allocating new quad data. (but who will?)\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.accelerated_item_rendering.bake_mesh_for_quads\")\n\t\t\t\t.defineEnum\t\t\t\t(\"bake_mesh_for_quads\",\t\t\t\t\tFeatureStatus.ENABLED);\n\n\t\tacceleratedItemRenderingDefaultPipeline\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- VANILLA: Item models will not be rendered into the accelerated pipeline unless mods explicitly enable it temporarily when rendering their own item models.\")\n\t\t\t\t.comment\t\t\t\t(\"- ACCELERATED: All item models will be rendered in the accelerated pipeline unless mods explicitly disable it temporarily when rendering their own item models.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.accelerated_item_rendering.default_pipeline\")\n\t\t\t\t.defineEnum\t\t\t\t(\"default_pipeline\",\t\t\t\t\tPipelineSetting.ACCELERATED);\n\n\t\tacceleratedItemRenderingMeshType\t\t\t\t= builder\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.comment\t\t\t\t(\"- CLIENT: Cached mesh will be stored on the client side (CPU), which will use less VRAM but take more time to upload to the server side (GPU) during rendering.\")\n\t\t\t\t.comment\t\t\t\t(\"- SERVER: Cached mesh will be stored on the server side (GPU), which may speed up rendering but will use more VRAM to store the mesh.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.accelerated_item_rendering.mesh_type\")\n\t\t\t\t.defineEnum\t\t\t\t(\"mesh_type\",\t\t\t\t\t\t\tMeshType.SERVER);\n\n\t\tacceleratedItemRenderingHandAcceleration\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Accelerated Rendering will not accelerate item models that are marked as \\\"too small to make up the cost of acceleration\\\" when rendering it in hand unless mods explicitly enable it temporarily when rendering their own item models.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Accelerated Rendering will still accelerate item models that are marked as \\\"too small to make up the cost of acceleration\\\" when rendering it in hand unless mods explicitly disable it temporarily when rendering their own item models, which may slightly reduce the FPS but accelerate vanilla-like modded item models with large amount of vertices.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.accelerated_item_rendering.hand_acceleration\")\n\t\t\t\t.defineEnum\t\t\t\t(\"hand_acceleration\",\t\t\t\t\tFeatureStatus.ENABLED);\n\n\t\tacceleratedItemRenderingGuiAcceleration\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Accelerated Rendering will not accelerate item models that are marked as \\\"too small to make up the cost of acceleration\\\" when rendering it in a container GUI unless mods explicitly enable it temporarily when rendering their own item models.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Accelerated Rendering will still accelerate item models that are marked as \\\"too small to make up the cost of acceleration\\\" when rendering it in a container GUI unless mods explicitly disable it temporarily when rendering their own item models, which may slightly reduce the FPS but accelerate vanilla-like modded item models with large amount of vertices.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.accelerated_item_rendering.gui_acceleration\")\n\t\t\t\t.defineEnum\t\t\t\t(\"gui_acceleration\",\t\t\t\t\tFeatureStatus.ENABLED);\n\n\t\tacceleratedItemRenderingGuiItemBatching\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Items in the container GUI will be rendered as per item per batch if the GUI Acceleration is enabled, which is inefficient and may cause reduction in FPS, but it has better compatibility in modded container GUI.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Items in the container will be rendered together in a single batch if the GUI Acceleration is enabled, which is much more efficient but has little compatibility in modded container GUI.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.accelerated_item_rendering.gui_item_batching\")\n\t\t\t\t.defineEnum\t\t\t\t(\"gui_item_batching\",\t\t\t\t\tFeatureStatus.ENABLED);\n\n\t\tacceleratedItemRenderingMergeGuiItemBatches\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Items rendered in background and slots will be separated into two batches when accelerate container GUI, which is inefficient any may cause slight reduction in FPS, but it has better compatibility in modded container GUI.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Items rendered in background and slots will be merged into a single batch when accelerate container GUI, which is much more efficient but has less compatibility in modded container GUI.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.accelerated_item_rendering.merge_gui_item_batching\")\n\t\t\t\t.defineEnum\t\t\t\t(\"merge_gui_item_batching\",\t\t\t\tFeatureStatus.ENABLED);\n\n\t\tbuilder.pop();\n\n\t\tbuilder\n\t\t\t\t.comment\t\t\t\t(\"Accelerated Text Rendering Settings\")\n\t\t\t\t.comment\t\t\t\t(\"Accelerated Text Rendering uses GPU to cache and transform vertices while rendering text through BakedGlyph, instead of generating and transforming vertices every time the text are rendered in CPU.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.accelerated_text_rendering\")\n\t\t\t\t.push\t\t\t\t\t(\"accelerated_text_rendering\");\n\n\t\tacceleratedTextRenderingFeatureStatus\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Disable accelerated text rendering.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Enable accelerated text rendering.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.accelerated_text_rendering.feature_status\")\n\t\t\t\t.defineEnum\t\t\t\t(\"feature_status\",\t\t\t\t\t\tFeatureStatus.ENABLED);\n\n\t\tacceleratedTextRenderingDefaultPipeline\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- VANILLA: Text will not be rendered into the accelerated pipeline unless mods explicitly enable it temporarily when rendering their own text.\")\n\t\t\t\t.comment\t\t\t\t(\"- ACCELERATED: All text will be rendered in the accelerated pipeline unless mods explicitly disable it temporarily when rendering their own text.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.accelerated_text_rendering.default_pipeline\")\n\t\t\t\t.defineEnum\t\t\t\t(\"default_pipeline\",\t\t\t\t\tPipelineSetting.ACCELERATED);\n\n\t\tacceleratedTextRenderingMeshType\t\t\t\t= builder\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.comment\t\t\t\t(\"- CLIENT: Cached mesh will be stored on the client side (CPU), which will use less VRAM but take more time to upload to the server side (GPU) during rendering.\")\n\t\t\t\t.comment\t\t\t\t(\"- SERVER: Cached mesh will be stored on the server side (GPU), which may speed up rendering but will use more VRAM to store the mesh.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.accelerated_text_rendering.mesh_type\")\n\t\t\t\t.defineEnum\t\t\t\t(\"mesh_type\",\t\t\t\t\t\t\tMeshType.SERVER);\n\n\t\tbuilder.pop();\n\n\t\tbuilder\n\t\t\t\t.comment\t\t\t\t(\"Simple Orientation Face Culling Settings\")\n\t\t\t\t.comment\t\t\t\t(\"Simple Orientation face culling uses an compute shader before the draw call to discard faces that is not visible on screen by checking if it is facing to the screen using a determinant of 3 * 3 matrix.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.orientation_culling\")\n\t\t\t\t.push\t\t\t\t\t(\"orientation_culling\");\n\n\t\torientationCullingFeatureStatus\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Disable simple orientation face culling.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Enable simple orientation face culling.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.orientation_culling.feature_status\")\n\t\t\t\t.defineEnum\t\t\t\t(\"feature_Status\",\t\t\t\t\t\tFeatureStatus.ENABLED);\n\n\t\torientationCullingDefaultCulling\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Faces will not be culled unless mods explicitly enable it temporarily when rendering their own faces.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: All faces will be culled unless mods explicitly disable it temporarily when rendering their own faces.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.orientation_culling.default_culling\")\n\t\t\t\t.defineEnum\t\t\t\t(\"default_culling\",\t\t\t\t\t\tFeatureStatus.ENABLED);\n\n\t\torientationCullingIgnoreCullState\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Simple orientation face culling will not cull entities that are not declared as \\\"cullable\\\".\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Simple orientation face culling will cull all entities even if they are not declared as \\\"cullable\\\".\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.orientation_culling.ignore_cull_state\")\n\t\t\t\t.defineEnum\t\t\t\t(\"ignore_cull_state\",\t\t\t\t\tFeatureStatus.DISABLED);\n\n\t\tbuilder.pop();\n\n\t\tbuilder\n\t\t\t\t.comment\t\t\t\t(\"Filters Settings\")\n\t\t\t\t.comment\t\t\t\t(\"Filters allows you to prevent specific entities/block entities/items from being accelerated when rendering for better compatibility.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.filter\")\n\t\t\t\t.push\t\t\t\t\t(\"filter\");\n\n\t\tfilterFeatureStatus\t\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Filters will be disabled and all entities, block entities and items will be accelerated when rendering.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Filters will test if the entities, block entities and items should be accelerated when rendering based on the filter values and the filter type.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.filter.feature_status\")\n\t\t\t\t.defineEnum\t\t\t\t(\"feature_status\",\t\t\t\t\t\tFeatureStatus.ENABLED);\n\n\t\tfilterMenuFilter\t\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Menu filter will be disabled and geometries in all container GUI will be accelerated.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Menu filter will test if geometries in specific container GUI should be accelerated when rendering based on the filter values and the filter type.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.filter.menu_filter\")\n\t\t\t\t.defineEnum\t\t\t\t(\"menu_filter\",\t\t\t\t\t\t\tFeatureStatus.ENABLED);\n\n\t\tfilterEntityFilter\t\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Entity filter will be disabled and all entities will be accelerated.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Entity filter will test if the entities should be accelerated when rendering based on the filter values and the filter type.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.filter.entity_filter\")\n\t\t\t\t.defineEnum\t\t\t\t(\"entity_filter\",\t\t\t\t\t\tFeatureStatus.DISABLED);\n\n\t\tfilterBlockEntityFilter\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Block entity filter will be disabled and all block entities will be accelerated.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Block entity filter will test if the block entities should be accelerated when rendering based on the filter values and the filter type.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.filter.block_entity_filter\")\n\t\t\t\t.defineEnum\t\t\t\t(\"block_entity_filter\",\t\t\t\t\tFeatureStatus.DISABLED);\n\n\t\tfilterItemFilter\t\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Item filter will be disabled and all items will be accelerated.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Item filter will test if the items should be accelerated when rendering based on the filter values and the filter type.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.filter.item_filter\")\n\t\t\t\t.defineEnum\t\t\t\t(\"item_filter\",\t\t\t\t\t\t\tFeatureStatus.DISABLED);\n\n\t\tfilterStageFilter\t\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Custom rendering stage filter will be disabled and geometries in all custom rendering stages will be accelerated.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Custom rendering stage filter will test if geometries in specific custom rendering stage should be accelerated when rendering based on the filter values and the filter type.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.filter.stage_filter\")\n\t\t\t\t.defineEnum\t\t\t\t(\"stage_filter\",\t\t\t\t\t\tFeatureStatus.ENABLED);\n\n\t\tfilterMenuFilterType\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- BLACKLIST: Container GUIs that are not in the filter values can pass the filter and be accelerated when rendering.\")\n\t\t\t\t.comment\t\t\t\t(\"- WHITELIST: Container GUIs that are in the filter values can pass the filter and be accelerated when rendering.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.filter.menu_filter_type\")\n\t\t\t\t.defineEnum\t\t\t\t(\"menu_filter_type\",\t\t\t\t\tFilterType.WHITELIST);\n\n\t\tfilterEntityFilterType\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- BLACKLIST: Entities that are not in the filter values can pass the filter and be accelerated when rendering.\")\n\t\t\t\t.comment\t\t\t\t(\"- WHITELIST: Entities that are in the filter values can pass the filter and be accelerated when rendering.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.filter.entity_filter_type\")\n\t\t\t\t.defineEnum\t\t\t\t(\"entity_filter_type\",\t\t\t\t\tFilterType.BLACKLIST);\n\n\t\tfilterBlockEntityFilterType\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- BLACKLIST: Block entities that are not in the filter values can pass the filter and be accelerated when rendering.\")\n\t\t\t\t.comment\t\t\t\t(\"- WHITELIST: Block entities that are in the filter values can pass the filter and be accelerated when rendering.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.filter.block_entity_filter_type\")\n\t\t\t\t.defineEnum\t\t\t\t(\"block_entity_filter_type\",\t\t\tFilterType.BLACKLIST);\n\n\t\tfilterItemFilterType\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- BLACKLIST: Items that are not in the filter values can pass the filter and be accelerated when rendering.\")\n\t\t\t\t.comment\t\t\t\t(\"- WHITELIST: Items that are in the filter values can pass the filter and be accelerated when rendering.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.filter.item_filter_type\")\n\t\t\t\t.defineEnum\t\t\t\t(\"item_filter_type\",\t\t\t\t\tFilterType.BLACKLIST);\n\n\t\tfilterStageFilterType\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- BLACKLIST: Custom rendering stages that are not in the filter values can pass the filter and be accelerated when rendering.\")\n\t\t\t\t.comment\t\t\t\t(\"- WHITELIST: Custom rendering stages that are in the filter values can pass the filter and be accelerated when rendering.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.filter.stage_filter_type\")\n\t\t\t\t.defineEnum\t\t\t\t(\"stage_filter_type\",\t\t\t\t\tFilterType.WHITELIST);\n\n\t\tfilterMenuFilterValues\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"You can configure the menu filter by this list.\")\n\t\t\t\t.comment\t\t\t\t(\"Menu filter will use this list and the filter type to determine if a container GUI can pass the filter.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.filter.menu_filter_values\")\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.defineListAllowEmpty\t(\"menu_filter_values\",\t\t\t\t\tObjectArrayList.of(\"minecraft:.*\"),\t\t\t\t\t\t\t\t() -> \"minecraft:empty\", object -> object instanceof String);\n\n\t\tfilterEntityFilterValues\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"You can configure the entity filter by this list.\")\n\t\t\t\t.comment\t\t\t\t(\"Entity filter will use this list and the filter type to determine if an entity can pass the filter.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.filter.entity_filter_values\")\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.defineListAllowEmpty\t(\"entity_filter_values\",\t\t\t\tnew ObjectArrayList<>(),\t\t\t\t\t\t\t\t\t\t() -> \"minecraft:empty\", object -> object instanceof String);\n\n\t\tfilterBlockEntityFilterValues\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"You can configure the block entity filter by this list.\")\n\t\t\t\t.comment\t\t\t\t(\"Block entity filter will use this list and the filter type to determine if a block entity can pass the filter.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.filter.block_entity_filter_values\")\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.defineListAllowEmpty\t(\"block_entity_filter_values\",\t\t\tnew ObjectArrayList<>(),\t\t\t\t\t\t\t\t\t\t() -> \"minecraft:empty\", object -> object instanceof String);\n\n\t\tfilterItemFilterValues\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"You can configure the item filter by this list.\")\n\t\t\t\t.comment\t\t\t\t(\"Item filter will use this list and the filter type to determine if an item can pass the filter.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.filter.item_filter_values\")\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.defineListAllowEmpty\t(\"item_filter_values\",\t\t\t\t\tnew ObjectArrayList<>(),\t\t\t\t\t\t\t\t\t\t() -> \"minecraft:empty\", object -> object instanceof String);\n\n\t\tfilterStageFilterValues\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"You can configure the custom rendering stage filter by this list.\")\n\t\t\t\t.comment\t\t\t\t(\"Custom rendering stage filter will use this list and the filter type to determine if a custom rendering stage can pass the filter.\")\n\t\t\t\t.comment\t\t\t\t(\"It's not recommend to modify this list unless other mods adds their own custom rendering stages.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.filter.stage_filter_values\")\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.defineListAllowEmpty\t(\"stage_filter_values\",\t\t\t\t\tObjectArrayList.of(\"after_entities\", \"after_block_entities\"),\t() -> \"minecraft:empty\", object -> object instanceof String);\n\n\t\tbuilder.pop();\n\n\t\tbuilder\n\t\t\t\t.comment\t\t\t\t(\"Iris Compatibility Settings\")\n\t\t\t\t.comment\t\t\t\t(\"Iris Compatibility Settings allows Accelerated Rendering to work correctly with Iris.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.iris_compatibility\")\n\t\t\t\t.push\t\t\t\t\t(\"iris_compatibility\");\n\n\t\tirisCompatFeatureStatus\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Accelerated Rendering will be incompatible with Iris and cause visual glitches when working with Iris.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Accelerated Rendering will use compute shaders that fits Iris's vertex formats, which make it compatible with Iris.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.iris_compatibility.feature_status\")\n\t\t\t\t.defineEnum\t\t\t\t(\"feature_status\",\t\t\t\t\t\tFeatureStatus.ENABLED);\n\n\t\tirisCompatOrientationCullingCompat\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Simple Orientation culling will not work with Iris because the culling shader is for vanilla's vertex formats.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Simple Orientation culling will use another culling shader that fits iris's vertex format, which make it compatible with Iris.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.iris_compatibility.orientation_culling_compatibility\")\n\t\t\t\t.defineEnum\t\t\t\t(\"orientation_culling_compatibility\",\tFeatureStatus.ENABLED);\n\n\t\tirisCompatShadowCulling\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Entities will not be culled when they are rendered as shadows unless mods explicitly enable it temporarily when rendering their own shadows. Which reduce FPS due to redundant faces.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Entities will be culled when they are rendered as shadows unless mods explicitly disable it temporarily when rendering their own shadows. Redundant faces will be culled and improve FPS, but it may cause incorrect shadows.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.iris_compatibility.shadow_culling\")\n\t\t\t\t.defineEnum\t\t\t\t(\"shadow_culling\",\t\t\t\t\t\tFeatureStatus.ENABLED);\n\n\t\tirisCompatPolygonProcessing\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Extra information in vertices provided by Iris will not be included or calculated in the accelerated pipeline unless mods explicitly enable it temporarily when rendering their own faces, which may cause visual glitches or incorrect rendering.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Extra information in vertices provided by Iris will be included and calculated in the accelerated pipeline by a compute shader unless mods explicitly disable it temporarily when rendering their own faces.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.iris_compatibility.polygon_processing\")\n\t\t\t\t.defineEnum\t\t\t\t(\"polygon_processing\",\t\t\t\t\tFeatureStatus.ENABLED);\n\n\t\tbuilder.pop();\n\n\t\tbuilder\n\t\t\t\t.comment\t\t\t\t(\"Curios Compatibility Settings\")\n\t\t\t\t.comment\t\t\t\t(\"Curios Compatibility Settings allows Accelerated Rendering to work correctly with Curios.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.curios_compatibility\")\n\t\t\t\t.push\t\t\t\t\t(\"curios_compatibility\");\n\n\t\tcuriosCompatFeatureStatus\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Accelerated Rendering will not interrupt the acceleration of the Curios layer on entities.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Accelerated Rendering will interrupt the acceleration of Curios layer on entities to prevent some mods using extremely bad rendering code that breaks the caching of Accelerated Rendering.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.curios_compatibility.feature_status\")\n\t\t\t\t.defineEnum\t\t\t\t(\"feature_status\",\t\t\t\t\t\tFeatureStatus.ENABLED);\n\n\t\tcuriosCompatLayerAcceleration\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Curios layer will not be accelerated by default to prevent some mods using extremely bad rendering code that breaks the caching of Accelerated Rendering unless mods explicitly enable the acceleration when rendering their accessories or equipments.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Curios layer will be accelerated by default unless mods explicitly enable the acceleration when rendering their accessories or equipments.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.curios_compatibility.layer_acceleration\")\n\t\t\t\t.defineEnum\t\t\t\t(\"layer_acceleration\",\t\t\t\t\tFeatureStatus.DISABLED);\n\n\t\tcuriosItemFilter\t\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- DISABLED: Curios item filter will be disabled and acceleration of the rendering of all curios accessories/equipments will be determined by the \\\"layer acceleration\\\" option.\")\n\t\t\t\t.comment\t\t\t\t(\"- ENABLED: Curios item filter will test if the acceleration of the curios accessories/equipments should be prevented based on the filter values and the filter type.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.curios_compatibility.item_filter\")\n\t\t\t\t.defineEnum\t\t\t\t(\"item_filter\",\t\t\t\t\t\t\tFeatureStatus.DISABLED);\n\n\t\tcuriosItemFilterType\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"- BLACKLIST: Curios items that are not in the filter values can pass the filter and not being prevented to be accelerated.\")\n\t\t\t\t.comment\t\t\t\t(\"- WHITELIST: Curios items that are in the filter values can pass the filter and not being prevented to be accelerated.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.curios_compatibility.item_filter_type\")\n\t\t\t\t.defineEnum\t\t\t\t(\"item_filter_type\",\t\t\t\t\tFilterType.BLACKLIST);\n\n\t\tcuriosItemFilterValues\t\t\t\t\t\t\t= builder\n\t\t\t\t.comment\t\t\t\t(\"You can configure the curios item filter by this list.\")\n\t\t\t\t.comment\t\t\t\t(\"Curios item filter will use this list and the filter type to determine if a curios item can pass the filter.\")\n\t\t\t\t.translation\t\t\t(\"acceleratedrendering.configuration.curios_compatibility.item_filter_values\")\n\t\t\t\t.gameRestart\t\t\t()\n\t\t\t\t.defineListAllowEmpty\t(\"item_filter_values\",\t\t\t\t\tnew ObjectArrayList<>(), () -> \"minecraft:air\", object -> object instanceof String);\n\n\t\tbuilder.pop();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/configs/FeatureStatus.java",
    "content": "package com.github.argon4w.acceleratedrendering.configs;\n\npublic enum FeatureStatus {\n\n\tDISABLED,\n\tENABLED\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/configs/PipelineSetting.java",
    "content": "package com.github.argon4w.acceleratedrendering.configs;\n\npublic enum PipelineSetting {\n\n\tVANILLA,\n\tACCELERATED\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/CoreBuffers.java",
    "content": "package com.github.argon4w.acceleratedrendering.core;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.AcceleratedBufferSources;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.AcceleratedBufferSource;\nimport com.github.argon4w.acceleratedrendering.core.buffers.environments.IBufferEnvironment;\nimport com.mojang.blaze3d.vertex.VertexFormat;\n\npublic class CoreBuffers {\n\n\tpublic static final AcceleratedBufferSource BLOCK\t\t\t\t\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.BLOCK);\n\tpublic static final AcceleratedBufferSource ENTITY\t\t\t\t\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.ENTITY);\n\tpublic static final AcceleratedBufferSource\tPOS\t\t\t\t\t\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.POS);\n\tpublic static final AcceleratedBufferSource POS_COLOR\t\t\t\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_COLOR);\n\tpublic static final AcceleratedBufferSource POS_TEX\t\t\t\t\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_TEX);\n\tpublic static final AcceleratedBufferSource POS_TEX_COLOR\t\t\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_TEX_COLOR);\n\tpublic static final AcceleratedBufferSource POS_COLOR_TEX_LIGHT\t\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_COLOR_TEX_LIGHT);\n\tpublic static final AcceleratedBufferSource POS_TEX_COLOR_OUTLINE\t= new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_TEX_COLOR);\n\n\tpublic static final AcceleratedBufferSources CORE = AcceleratedBufferSources\n\t\t\t.builder()\n\t\t\t.source\t(CoreBuffers\t\t.BLOCK)\n\t\t\t.source\t(CoreBuffers\t\t.ENTITY)\n\t\t\t.source\t(CoreBuffers\t\t.POS)\n\t\t\t.source\t(CoreBuffers\t\t.POS_COLOR)\n\t\t\t.source\t(CoreBuffers\t\t.POS_TEX)\n\t\t\t.source\t(CoreBuffers\t\t.POS_TEX_COLOR)\n\t\t\t.source\t(CoreBuffers\t\t.POS_COLOR_TEX_LIGHT)\n\t\t\t.mode\t(VertexFormat.Mode\t.QUADS)\n\t\t\t.mode\t(VertexFormat.Mode\t.TRIANGLES)\n\t\t\t.build\t();\n\n\tpublic static final AcceleratedBufferSources OUTLINE = AcceleratedBufferSources\n\t\t\t.builder()\n\t\t\t.source\t(CoreBuffers\t\t.POS_TEX_COLOR_OUTLINE)\n\t\t\t.mode\t(VertexFormat.Mode\t.QUADS)\n\t\t\t.mode\t(VertexFormat.Mode\t.TRIANGLES)\n\t\t\t.build\t();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/CoreBuffersProvider.java",
    "content": "package com.github.argon4w.acceleratedrendering.core;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.EmptyAcceleratedBufferSources;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAcceleratedBufferSource;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.BufferSourceExtension;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.RenderBuffers;\n\nimport java.util.function.Supplier;\n\n@ExtensionMethod(BufferSourceExtension.class)\npublic class CoreBuffersProvider {\n\n\tpublic static final Supplier<IAcceleratedBufferSource> EMPTY\t= () -> EmptyAcceleratedBufferSources\t.INSTANCE;\n\tpublic static final Supplier<IAcceleratedBufferSource> CORE\t\t= () -> CoreBuffers\t\t\t\t\t\t.CORE;\n\tpublic static final Supplier<IAcceleratedBufferSource> OUTLINE\t= () -> CoreBuffers\t\t\t\t\t\t.OUTLINE;\n\n\tpublic static void bindAcceleratedBufferSources(RenderBuffers renderBuffers) {\n\t\trenderBuffers.bufferSource\t\t\t().getAcceleratable().bindAcceleratedBufferSource(CoreBuffersProvider.CORE);\n\t\trenderBuffers.crumblingBufferSource\t().getAcceleratable().bindAcceleratedBufferSource(CoreBuffersProvider.CORE);\n\t\trenderBuffers.outlineBufferSource\t().getAcceleratable().bindAcceleratedBufferSource(CoreBuffersProvider.OUTLINE);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/CoreFeature.java",
    "content": "package com.github.argon4w.acceleratedrendering.core;\n\nimport com.github.argon4w.acceleratedrendering.configs.FeatureConfig;\nimport com.github.argon4w.acceleratedrendering.configs.FeatureStatus;\nimport com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState;\nimport com.github.argon4w.acceleratedrendering.core.backends.states.buffers.BlockBufferBindingStateType;\nimport com.github.argon4w.acceleratedrendering.core.backends.states.buffers.BufferBlockType;\nimport com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache.BlockBufferBindingCacheType;\nimport com.github.argon4w.acceleratedrendering.core.backends.states.scissors.ScissorBindingStateType;\nimport com.github.argon4w.acceleratedrendering.core.backends.states.viewports.ViewportBindingStateType;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.ILayerStorage;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.LayerStorageType;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.IMeshInfoCache;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.MeshInfoCacheType;\nimport com.github.argon4w.acceleratedrendering.core.meshes.data.cache.IMeshDataCache;\nimport com.github.argon4w.acceleratedrendering.core.meshes.data.cache.MeshDataCacheType;\nimport com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderProgramLoader;\nimport com.github.argon4w.acceleratedrendering.core.utils.PackedVector2i;\nimport com.google.common.util.concurrent.Runnables;\n\nimport java.util.ArrayDeque;\n\npublic class CoreFeature {\n\n\tprivate static final\tArrayDeque<FeatureStatus>\tFORCE_TRANSLUCENT_ACCELERATION_CONTROLLER_STACK\t= new ArrayDeque<>();\n\tprivate static final\tArrayDeque<FeatureStatus>\tCACHE_IDENTICAL_POSE_CONTROLLER_STACK\t\t\t= new ArrayDeque<>();\n\tprivate static final\tArrayDeque<Integer>\t\t\tDEFAULT_LAYER_CONTROLLER_STACK\t\t\t\t\t= new ArrayDeque<>();\n\tprivate static final\tArrayDeque<Runnable>\t\tDEFAULT_LAYER_BEFORE_FUNCTION_CONTROLLER_STACK\t= new ArrayDeque<>();\n\tprivate static final\tArrayDeque<Runnable>\t\tDEFAULT_LAYER_AFTER_FUNCTION_CONTROLLER_STACK\t= new ArrayDeque<>();\n\tprivate static \t\t\tboolean\t\t\t\t\t\tRENDERING_LEVEL\t\t\t\t\t\t\t\t\t= false;\n\tprivate static\t\t\tboolean\t\t\t\t\t\tRENDERING_HAND\t\t\t\t\t\t\t\t\t= false;\n\tprivate static\t\t\tboolean\t\t\t\t\t\tRENDERING_GUI\t\t\t\t\t\t\t\t\t= false;\n\tprivate static\t\t\tboolean\t\t\t\t\t\tGUI_BATCHING\t\t\t\t\t\t\t\t\t= false;\n\n\tpublic static boolean isLoaded() {\n\t\treturn ComputeShaderProgramLoader.isProgramsLoaded();\n\t}\n\n\tpublic static boolean isConfigLoaded() {\n\t\treturn FeatureConfig.SPEC.isLoaded();\n\t}\n\n\tpublic static boolean isDebugContextEnabled() {\n\t\treturn FeatureConfig.CONFIG.coreDebugContextEnabled.get() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static int getPooledRingBufferSize() {\n\t\treturn FeatureConfig.CONFIG.corePooledRingBufferSize.getAsInt();\n\t}\n\n\tpublic static int getPooledBatchingSize() {\n\t\treturn FeatureConfig.CONFIG.corePooledBatchingSize.getAsInt();\n\t}\n\n\tpublic static int getCachedImageSize() {\n\t\treturn FeatureConfig.CONFIG.coreCachedImageSize.getAsInt();\n\t}\n\n\tpublic static float getDynamicUVResolution() {\n\t\treturn FeatureConfig.CONFIG.coreDynamicUVResolution.getAsInt();\n\t}\n\n\tpublic static boolean shouldForceAccelerateTranslucent() {\n\t\treturn getForceTranslucentAccelerationSetting() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean shouldCacheIdenticalPose() {\n\t\treturn getCacheIdenticalPoseSetting() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static MeshInfoCacheType getMeshInfoCacheType() {\n\t\treturn FeatureConfig.CONFIG.coreMeshInfoCacheType.get();\n\t}\n\n\tpublic static LayerStorageType getLayerStorageType() {\n\t\treturn FeatureConfig.CONFIG.coreLayerStorageType.get();\n\t}\n\n\tpublic static MeshDataCacheType getMeshMergeType() {\n\t\treturn FeatureConfig.CONFIG.coreMeshMergeType.get();\n\t}\n\n\tpublic static boolean shouldUploadMeshImmediately() {\n\t\treturn FeatureConfig.CONFIG.coreUploadMeshImmediately.get() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean shouldCacheDynamicRenderType() {\n\t\treturn FeatureConfig.CONFIG.coreCacheDynamicRenderType.get() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean shouldRestoreBlockBuffers() {\n\t\treturn FeatureConfig.CONFIG.restoringFeatureStatus.get() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static BlockBufferBindingCacheType getBlockBufferBindingCacheType() {\n\t\treturn FeatureConfig.CONFIG.restoringBindingCacheType.get();\n\t}\n\n\tpublic static BlockBufferBindingStateType getShaderStorageStateType() {\n\t\treturn FeatureConfig.CONFIG.restoringShaderStorageType.get();\n\t}\n\n\tpublic static ViewportBindingStateType getViewportBindingStateType() {\n\t\treturn FeatureConfig.CONFIG.coreViewportBindingType.get();\n\t}\n\n\tpublic static ScissorBindingStateType getScissorBindingStateType() {\n\t\treturn FeatureConfig.CONFIG.coreScissorBindingType.get();\n\t}\n\n\tpublic static BlockBufferBindingStateType getAtomicCounterStateType() {\n\t\treturn FeatureConfig.CONFIG.restoringAtomicCounterType.get();\n\t}\n\n\tpublic static int getShaderStorageRestoringRange() {\n\t\treturn FeatureConfig.CONFIG.restoringShaderStorageRange.getAsInt();\n\t}\n\n\tpublic static int getAtomicCounterRestoringRange() {\n\t\treturn FeatureConfig.CONFIG.restoringAtomicCounterRange.getAsInt();\n\t}\n\n\tpublic static IMeshInfoCache createMeshInfoCache() {\n\t\treturn getMeshInfoCacheType().create();\n\t}\n\n\tpublic static ILayerStorage createLayerStorage() {\n\t\treturn getLayerStorageType().create(getPooledBatchingSize());\n\t}\n\n\tpublic static IMeshDataCache createMeshDataCache() {\n\t\treturn getMeshMergeType().create();\n\t}\n\n\tpublic static IBindingState createViewportState() {\n\t\treturn getViewportBindingStateType().create();\n\t}\n\n\tpublic static IBindingState createScissorState() {\n\t\treturn getScissorBindingStateType().create();\n\t}\n\n\tpublic static IBindingState createShaderStorageState() {\n\t\treturn getShaderStorageStateType().create(getBlockBufferBindingCacheType(), BufferBlockType.SHADER_STORAGE, getShaderStorageRestoringRange());\n\t}\n\n\tpublic static IBindingState createAtomicCounterState() {\n\t\treturn getAtomicCounterStateType().create(getBlockBufferBindingCacheType(), BufferBlockType.ATOMIC_COUNTER, getAtomicCounterRestoringRange());\n\t}\n\n\tpublic static int packDynamicUV(float u, float v) {\n\t\treturn PackedVector2i.pack(u * getDynamicUVResolution(), v * getDynamicUVResolution());\n\t}\n\n\tpublic static float unpackDynamicU(int packedUV) {\n\t\treturn PackedVector2i.unpackU(packedUV) / getDynamicUVResolution();\n\t}\n\n\tpublic static float unpackDynamicV(int packedUV) {\n\t\treturn PackedVector2i.unpackV(packedUV) / getDynamicUVResolution();\n\t}\n\n\tpublic static void disableForceTranslucentAcceleration() {\n\t\tFORCE_TRANSLUCENT_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.DISABLED);\n\t}\n\n\tpublic static void disableCacheIdenticalPose() {\n\t\tCACHE_IDENTICAL_POSE_CONTROLLER_STACK.push(FeatureStatus.DISABLED);\n\t}\n\n\tpublic static void forceEnableForceTranslucentAcceleration() {\n\t\tFORCE_TRANSLUCENT_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.ENABLED);\n\t}\n\n\tpublic static void forceEnableCacheIdenticalPose() {\n\t\tCACHE_IDENTICAL_POSE_CONTROLLER_STACK.push(FeatureStatus.ENABLED);\n\t}\n\n\tpublic static void forceSetForceTranslucentAcceleration(FeatureStatus status) {\n\t\tFORCE_TRANSLUCENT_ACCELERATION_CONTROLLER_STACK.push(status);\n\t}\n\n\tpublic static void forceSetCacheIdenticalPose(FeatureStatus status) {\n\t\tCACHE_IDENTICAL_POSE_CONTROLLER_STACK.push(status);\n\t}\n\n\tpublic static void forceSetDefaultLayer(int defaultLayer) {\n\t\tDEFAULT_LAYER_CONTROLLER_STACK.push(defaultLayer);\n\t}\n\n\tpublic static void forceSetDefaultLayerBeforeFunction(Runnable runnable) {\n\t\tDEFAULT_LAYER_BEFORE_FUNCTION_CONTROLLER_STACK.push(runnable);\n\t}\n\n\tpublic static void forceSetDefaultLayerAfterFunction(Runnable runnable) {\n\t\tDEFAULT_LAYER_AFTER_FUNCTION_CONTROLLER_STACK.push(runnable);\n\t}\n\n\tpublic static void resetForceTranslucentAcceleration() {\n\t\tFORCE_TRANSLUCENT_ACCELERATION_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static void resetCacheIdenticalPose() {\n\t\tCACHE_IDENTICAL_POSE_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static void resetDefaultLayer() {\n\t\tDEFAULT_LAYER_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static void resetDefaultLayerBeforeFunction() {\n\t\tDEFAULT_LAYER_BEFORE_FUNCTION_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static void resetDefaultLayerAfterFunction() {\n\t\tDEFAULT_LAYER_AFTER_FUNCTION_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static FeatureStatus getForceTranslucentAccelerationSetting() {\n\t\treturn FORCE_TRANSLUCENT_ACCELERATION_CONTROLLER_STACK.isEmpty() ? getDefaultForceTranslucentAccelerationSetting() : FORCE_TRANSLUCENT_ACCELERATION_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static FeatureStatus getCacheIdenticalPoseSetting() {\n\t\treturn CACHE_IDENTICAL_POSE_CONTROLLER_STACK.isEmpty() ? getDefaultCacheIdenticalPoseSetting() : CACHE_IDENTICAL_POSE_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static int getDefaultLayer() {\n\t\treturn DEFAULT_LAYER_CONTROLLER_STACK.isEmpty() ? 0 : DEFAULT_LAYER_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static Runnable getDefaultLayerBeforeFunction() {\n\t\treturn DEFAULT_LAYER_BEFORE_FUNCTION_CONTROLLER_STACK.isEmpty() ? Runnables.doNothing() : DEFAULT_LAYER_BEFORE_FUNCTION_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static Runnable getDefaultLayerAfterFunction() {\n\t\treturn DEFAULT_LAYER_AFTER_FUNCTION_CONTROLLER_STACK.isEmpty() ? Runnables.doNothing() : DEFAULT_LAYER_AFTER_FUNCTION_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static FeatureStatus getDefaultForceTranslucentAccelerationSetting() {\n\t\treturn FeatureConfig.CONFIG.coreForceTranslucentAcceleration.get();\n\t}\n\n\tpublic static FeatureStatus getDefaultCacheIdenticalPoseSetting() {\n\t\treturn FeatureConfig.CONFIG.coreCacheIdenticalPose.get();\n\t}\n\n\tpublic static void setRenderingLevel() {\n\t\tRENDERING_LEVEL = true;\n\t}\n\n\tpublic static void resetRenderingLevel() {\n\t\tRENDERING_LEVEL = false;\n\t}\n\n\tpublic static void setRenderingHand() {\n\t\tRENDERING_HAND = true;\n\t}\n\n\tpublic static void resetRenderingHand() {\n\t\tRENDERING_HAND = false;\n\t}\n\n\tpublic static void setRenderingGui() {\n\t\tRENDERING_GUI = true;\n\t}\n\n\tpublic static void resetRenderingGui() {\n\t\tRENDERING_GUI = false;\n\t}\n\n\tpublic static boolean isRenderingLevel() {\n\t\treturn RENDERING_LEVEL;\n\t}\n\n\tpublic static boolean isRenderingHand() {\n\t\treturn RENDERING_HAND;\n\t}\n\n\tpublic static boolean isRenderingGui() {\n\t\treturn RENDERING_GUI;\n\t}\n\n\tpublic static void setGuiBatching() {\n\t\tGUI_BATCHING = true;\n\t}\n\n\tpublic static void resetGuiBatching() {\n\t\tGUI_BATCHING = false;\n\t}\n\n\tpublic static boolean isGuiBatching() {\n\t\treturn GUI_BATCHING;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/CoreStates.java",
    "content": "package com.github.argon4w.acceleratedrendering.core;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState;\n\npublic class CoreStates {\n\n\tpublic static final IBindingState SHADER_STORAGE_BUFFER_STATE = CoreFeature.createShaderStorageState();\n\tpublic static final IBindingState ATOMIC_COUNTER_BUFFER_STATE = CoreFeature.createAtomicCounterState();\n\n\tpublic static void recordBuffers() {\n\t\tif (CoreFeature.shouldRestoreBlockBuffers()) {\n\t\t\tSHADER_STORAGE_BUFFER_STATE.record(null);\n\t\t\tATOMIC_COUNTER_BUFFER_STATE.record(null);\n\t\t}\n\t}\n\n\tpublic static void restoreBuffers() {\n\t\tif (CoreFeature.shouldRestoreBlockBuffers()) {\n\t\t\tSHADER_STORAGE_BUFFER_STATE.restore();\n\t\t\tATOMIC_COUNTER_BUFFER_STATE.restore();\n\t\t}\n\t}\n\n\tpublic static void delete() {\n\t\tSHADER_STORAGE_BUFFER_STATE.delete();\n\t\tATOMIC_COUNTER_BUFFER_STATE.delete();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/DebugOutput.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends;\n\nimport static org.lwjgl.opengl.GL46.GL_DEBUG_OUTPUT_SYNCHRONOUS;\nimport static org.lwjgl.opengl.GL46.glEnable;\n\npublic class DebugOutput {\n\n\tpublic static void enable() {\n\t\tglEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/GLConstants.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends;\n\nimport static org.lwjgl.opengl.GL46.*;\n\npublic class GLConstants {\n\n\tpublic static final int MAX_SHADER_STORAGE_BLOCK_SIZE\t= glGetInteger\t(GL_MAX_SHADER_STORAGE_BLOCK_SIZE);\n\tpublic static final int MAX_COMPUTE_WORK_GROUP_COUNT_X\t= glGetIntegeri\t(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0);\n\tpublic static final int MAX_COMPUTE_WORK_GROUP_COUNT_Y\t= glGetIntegeri\t(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1);\n\tpublic static final int MAX_COMPUTE_WORK_GROUP_COUNT_Z\t= glGetIntegeri\t(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2);\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/Sync.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends;\n\nimport static org.lwjgl.opengl.GL46.*;\n\npublic class Sync {\n\n\tprivate long syncHandle;\n\n\tpublic Sync() {\n\t\tthis.syncHandle = -1;\n\t}\n\n\tpublic boolean isSyncSet() {\n\t\treturn syncHandle != -1;\n\t}\n\n\tpublic boolean isSyncSignaled() {\n\t\treturn glGetSynci(syncHandle, GL_SYNC_STATUS, null) == GL_SIGNALED;\n\t}\n\n\tpublic void waitSync() {\n\t\tglClientWaitSync(syncHandle, GL_SYNC_FLUSH_COMMANDS_BIT, Long.MAX_VALUE);\n\t}\n\n\tpublic void setSync() {\n\t\tsyncHandle = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);\n\t}\n\n\tpublic void deleteSync() {\n\t\tglDeleteSync(syncHandle);\n\t}\n\n\tpublic void resetSync() {\n\t\tsyncHandle = -1;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/VertexArray.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends;\n\nimport static org.lwjgl.opengl.GL46.*;\n\npublic class VertexArray {\n\n\tprivate final int vaoHandle;\n\n\tpublic VertexArray() {\n\t\tthis.vaoHandle = glCreateVertexArrays();\n\t}\n\n\tpublic void bind() {\n\t\tglBindVertexArray(vaoHandle);\n\t}\n\n\tpublic void unbind() {\n\t\tglBindVertexArray(0);\n\t}\n\n\tpublic void delete() {\n\t\tglDeleteVertexArrays(vaoHandle);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/buffers/EmptyServerBuffer.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.buffers;\n\nimport java.nio.ByteBuffer;\n\npublic class EmptyServerBuffer implements IServerBuffer {\n\n\tpublic static final EmptyServerBuffer INSTANCE = new EmptyServerBuffer();\n\n\t@Override\n\tpublic int getBufferHandle() {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic void delete() {\n\n\t}\n\n\t@Override\n\tpublic void bind(int target) {\n\n\t}\n\n\t@Override\n\tpublic void data(ByteBuffer data) {\n\n\t}\n\n\t@Override\n\tpublic void bindBase(int target, int index) {\n\n\t}\n\n\t@Override\n\tpublic void bindRange(\n\t\t\tint\t\ttarget,\n\t\t\tint\t\tindex,\n\t\t\tlong\toffset,\n\t\t\tlong\tsize\n\t) {\n\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/buffers/IClientBuffer.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.buffers;\n\npublic interface IClientBuffer {\n\n\tlong reserve\t(long bytes);\n\tlong reserve\t(long bytes, boolean occupied);\n\tlong addressAt\t(long position);\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/buffers/IServerBuffer.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.buffers;\n\nimport java.nio.ByteBuffer;\n\npublic interface IServerBuffer {\n\n\tint getBufferHandle ();\n\tvoid delete\t\t\t();\n\tvoid data\t\t\t(ByteBuffer\tdata);\n\tvoid bind           (int\t\ttarget);\n\tvoid bindBase       (int\t\ttarget, int index);\n\tvoid bindRange      (int\t\ttarget, int index, long offset, long size);\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/buffers/ImmutableBuffer.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.buffers;\n\nimport java.nio.ByteBuffer;\n\nimport static org.lwjgl.opengl.GL46.*;\n\npublic class ImmutableBuffer implements IServerBuffer {\n\n\tprotected final int bufferHandle;\n\n\tpublic ImmutableBuffer(long size, int bits) {\n\t\tthis.bufferHandle = glCreateBuffers();\n\n\t\tglNamedBufferStorage(\n\t\t\t\tthis.bufferHandle,\n\t\t\t\tsize,\n\t\t\t\tbits\n\t\t);\n\t}\n\n\tpublic void copyTo(IServerBuffer buffer, long size) {\n\t\tglCopyNamedBufferSubData(\n\t\t\t\tbufferHandle,\n\t\t\t\tbuffer.getBufferHandle(),\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tsize\n\t\t);\n\t}\n\n\tpublic long map(long length, int bits) {\n\t\treturn nglMapNamedBufferRange(\n\t\t\t\tbufferHandle,\n\t\t\t\t0L,\n\t\t\t\tlength,\n\t\t\t\tbits\n\t\t);\n\t}\n\n\tpublic void unmap() {\n\t\tglUnmapNamedBuffer(bufferHandle);\n\t}\n\n\t@Override\n\tpublic int getBufferHandle() {\n\t\treturn bufferHandle;\n\t}\n\n\t@Override\n\tpublic void delete() {\n\t\tglDeleteBuffers(bufferHandle);\n\t}\n\n\t@Override\n\tpublic void bind(int target) {\n\t\tglBindBuffer(target, bufferHandle);\n\t}\n\n\t@Override\n\tpublic void data(ByteBuffer data) {\n\t\tglNamedBufferSubData(\n\t\t\t\tbufferHandle,\n\t\t\t\t0,\n\t\t\t\tdata\n\t\t);\n\t}\n\n\t@Override\n\tpublic void bindBase(int target, int index) {\n\t\tglBindBufferBase(\n\t\t\t\ttarget,\n\t\t\t\tindex,\n\t\t\t\tbufferHandle\n\t\t);\n\t}\n\n\t@Override\n\tpublic void bindRange(\n\t\t\tint\t\ttarget,\n\t\t\tint\t\tindex,\n\t\t\tlong\toffset,\n\t\t\tlong\tsize\n\t) {\n\t\tglBindBufferRange(\n\t\t\t\ttarget,\n\t\t\t\tindex,\n\t\t\t\tbufferHandle,\n\t\t\t\toffset,\n\t\t\t\tsize\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/buffers/MappedBuffer.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.buffers;\n\nimport lombok.Getter;\n\nimport static org.lwjgl.opengl.GL46.*;\n\n@Getter\npublic class MappedBuffer extends MutableBuffer implements IClientBuffer {\n\n\tprotected long address;\n\tprotected long position;\n\tprotected long current;\n\n\tpublic MappedBuffer(long initialSize) {\n\t\tsuper(initialSize,\tGL_MAP_PERSISTENT_BIT\n\t\t\t\t| \t\t\tGL_MAP_WRITE_BIT\n\t\t\t\t|\t\t\tGL_MAP_COHERENT_BIT\n\t\t);\n\n\t\tthis.address\t= map();\n\t\tthis.position\t= 0L;\n\t\tthis.current\t= 0L;\n\t}\n\n\t@Override\n\tpublic long reserve(long bytes, boolean occupied) {\n\t\tif (bytes <= 0) {\n\t\t\treturn address + position;\n\t\t}\n\n\t\tvar oldPosition = this.position;\n\t\tvar newPosition = oldPosition + bytes;\n\n\t\tif (occupied) {\n\t\t\tthis.current\t= oldPosition;\n\t\t\tthis.position\t= newPosition;\n\t\t}\n\n\t\tif (newPosition <= size) {\n\t\t\treturn address + oldPosition;\n\t\t}\n\n\t\tresize(newPosition);\n\t\treturn address + oldPosition;\n\t}\n\n\t@Override\n\tpublic long reserve(long bytes) {\n\t\treturn reserve(bytes, true);\n\t}\n\n\t@Override\n\tpublic long addressAt(long position) {\n\t\treturn address + position;\n\t}\n\n\t@Override\n\tpublic void beforeExpand() {\n\t\tunmap();\n\t}\n\n\t@Override\n\tpublic void afterExpand() {\n\t\taddress = map();\n\t}\n\n\tpublic void reset() {\n\t\tposition = 0;\n\t}\n\n\tpublic long getCurrent() {\n\t\treturn address + current;\n\t}\n\n\tpublic long map() {\n\t\treturn map(\tGL_MAP_WRITE_BIT\n\t\t\t\t|\tGL_MAP_PERSISTENT_BIT\n\t\t\t\t|\tGL_MAP_COHERENT_BIT\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/buffers/MutableBuffer.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.buffers;\n\nimport com.github.argon4w.acceleratedrendering.core.utils.MutableSize;\n\nimport java.nio.ByteBuffer;\n\npublic class MutableBuffer extends MutableSize implements IServerBuffer {\n\n\tprivate final\tint\t\t\t\tbits;\n\n\tprotected\t\tImmutableBuffer glBuffer;\n\n\tpublic MutableBuffer(long initialSize, int bits) {\n\t\tsuper(initialSize);\n\n\t\tthis.bits\t\t= bits;\n\t\tthis.glBuffer\t= new ImmutableBuffer(this.size, bits);\n\t}\n\n\t@Override\n\tpublic void doExpand(long size, long bytes) {\n\t\tvar newSize\t\t= size + bytes;\n\t\tvar newBuffer\t= new ImmutableBuffer(newSize, bits);\n\n\t\tglBuffer.copyTo(newBuffer, size);\n\t\tglBuffer.delete();\n\t\tglBuffer = newBuffer;\n\t}\n\n\tpublic long map(int flags) {\n\t\treturn glBuffer.map(size, flags);\n\t}\n\n\tpublic void unmap() {\n\t\tglBuffer.unmap();\n\t}\n\n\tpublic void copyTo(IServerBuffer buffer) {\n\t\tglBuffer.copyTo(buffer, size);\n\t}\n\n\t@Override\n\tpublic int getBufferHandle() {\n\t\treturn glBuffer.getBufferHandle();\n\t}\n\n\t@Override\n\tpublic void delete() {\n\t\tglBuffer.delete();\n\t}\n\n\t@Override\n\tpublic void bind(int target) {\n\t\tglBuffer.bind(target);\n\t}\n\n\t@Override\n\tpublic void data(ByteBuffer data) {\n\t\tglBuffer.data(data);\n\t}\n\n\t@Override\n\tpublic void bindBase(int target, int index) {\n\t\tglBuffer.bindBase(target, index);\n\t}\n\n\t@Override\n\tpublic void bindRange(\n\t\t\tint\t\ttarget,\n\t\t\tint\t\tindex,\n\t\t\tlong\toffset,\n\t\t\tlong\tsize\n\t) {\n\t\tglBuffer.bindRange(\n\t\t\t\ttarget,\n\t\t\t\tindex,\n\t\t\t\toffset,\n\t\t\t\tsize\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/programs/BarrierFlags.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.programs;\n\nimport static org.lwjgl.opengl.GL46.*;\n\npublic enum BarrierFlags {\n\n\tSHADER_STORAGE\t(GL_SHADER_STORAGE_BARRIER_BIT),\n\tATOMIC_COUNTER\t(GL_ATOMIC_COUNTER_BARRIER_BIT),\n\tELEMENT_ARRAY\t(GL_ELEMENT_ARRAY_BARRIER_BIT),\n\tCOMMAND\t\t\t(GL_COMMAND_BARRIER_BIT);\n\n\tprivate final int flag;\n\n\tBarrierFlags(int flag) {\n\t\tthis.flag = flag;\n\t}\n\n\tpublic static int getFlags(BarrierFlags... barrierFlags) {\n\t\tint intFlags = 0;\n\n\t\tfor (BarrierFlags barrierFlag : barrierFlags) {\n\t\t\tintFlags = intFlags | barrierFlag.flag;\n\t\t}\n\n\t\treturn intFlags;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/programs/ComputeProgram.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.programs;\n\nimport lombok.Getter;\n\nimport static org.lwjgl.opengl.GL46.*;\n\n@Getter\npublic class ComputeProgram {\n\n\tprivate final int programHandle;\n\tprivate final int barrierFlags;\n\n\tpublic ComputeProgram(int barrierFlags) {\n\t\tthis.programHandle\t= glCreateProgram();\n\t\tthis.barrierFlags\t= barrierFlags;\n\t}\n\n\tpublic void dispatch(\n\t\t\tint countX,\n\t\t\tint countY,\n\t\t\tint countZ\n\t) {\n\t\tglDispatchCompute(\n\t\t\t\tcountX,\n\t\t\t\tcountY,\n\t\t\t\tcountZ\n\t\t);\n\t}\n\n\tpublic void setup() {\n\n\t}\n\n\tpublic void linkProgram() {\n\t\tglLinkProgram(programHandle);\n\t}\n\n\tpublic boolean isLinked() {\n\t\treturn glGetProgrami(programHandle, GL_LINK_STATUS) == GL_TRUE;\n\t}\n\n\tpublic void useProgram() {\n\t\tglUseProgram(programHandle);\n\t}\n\n\tpublic void resetProgram() {\n\t\tglUseProgram(0);\n\t}\n\n\tpublic void attachShader(ComputeShader computeShader) {\n\t\tglAttachShader(programHandle, computeShader.getShaderHandle());\n\t}\n\n\tpublic void waitBarriers() {\n\t\tglMemoryBarrier(barrierFlags);\n\t}\n\n\tpublic int getUniformLocation(String name) {\n\t\treturn glGetUniformLocation(programHandle, name);\n\t}\n\n\tpublic Uniform getUniform(String name) {\n\t\treturn new Uniform(programHandle, getUniformLocation(name));\n\t}\n\n\tpublic String getInfoLog() {\n\t\treturn glGetProgramInfoLog(programHandle);\n\t}\n\n\tpublic void delete() {\n\t\tglDeleteProgram(programHandle);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/programs/ComputeShader.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.programs;\n\nimport lombok.Getter;\n\nimport static org.lwjgl.opengl.GL46.*;\n\n@Getter\npublic class ComputeShader {\n\n\tprivate final int shaderHandle;\n\n\tpublic ComputeShader() {\n\t\tthis.shaderHandle = glCreateShader(GL_COMPUTE_SHADER);\n\t}\n\n\tpublic void setShaderSource(String source) {\n\t\tglShaderSource(shaderHandle, source);\n\t}\n\n\tpublic void compileShader() {\n\t\tglCompileShader(shaderHandle);\n\t}\n\n\tpublic boolean isCompiled() {\n\t\treturn glGetShaderi(shaderHandle, GL_COMPILE_STATUS) == GL_TRUE;\n\t}\n\n\tpublic String getInfoLog() {\n\t\treturn glGetShaderInfoLog(shaderHandle);\n\t}\n\n\tpublic void delete() {\n\t\tglDeleteShader(shaderHandle);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/programs/Uniform.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.programs;\n\nimport org.joml.Matrix4f;\nimport org.lwjgl.system.MemoryStack;\n\nimport static org.lwjgl.opengl.GL41.glProgramUniform1ui;\nimport static org.lwjgl.opengl.GL46.glProgramUniformMatrix4fv;\n\npublic class Uniform {\n\n\tprivate final int programHandle;\n\tprivate final int uniformLocation;\n\n\tpublic Uniform(int programHandle, int uniformLocation) {\n\t\tthis.programHandle\t\t= programHandle;\n\t\tthis.uniformLocation\t= uniformLocation;\n\t}\n\n\tpublic void uploadMatrix4f(Matrix4f matrix) {\n\t\ttry (MemoryStack stack = MemoryStack.stackPush()) {\n\t\t\tglProgramUniformMatrix4fv(\n\t\t\t\t\tprogramHandle,\n\t\t\t\t\tuniformLocation,\n\t\t\t\t\tfalse,\n\t\t\t\t\tmatrix.get(stack.callocFloat(16))\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic void uploadUnsignedInt(int value) {\n\t\tglProgramUniform1ui(\n\t\t\t\tprogramHandle,\n\t\t\t\tuniformLocation,\n\t\t\t\tvalue\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/EmptyBindingState.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.states;\n\nimport net.minecraft.client.gui.GuiGraphics;\n\npublic class EmptyBindingState implements IBindingState {\n\n\tpublic static final IBindingState INSTANCE = new EmptyBindingState();\n\n\t@Override\n\tpublic void record(GuiGraphics graphics) {\n\n\t}\n\n\t@Override\n\tpublic void restore() {\n\n\t}\n\n\t@Override\n\tpublic void delete() {\n\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/FramebufferBindingState.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.states;\n\nimport net.minecraft.client.gui.GuiGraphics;\n\nimport static org.lwjgl.opengl.GL46.*;\n\npublic class FramebufferBindingState implements IBindingState {\n\n\tprivate int bindingFramebuffer;\n\tprivate int bindingReadFramebuffer;\n\tprivate int bindingDrawFramebuffer;\n\n\tpublic FramebufferBindingState() {\n\t\tthis.bindingFramebuffer\t\t= 0;\n\t\tthis.bindingReadFramebuffer\t= 0;\n\t\tthis.bindingDrawFramebuffer\t= 0;\n\t}\n\n\t@Override\n\tpublic void record(GuiGraphics graphics) {\n\t\tbindingFramebuffer = glGetInteger(GL_FRAMEBUFFER_BINDING);\n\n\t\tif (bindingFramebuffer == 0) {\n\t\t\tbindingReadFramebuffer = glGetInteger(GL_READ_FRAMEBUFFER_BINDING);\n\t\t\tbindingDrawFramebuffer = glGetInteger(GL_DRAW_FRAMEBUFFER_BINDING);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void restore() {\n\t\tif (bindingFramebuffer != 0) {\n\t\t\tglBindFramebuffer(GL_FRAMEBUFFER, bindingFramebuffer);\n\t\t} else {\n\t\t\tglBindFramebuffer(GL_READ_FRAMEBUFFER, bindingReadFramebuffer);\n\t\t\tglBindFramebuffer(GL_DRAW_FRAMEBUFFER, bindingDrawFramebuffer);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void delete() {\n\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/IBindingState.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.states;\n\nimport net.minecraft.client.gui.GuiGraphics;\n\npublic interface IBindingState {\n\n\tvoid record\t(GuiGraphics graphics);\n\tvoid restore();\n\tvoid delete\t();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/buffers/BlockBufferBindingStateType.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.states.buffers;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.states.EmptyBindingState;\nimport com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState;\nimport com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache.BlockBufferBindingCacheType;\n\npublic enum BlockBufferBindingStateType {\n\n\tIGNORED,\n\tRESTORED;\n\n\tpublic IBindingState create(\n\t\t\tBlockBufferBindingCacheType\tcacheType,\n\t\t\tBufferBlockType\t\t\t\tblockType,\n\t\t\tint\t\t\t\t\t\t\tbindingRange\n\t) {\n\t\treturn create(\n\t\t\t\tthis,\n\t\t\t\tcacheType,\n\t\t\t\tblockType,\n\t\t\t\tbindingRange\n\t\t);\n\t}\n\n\tpublic static IBindingState create(\n\t\t\tBlockBufferBindingStateType\t\tstateType,\n\t\t\tBlockBufferBindingCacheType\t\tcacheType,\n\t\t\tBufferBlockType\t\t\t\t\tblockType,\n\t\t\tint\t\t\t\t\t\t\t\tbindingRange\n\t) {\n\t\treturn switch (stateType) {\n\t\t\tcase IGNORED\t-> EmptyBindingState.INSTANCE;\n\t\t\tcase RESTORED\t-> new SimpleBlockBufferBindingState(\n\t\t\t\t\tcacheType,\n\t\t\t\t\tbindingRange,\n\t\t\t\t\tblockType.getBindingBlock\t(),\n\t\t\t\t\tblockType.getBufferParam\t(),\n\t\t\t\t\tblockType.getOffsetParam\t(),\n\t\t\t\t\tblockType.getSizeParam\t\t()\n\t\t\t);\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/buffers/BufferBlockType.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.states.buffers;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\n\nimport static org.lwjgl.opengl.GL46.*;\n\n@Getter\n@AllArgsConstructor\npublic enum BufferBlockType {\n\n\tSHADER_STORAGE(\n\t\t\tGL_SHADER_STORAGE_BUFFER,\n\t\t\tGL_SHADER_STORAGE_BUFFER_BINDING,\n\t\t\tGL_SHADER_STORAGE_BUFFER_START,\n\t\t\tGL_SHADER_STORAGE_BUFFER_SIZE\n\t),\n\n\tATOMIC_COUNTER(\n\t\t\tGL_ATOMIC_COUNTER_BUFFER,\n\t\t\tGL_ATOMIC_COUNTER_BUFFER_BINDING,\n\t\t\tGL_ATOMIC_COUNTER_BUFFER_START,\n\t\t\tGL_ATOMIC_COUNTER_BUFFER_SIZE\n\t);\n\n\tprivate final int bindingBlock;\n\tprivate final int bufferParam;\n\tprivate final int offsetParam;\n\tprivate final int sizeParam;\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/buffers/SimpleBlockBufferBindingState.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.states.buffers;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState;\nimport com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache.BlockBufferBindingCacheType;\nimport com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache.IBlockBufferBindingCache;\nimport net.minecraft.client.gui.GuiGraphics;\n\nimport static org.lwjgl.opengl.GL46.*;\n\npublic class SimpleBlockBufferBindingState implements IBindingState {\n\n\tprivate final IBlockBufferBindingCache\tbindingCache;\n\tprivate final int\t\t\t\t\t\tbindingRange;\n\tprivate final int\t\t\t\t\t\tbindingBlock;\n\tprivate final int\t\t\t\t\t\tbufferParam;\n\tprivate final int\t\t\t\t\t\toffsetParam;\n\tprivate final int\t\t\t\t\t\tsizeParam;\n\n\tpublic SimpleBlockBufferBindingState(\n\t\t\tBlockBufferBindingCacheType\ttype,\n\t\t\tint\t\t\t\t\t\t\tbindingRange,\n\t\t\tint\t\t\t\t\t\t\tbindingBlock,\n\t\t\tint\t\t\t\t\t\t\tbufferParam,\n\t\t\tint\t\t\t\t\t\t\toffsetParam,\n\t\t\tint\t\t\t\t\t\t\tsizeParam\n\t) {\n\t\tthis.bindingRange\t= bindingRange;\n\t\tthis.bindingCache\t= type.create(this.bindingRange);\n\n\t\tthis.bindingBlock\t= bindingBlock;\n\t\tthis.bufferParam\t= bufferParam;\n\t\tthis.offsetParam\t= offsetParam;\n\t\tthis.sizeParam\t\t= sizeParam;\n\t}\n\n\t@Override\n\tpublic void record(GuiGraphics graphics) {\n\t\tfor (var bindingPoint = 0; bindingPoint < bindingRange; bindingPoint++) {\n\t\t\tbindingCache.setup(\n\t\t\t\t\tbindingPoint,\n\t\t\t\t\tglGetIntegeri(bufferParam,\tbindingPoint),\n\t\t\t\t\tglGetIntegeri(offsetParam,\tbindingPoint),\n\t\t\t\t\tglGetIntegeri(sizeParam,\tbindingPoint)\n\t\t\t);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void restore() {\n\t\tfor (var bindingPoint = 0; bindingPoint < bindingRange; bindingPoint ++) {\n\t\t\tvar buffer\t= bindingCache.getBuffer(bindingPoint);\n\t\t\tvar offset\t= bindingCache.getOffset(bindingPoint);\n\t\t\tvar size\t= bindingCache.getSize\t(bindingPoint);\n\n\t\t\tif (\t\toffset\t== 0\n\t\t\t\t\t&&\tsize\t== 0\n\t\t\t) {\n\t\t\t\tglBindBufferBase(\n\t\t\t\t\t\tbindingBlock,\n\t\t\t\t\t\tbindingPoint,\n\t\t\t\t\t\tbuffer\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tglBindBufferRange(\n\t\t\t\t\t\tbindingBlock,\n\t\t\t\t\t\tbindingPoint,\n\t\t\t\t\t\tbuffer,\n\t\t\t\t\t\toffset,\n\t\t\t\t\t\tsize\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void delete() {\n\t\tbindingCache.delete();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/buffers/cache/BlockBufferBindingCacheType.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache;\n\npublic enum BlockBufferBindingCacheType {\n\n\tSIMPLE,\n\tUNSAFE,\n\tHANDLE;\n\n\tpublic IBlockBufferBindingCache create(int size) {\n\t\treturn create(this, size);\n\t}\n\n\tpublic static IBlockBufferBindingCache create(BlockBufferBindingCacheType type, int size) {\n\t\treturn switch (type) {\n\t\t\tcase SIMPLE -> new SimpleBlockBufferBindingCache\t\t(size);\n\t\t\tcase HANDLE -> new FlattenBlockBufferBindingCache\t\t(size);\n\t\t\tcase UNSAFE -> new UnsafeMemoryBlockBufferBindingCache\t(size);\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/buffers/cache/FlattenBlockBufferBindingCache.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache;\n\nimport java.lang.invoke.MethodHandles;\nimport java.lang.invoke.VarHandle;\n\npublic class FlattenBlockBufferBindingCache implements IBlockBufferBindingCache {\n\n\tpublic static\tfinal VarHandle\tHANDLE\t\t\t\t\t\t= MethodHandles.arrayElementVarHandle(long[].class).withInvokeExactBehavior();\n\tpublic static\tfinal int\t\tBLOCK_BUFFER_BINDING_SIZE\t= 3;\n\tpublic static\tfinal int\t\tBUFFER_OFFSET\t\t\t\t= 0;\n\tpublic static\tfinal int\t\tOFFSET_OFFSET\t\t\t\t= 1;\n\tpublic static\tfinal int\t\tSIZE_OFFSET\t\t\t\t\t= 2;\n\n\tprivate\t\t\tfinal long[]\tcache;\n\n\tpublic FlattenBlockBufferBindingCache(int size) {\n\t\tthis.cache = new long[size * BLOCK_BUFFER_BINDING_SIZE];\n\t}\n\n\t@Override\n\tpublic void delete() {\n\n\t}\n\n\t@Override\n\tpublic void setup(\n\t\t\tint\t\tbindingPoint,\n\t\t\tint\t\tbuffer,\n\t\t\tlong\toffset,\n\t\t\tlong\tsize\n\t) {\n\t\tvar bindingIndex = bindingPoint * BLOCK_BUFFER_BINDING_SIZE;\n\n\t\tHANDLE.set(cache, bindingIndex + BUFFER_OFFSET,\t(long)\tbuffer);\n\t\tHANDLE.set(cache, bindingIndex + OFFSET_OFFSET,\t\t\toffset);\n\t\tHANDLE.set(cache, bindingIndex + SIZE_OFFSET,\t\t\tsize);\n\t}\n\n\t@Override\n\tpublic int getBuffer(int bindingPoint) {\n\t\treturn (int) (long) HANDLE.get(cache, bindingPoint * BLOCK_BUFFER_BINDING_SIZE + BUFFER_OFFSET);\n\t}\n\n\t@Override\n\tpublic long getOffset(int bindingPoint) {\n\t\treturn (long) HANDLE.get(cache, bindingPoint * BLOCK_BUFFER_BINDING_SIZE + OFFSET_OFFSET);\n\t}\n\n\t@Override\n\tpublic long getSize(int bindingPoint) {\n\t\treturn (long) HANDLE.get(cache, bindingPoint * BLOCK_BUFFER_BINDING_SIZE + SIZE_OFFSET);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/buffers/cache/IBlockBufferBindingCache.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache;\n\npublic interface IBlockBufferBindingCache {\n\n\tvoid\tdelete\t\t();\n\tvoid\tsetup\t\t(int bindingPoint, int buffer, long offset, long size);\n\tint\t\tgetBuffer\t(int bindingPoint);\n\tlong\tgetOffset\t(int bindingPoint);\n\tlong\tgetSize\t\t(int bindingPoint);\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/buffers/cache/SimpleBlockBufferBinding.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache;\n\nimport lombok.Getter;\n\n@Getter\npublic class SimpleBlockBufferBinding {\n\n\tprivate int\t\tbuffer;\n\tprivate long\toffset;\n\tprivate long\tsize;\n\n\tpublic SimpleBlockBufferBinding() {\n\t\tthis.buffer\t= -1;\n\t\tthis.offset\t= -1;\n\t\tthis.size\t= -1;\n\t}\n\n\tpublic void setupBlockBufferBinding(\n\t\t\tint\t\tbuffer,\n\t\t\tlong\toffset,\n\t\t\tlong\tsize\n\t) {\n\t\tthis.buffer\t= buffer;\n\t\tthis.offset\t= offset;\n\t\tthis.size\t= size;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/buffers/cache/SimpleBlockBufferBindingCache.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache;\n\npublic class SimpleBlockBufferBindingCache implements IBlockBufferBindingCache {\n\n\tprivate final SimpleBlockBufferBinding[] cache;\n\n\tpublic SimpleBlockBufferBindingCache(int size) {\n\t\tcache = new SimpleBlockBufferBinding[size];\n\n\t\tfor (int i = 0; i < cache.length; i++) {\n\t\t\tcache[i] = new SimpleBlockBufferBinding();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void delete() {\n\n\t}\n\n\t@Override\n\tpublic void setup(\n\t\t\tint bindingPoint,\n\t\t\tint buffer,\n\t\t\tlong offset,\n\t\t\tlong size\n\t) {\n\t\tcache[bindingPoint].setupBlockBufferBinding(\n\t\t\t\tbuffer,\n\t\t\t\toffset,\n\t\t\t\tsize\n\t\t);\n\t}\n\n\t@Override\n\tpublic int getBuffer(int bindingPoint) {\n\t\treturn cache[bindingPoint].getBuffer();\n\t}\n\n\t@Override\n\tpublic long getOffset(int bindingPoint) {\n\t\treturn cache[bindingPoint].getOffset();\n\t}\n\n\t@Override\n\tpublic long getSize(int bindingPoint) {\n\t\treturn cache[bindingPoint].getSize();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/buffers/cache/UnsafeMemoryBlockBufferBindingCache.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache;\n\nimport io.netty.util.internal.shaded.org.jctools.util.UnsafeAccess;\nimport sun.misc.Unsafe;\n\npublic class UnsafeMemoryBlockBufferBindingCache implements IBlockBufferBindingCache {\n\n\tpublic static\tfinal Unsafe\tUNSAFE\t\t\t\t\t\t\t= UnsafeAccess.UNSAFE;\n\tpublic static\tfinal long\t\tBLOCK_BUFFER_BINDING_SIZE\t\t= 3L * 8L;\n\tpublic static\tfinal long\t\tBUFFER_OFFSET\t\t\t\t\t= 0L * 8L;\n\tpublic static\tfinal long\t\tOFFSET_OFFSET\t\t\t\t\t= 1L * 8L;\n\tpublic static\tfinal long\t\tSIZE_OFFSET\t\t\t\t\t\t= 2L * 8L;\n\n\tprivate\t\t\tfinal long\t\taddress;\n\n\tpublic UnsafeMemoryBlockBufferBindingCache(int size) {\n\t\tthis.address = UNSAFE.allocateMemory(size * BLOCK_BUFFER_BINDING_SIZE);\n\t}\n\n\t@Override\n\tpublic void delete() {\n\t\tUNSAFE.freeMemory(address);\n\t}\n\n\t@Override\n\tpublic void setup(\n\t\t\tint\t\tbindingPoint,\n\t\t\tint\t\tbuffer,\n\t\t\tlong\toffset,\n\t\t\tlong\tsize\n\t) {\n\t\tvar bindingAddress = address + bindingPoint * BLOCK_BUFFER_BINDING_SIZE;\n\n\t\tUNSAFE.putInt\t(bindingAddress + BUFFER_OFFSET,\tbuffer);\n\t\tUNSAFE.putLong\t(bindingAddress + OFFSET_OFFSET,\toffset);\n\t\tUNSAFE.putLong\t(bindingAddress + SIZE_OFFSET,\t\tsize);\n\t}\n\n\t@Override\n\tpublic int getBuffer(int bindingPoint) {\n\t\treturn UNSAFE.getInt(address + bindingPoint * BLOCK_BUFFER_BINDING_SIZE + BUFFER_OFFSET);\n\t}\n\n\t@Override\n\tpublic long getOffset(int bindingPoint) {\n\t\treturn UNSAFE.getLong(address + bindingPoint * BLOCK_BUFFER_BINDING_SIZE + OFFSET_OFFSET);\n\t}\n\n\t@Override\n\tpublic long getSize(int bindingPoint) {\n\t\treturn UNSAFE.getLong(address + bindingPoint * BLOCK_BUFFER_BINDING_SIZE + SIZE_OFFSET);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/scissors/MojangScissorBindingState.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.states.scissors;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiGraphics;\n\nimport static org.lwjgl.opengl.GL46.*;\n\npublic class MojangScissorBindingState implements IBindingState {\n\n\tprivate boolean recorded;\n\tprivate boolean\tenabled;\n\tprivate int\t\tscissorX;\n\tprivate int\t\tscissorY;\n\tprivate int\t\tscissorWidth;\n\tprivate int\t\tscissorHeight;\n\n\tpublic MojangScissorBindingState() {\n\t\tthis.enabled\t\t= false;\n\t\tthis.scissorX\t\t= 0;\n\t\tthis.scissorY\t\t= 0;\n\t\tthis.scissorWidth\t= 0;\n\t\tthis.scissorHeight\t= 0;\n\t}\n\n\t@Override\n\tpublic void record(GuiGraphics graphics) {\n\t\tvar rect = graphics.scissorStack.stack.peekLast();\n\n\t\tif (rect != null) {\n\t\t\tvar window\t= Minecraft.getInstance()\t.getWindow\t();\n\t\t\tvar height\t= window\t\t\t\t\t.getHeight\t();\n\t\t\tvar scale\t= window\t\t\t\t\t.getGuiScale();\n\n\t\t\tscissorY\t\t= (int) (height - rect.bottom()\t* scale);\n\t\t\tscissorX\t\t= (int) (rect.left\t()\t\t\t* scale);\n\t\t\tscissorWidth\t= (int) (rect.width\t()\t\t\t* scale);\n\t\t\tscissorHeight\t= (int) (rect.height()\t\t\t* scale);\n\t\t\tenabled\t\t\t= true;\n\t\t} else {\n\t\t\tenabled = false;\n\t\t}\n\n\t\trecorded = true;\n\t}\n\n\t@Override\n\tpublic void restore() {\n\t\tif (!recorded) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (enabled) {\n\t\t\tglEnable\t(GL_SCISSOR_TEST);\n\t\t\tglScissor\t(\n\t\t\t\t\tscissorX,\n\t\t\t\t\tscissorY,\n\t\t\t\t\tscissorWidth,\n\t\t\t\t\tscissorHeight\n\t\t\t);\n\t\t} else {\n\t\t\tglDisable(GL_SCISSOR_TEST);\n\t\t}\n\n\t\trecorded = false;\n\t}\n\n\t@Override\n\tpublic void delete() {\n\t\tenabled\t\t= false;\n\t\trecorded\t= false;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/scissors/OpenGLScissorBindingState.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.states.scissors;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState;\nimport net.minecraft.client.gui.GuiGraphics;\nimport org.lwjgl.system.MemoryUtil;\n\nimport java.nio.IntBuffer;\n\nimport static org.lwjgl.opengl.GL46.*;\n\npublic class OpenGLScissorBindingState implements IBindingState {\n\n\tprivate final\tIntBuffer\tbindingScissor;\n\n\tprivate\t\t\tboolean\t\tenabled;\n\tprivate\t\t\tboolean\t\trecorded;\n\n\tpublic OpenGLScissorBindingState() {\n\t\tthis.bindingScissor\t= MemoryUtil.memAllocInt(4);\n\t\tthis.enabled\t\t= false;\n\t\tthis.recorded\t\t= false;\n\t}\n\n\t@Override\n\tpublic void record(GuiGraphics graphics) {\n\t\tglGetIntegerv\t\t\t\t(GL_SCISSOR_BOX, bindingScissor);\n\t\tenabled\t\t= glIsEnabled\t(GL_SCISSOR_TEST);\n\t\trecorded\t= true;\n\t}\n\n\t@Override\n\tpublic void restore() {\n\t\tif (!recorded) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (enabled) {\n\t\t\tglEnable\t(GL_SCISSOR_TEST);\n\t\t\tglScissor\t(\n\t\t\t\t\tbindingScissor.get(0),\n\t\t\t\t\tbindingScissor.get(1),\n\t\t\t\t\tbindingScissor.get(2),\n\t\t\t\t\tbindingScissor.get(3)\n\t\t\t);\n\t\t} else {\n\t\t\tglDisable(GL_SCISSOR_TEST);\n\t\t}\n\n\t\trecorded = false;\n\t}\n\n\t@Override\n\tpublic void delete() {\n\t\tMemoryUtil.memFree(bindingScissor);\n\t\trecorded = false;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/scissors/ScissorBindingStateType.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.states.scissors;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.states.EmptyBindingState;\nimport com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState;\n\npublic enum ScissorBindingStateType {\n\n\tIGNORED,\n\tMOJANG,\n\tOPENGL;\n\n\tpublic IBindingState create() {\n\t\treturn create(this);\n\t}\n\n\tpublic static IBindingState create(ScissorBindingStateType type) {\n\t\treturn switch (type) {\n\t\t\tcase IGNORED\t-> EmptyBindingState.INSTANCE;\n\t\t\tcase MOJANG\t\t-> new MojangScissorBindingState();\n\t\t\tcase OPENGL\t\t-> new OpenGLScissorBindingState();\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/viewports/MojangViewportBindingState.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.states.viewports;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState;\nimport com.mojang.blaze3d.platform.GlStateManager;\nimport net.minecraft.client.gui.GuiGraphics;\n\npublic class MojangViewportBindingState implements IBindingState {\n\n\tprivate int viewportX;\n\tprivate int viewportY;\n\tprivate int viewportWidth;\n\tprivate int viewportHeight;\n\n\tpublic MojangViewportBindingState() {\n\t\tthis.viewportX\t\t= 0;\n\t\tthis.viewportY\t\t= 0;\n\t\tthis.viewportWidth\t= 0;\n\t\tthis.viewportHeight\t= 0;\n\t}\n\n\t@Override\n\tpublic void record(GuiGraphics graphics) {\n\t\tviewportX\t\t= GlStateManager.Viewport.x\t\t();\n\t\tviewportY\t\t= GlStateManager.Viewport.y\t\t();\n\t\tviewportWidth\t= GlStateManager.Viewport.width\t();\n\t\tviewportHeight\t= GlStateManager.Viewport.height();\n\t}\n\n\t@Override\n\tpublic void restore() {\n\t\tif (\t\tviewportX\t\t!= GlStateManager.Viewport.x\t\t()\n\t\t\t\t||\tviewportY\t\t!= GlStateManager.Viewport.y\t\t()\n\t\t\t\t||\tviewportWidth\t!= GlStateManager.Viewport.width\t()\n\t\t\t\t||\tviewportHeight\t!= GlStateManager.Viewport.height\t()\n\t\t) {\n\t\t\tGlStateManager._viewport(\n\t\t\t\t\tviewportX,\n\t\t\t\t\tviewportY,\n\t\t\t\t\tviewportWidth,\n\t\t\t\t\tviewportHeight\n\t\t\t);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void delete() {\n\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/viewports/OpenGLViewportBindingState.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.states.viewports;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState;\nimport net.minecraft.client.gui.GuiGraphics;\nimport org.lwjgl.system.MemoryUtil;\n\nimport java.nio.IntBuffer;\n\nimport static org.lwjgl.opengl.GL46.*;\n\npublic class OpenGLViewportBindingState implements IBindingState {\n\n\tprivate final IntBuffer bindingViewport;\n\n\tpublic OpenGLViewportBindingState() {\n\t\tthis.bindingViewport = MemoryUtil.memAllocInt(4);\n\t}\n\n\t@Override\n\tpublic void record(GuiGraphics graphics) {\n\t\tglGetIntegerv(GL_VIEWPORT, bindingViewport);\n\t}\n\n\t@Override\n\tpublic void restore() {\n\t\tglViewport(\n\t\t\t\tbindingViewport.get(0),\n\t\t\t\tbindingViewport.get(1),\n\t\t\t\tbindingViewport.get(2),\n\t\t\t\tbindingViewport.get(3)\n\t\t);\n\t}\n\n\t@Override\n\tpublic void delete() {\n\t\tMemoryUtil.memFree(bindingViewport);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/viewports/ViewportBindingStateType.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.backends.states.viewports;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.states.EmptyBindingState;\nimport com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState;\n\npublic enum ViewportBindingStateType {\n\n\tIGNORED,\n\tMOJANG,\n\tOPENGL;\n\n\tpublic IBindingState create() {\n\t\treturn create(this);\n\t}\n\n\tpublic static IBindingState create(ViewportBindingStateType type) {\n\t\treturn switch (type) {\n\t\t\tcase IGNORED\t-> EmptyBindingState.INSTANCE;\n\t\t\tcase MOJANG\t\t-> new MojangViewportBindingState();\n\t\t\tcase OPENGL\t\t-> new OpenGLViewportBindingState();\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/AcceleratedBufferSources.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.AcceleratedBufferSource;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAcceleratedBufferSource;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder;\nimport com.github.argon4w.acceleratedrendering.core.utils.RenderTypeUtils;\nimport com.mojang.blaze3d.vertex.VertexFormat;\nimport it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;\nimport it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;\nimport net.minecraft.client.renderer.RenderType;\n\nimport java.util.Map;\nimport java.util.Set;\n\npublic class AcceleratedBufferSources implements IAcceleratedBufferSource {\n\n\tprivate final Map<VertexFormat, AcceleratedBufferSource>\tsources;\n\tprivate final Set<VertexFormat.Mode>\t\t\t\t\t\tvalidModes;\n\tprivate final boolean\t\t\t\t\t\t\t\t\t\tsupportTranslucent;\n\tprivate final boolean\t\t\t\t\t\t\t\t\t\tsupportDynamic;\n\n\tprivate AcceleratedBufferSources(\n\t\t\tMap<VertexFormat, AcceleratedBufferSource>\tsources,\n\t\t\tSet<VertexFormat.Mode>\t\t\t\t\t\tvalidModes,\n\t\t\tboolean\t\t\t\t\t\t\t\t\t\tsupportTranslucent,\n\t\t\tboolean\t\t\t\t\t\t\t\t\t\tsupportDynamic\n\t) {\n\t\tthis.sources\t\t\t= sources;\n\t\tthis.validModes\t\t\t= validModes;\n\t\tthis.supportTranslucent\t= supportTranslucent;\n\t\tthis.supportDynamic\t\t= supportDynamic;\n\t}\n\n\t@Override\n\tpublic AcceleratedBufferBuilder getBuffer(\n\t\t\tRenderType\trenderType,\n\t\t\tRunnable\tbefore,\n\t\t\tRunnable\tafter,\n\t\t\tint\t\t\tlayer\n\t) {\n\t\tif (\t\t\trenderType\t\t!= null\n\t\t\t\t&& \t(\tCoreFeature\t\t.shouldForceAccelerateTranslucent\t()\t|| supportTranslucent\t|| !RenderTypeUtils.isTranslucent\t(renderType))\n\t\t\t\t&& \t(\tCoreFeature\t\t.shouldCacheDynamicRenderType\t\t()\t|| supportDynamic\t\t|| !RenderTypeUtils.isDynamic\t\t(renderType))\n\t\t\t\t&&\t\tvalidModes\t\t.contains\t\t\t\t\t\t\t(renderType.mode)\n\t\t\t\t&&\t\tsources\t\t\t.containsKey\t\t\t\t\t\t(renderType.format)\n\t\t) {\n\t\t\treturn sources\n\t\t\t\t\t.get\t\t(renderType.format)\n\t\t\t\t\t.getBuffer\t(\n\t\t\t\t\t\t\trenderType,\n\t\t\t\t\t\t\tbefore,\n\t\t\t\t\t\t\tafter,\n\t\t\t\t\t\t\tlayer\n\t\t\t\t\t);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic static Builder builder() {\n\t\treturn new Builder();\n\t}\n\n\tpublic static class Builder {\n\n\t\tprivate final\tMap<VertexFormat, AcceleratedBufferSource>\tsources;\n\t\tprivate final\tSet<VertexFormat.Mode>\t\t\t\t\t\tvalidModes;\n\n\t\tprivate\t\t\tboolean\t\t\t\t\t\t\t\t\t\tsupportTranslucent;\n\t\tprivate\t\t\tboolean\t\t\t\t\t\t\t\t\t\tsupportDynamic;\n\n\t\tprivate Builder() {\n\t\t\tthis.sources\t\t\t= new Reference2ObjectOpenHashMap\t<>();\n\t\t\tthis.validModes\t\t\t= new ReferenceOpenHashSet\t\t\t<>();\n\n\t\t\tthis.supportTranslucent\t= false;\n\t\t\tthis.supportDynamic\t\t= false;\n\t\t}\n\n\t\tpublic Builder source(AcceleratedBufferSource bufferSource) {\n\t\t\tfor (var format : bufferSource\n\t\t\t\t\t.getEnvironment\t\t()\n\t\t\t\t\t.getVertexFormats\t()\n\t\t\t) {\n\t\t\t\tsources.put(format, bufferSource);\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic Builder mode(VertexFormat.Mode mode) {\n\t\t\tvalidModes.add(mode);\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic Builder supportTranslucent() {\n\t\t\tsupportTranslucent = true;\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic Builder supportDynamic() {\n\t\t\tsupportDynamic = true;\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic AcceleratedBufferSources build() {\n\t\t\treturn new AcceleratedBufferSources(\n\t\t\t\t\tsources,\n\t\t\t\t\tvalidModes,\n\t\t\t\t\tsupportTranslucent,\n\t\t\t\t\tsupportDynamic\n\t\t\t);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/EmptyAcceleratedBufferSources.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAcceleratedBufferSource;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder;\nimport net.minecraft.client.renderer.RenderType;\n\npublic class EmptyAcceleratedBufferSources implements IAcceleratedBufferSource {\n\n\tpublic static final IAcceleratedBufferSource INSTANCE = new EmptyAcceleratedBufferSources();\n\n\t@Override\n\tpublic AcceleratedBufferBuilder getBuffer(\n\t\t\tRenderType\trenderType,\n\t\t\tRunnable\tbefore,\n\t\t\tRunnable\tafter,\n\t\t\tint\t\t\tlayer\n\t) {\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/AcceleratedBufferSource.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerKey;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.functions.CustomLayerFunction;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.functions.EmptyLayerFunction;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.empty.EmptyLayerStorage;\nimport com.github.argon4w.acceleratedrendering.core.buffers.environments.IBufferEnvironment;\nimport com.github.argon4w.acceleratedrendering.core.programs.dispatchers.MeshUploadingProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.utils.RenderTypeUtils;\nimport com.mojang.blaze3d.systems.RenderSystem;\nimport com.mojang.blaze3d.vertex.BufferUploader;\nimport it.unimi.dsi.fastutil.ints.IntAVLTreeSet;\nimport it.unimi.dsi.fastutil.ints.IntSet;\nimport it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;\nimport it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;\nimport lombok.Getter;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.renderer.RenderType;\n\nimport java.util.Map;\nimport java.util.Set;\n\nimport static org.lwjgl.opengl.GL46.*;\n\npublic class AcceleratedBufferSource implements IAcceleratedBufferSource {\n\n\t@Getter private\tfinal\tIBufferEnvironment\t\t\t\t\t\tenvironment;\n\tprivate\t\t\tfinal\tAcceleratedRingBuffers\t\t\t\t\tringBuffers;\n\tprivate\t\t\tfinal\tSet<AcceleratedRingBuffers.Buffers>\t\tbuffers;\n\tprivate\t\t\tfinal\tMap<LayerKey, AcceleratedBufferBuilder> activeBuilders;\n\tprivate\t\t\tfinal\tIntSet\t\t\t\t\t\t\t\t\tactiveLayers;\n\n\tprivate\t\t\t\t\tAcceleratedRingBuffers.Buffers\t\t\tcurrentBuffer;\n\tprivate \t\t\t\tboolean\t\t\t\t\t\t\t\t\tused;\n\tprivate\t\t\t\t\tint\t\t\t\t\t\t\t\t\t\tbarriers;\n\n\tpublic AcceleratedBufferSource(IBufferEnvironment bufferEnvironment) {\n\t\tthis.environment\t= bufferEnvironment;\n\t\tthis.ringBuffers\t= new AcceleratedRingBuffers\t\t(this.environment);\n\t\tthis.buffers\t\t= new ObjectLinkedOpenHashSet\t<>\t();\n\t\tthis.activeBuilders\t= new Object2ObjectOpenHashMap\t<>\t();\n\t\tthis.activeLayers\t= new IntAVLTreeSet\t\t\t\t\t();\n\n\t\tthis.currentBuffer\t= this.ringBuffers.get(false);\n\t\tthis.used\t\t\t= false;\n\t\tthis.barriers\t\t= GL_SHADER_STORAGE_BARRIER_BIT;\n\n\t\tthis.buffers.add(this.currentBuffer);\n\t}\n\n\tpublic void delete() {\n\t\tringBuffers.delete();\n\t}\n\n\t@Override\n\tpublic AcceleratedBufferBuilder getBuffer(\n\t\t\tRenderType\trenderType,\n\t\t\tRunnable\tbefore,\n\t\t\tRunnable\tafter,\n\t\t\tint\t\t\tlayerIndex\n\t) {\n\t\tvar layerKey\t= new LayerKey\t\t\t\t\t(layerIndex, renderType);\n\t\tvar builder\t\t= activeBuilders.get\t\t\t(layerKey);\n\t\tvar builders\t= currentBuffer\t.getBuilders\t();\n\t\tvar functions\t= currentBuffer\t.getFunctions\t();\n\t\tvar layers\t\t= currentBuffer\t.getLayers\t\t();\n\t\tvar function\t= functions\t\t.get\t\t\t(layerIndex);\n\t\tvar layer\t\t= layers\t\t.get\t\t\t(layerIndex);\n\n\t\tif (builder != null) {\n\t\t\tfunction = builder\t.getFunction();\n\t\t\tfunction\t\t\t.addBefore\t(before);\n\t\t\tfunction\t\t\t.addAfter\t(after);\n\n\t\t\treturn builder;\n\t\t}\n\n\t\tvar vertexBuffer\t= currentBuffer.getVertexBuffer\t\t();\n\t\tvar varyingBuffer\t= currentBuffer.getVaryingBuffer\t();\n\t\tvar elementSegment\t= currentBuffer.getElementSegment\t();\n\n\t\tif (vertexBuffer == null) {\n\t\t\tcurrentBuffer\t= ringBuffers\t.get\t\t\t\t(true);\n\t\t\tbuilders\t\t= currentBuffer\t.getBuilders\t\t();\n\t\t\tfunctions\t\t= currentBuffer\t.getFunctions\t\t();\n\t\t\tlayers\t\t\t= currentBuffer\t.getLayers\t\t\t();\n\t\t\tfunction\t\t= functions\t\t.get\t\t\t\t(layerIndex);\n\t\t\tlayer\t\t\t= layers\t\t.get\t\t\t\t(layerIndex);\n\n\t\t\tvertexBuffer\t= currentBuffer\t.getVertexBuffer\t();\n\t\t\tvaryingBuffer\t= currentBuffer\t.getVaryingBuffer\t();\n\t\t\telementSegment\t= currentBuffer\t.getElementSegment\t();\n\n\t\t\tbuffers.add(currentBuffer);\n\t\t}\n\n\t\tif (layer == null) {\n\t\t\tfunction\t= new CustomLayerFunction\t\t\t();\n\t\t\tlayer \t\t= CoreFeature\t.createLayerStorage\t();\n\t\t\tlayers\t\t\t\t\t\t.put\t\t\t\t(layerIndex, layer);\n\t\t\tfunctions\t\t\t\t\t.put\t\t\t\t(layerIndex, function);\n\t\t}\n\n\t\tbuilder = new AcceleratedBufferBuilder(\n\t\t\t\tvertexBuffer,\n\t\t\t\tvaryingBuffer,\n\t\t\t\telementSegment,\n\t\t\t\tcurrentBuffer,\n\t\t\t\tfunction,\n\t\t\t\trenderType\n\t\t);\n\n\t\tused = true;\n\n\t\tbuilders\t\t.put\t\t(layerKey, builder);\n\t\tfunction\t\t.addBefore\t(before);\n\t\tfunction\t\t.addAfter\t(after);\n\t\tactiveBuilders\t.put\t\t(layerKey, builder);\n\t\tactiveLayers\t.add\t\t(layerIndex);\n\n\t\treturn builder;\n\t}\n\n\tpublic void prepareBuffers() {\n\t\tif (!used) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (var buffer : buffers) {\n\t\t\tvar builders\t= buffer.getBuilders();\n\t\t\tvar program\t\t= glGetInteger\t\t(GL_CURRENT_PROGRAM);\n\n\t\t\tif (builders.isEmpty()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tenvironment.getImmediateMeshBuffer\t\t\t\t().bindBase\t(GL_SHADER_STORAGE_BUFFER,\tMeshUploadingProgramDispatcher.SPARSE_MESH_BUFFER_INDEX);\n\t\t\tenvironment.selectMeshUploadingProgramDispatcher().dispatch\t(builders.values(),\t\t\tbuffer);\n\t\t\tenvironment.selectTransformProgramDispatcher\t().dispatch\t(builders.values());\n\n\t\t\tglMemoryBarrier(barriers);\n\n\t\t\tfor (var layerKey : builders.keySet()) {\n\t\t\t\tvar builder = builders.get(layerKey);\n\n\t\t\t\tif (builder.isEmpty()) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tvar drawContext\t\t= buffer\t\t\t.getDrawContext\t\t();\n\t\t\t\tvar elementSegment\t= builder\t\t\t.getElementSegment\t();\n\t\t\t\tvar renderType\t\t= layerKey\t\t\t.renderType\t\t\t();\n\t\t\t\tvar layer\t\t\t= layerKey\t\t\t.layer\t\t\t\t();\n\t\t\t\tvar drawType\t\t= RenderTypeUtils\t.getDrawType\t\t(renderType);\n\n\t\t\t\tbuilder\t\t\t\t\t\t\t\t\t.setOutdated\t\t();\n\t\t\t\telementSegment\t\t\t\t\t\t\t.allocateOffset\t\t();\n\t\t\t\tbuffer\t\t\t\t\t\t\t\t\t.bindElementBuffer\t(elementSegment);\n\t\t\t\tdrawContext\t\t\t\t\t\t\t\t.bindComputeBuffers\t(elementSegment);\n\t\t\t\tdrawContext\t\t\t\t\t\t\t\t.setRenderType\t\t(renderType);\n\n\t\t\t\tbuffer\n\t\t\t\t\t\t.getLayers\t()\n\t\t\t\t\t\t.get\t\t(layer)\n\t\t\t\t\t\t.get\t\t(drawType)\n\t\t\t\t\t\t.add\t\t(drawContext);\n\n\t\t\t\tbarriers |= builder.getPolygonProgramDispatcher().dispatch(builder);\n\t\t\t\tbarriers |= builder.getCullingProgramDispatcher().dispatch(builder);\n\t\t\t}\n\n\t\t\tglUseProgram(program);\n\t\t}\n\t}\n\n\tpublic void drawBuffers(LayerDrawType drawType) {\n\t\tif (!used) {\n\t\t\treturn;\n\t\t}\n\n\t\tglMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT\n\t\t\t\t|\t\tGL_ELEMENT_ARRAY_BARRIER_BIT\n\t\t\t\t|\t\tGL_COMMAND_BARRIER_BIT\n\t\t);\n\n\t\tfor (\t\tint layerIndex\t: activeLayers) {\n\t\t\tfor (\tvar buffer\t\t: buffers) {\n\t\t\t\tvar function = buffer.getFunctions\t().getOrDefault(layerIndex, EmptyLayerFunction\t.INSTANCE);\n\t\t\t\tvar contexts = buffer.getLayers\t\t().getOrDefault(layerIndex, EmptyLayerStorage\t.INSTANCE).get(drawType);\n\n\t\t\t\tif (contexts.isEmpty()) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tBufferUploader\t.invalidate\t\t();\n\t\t\t\tbuffer\t\t\t.bindDrawBuffers();\n\t\t\t\tcontexts\t\t.prepare\t\t();\n\t\t\t\tfunction\t\t.runBefore\t\t();\n\n\t\t\t\tfor (var drawContext : contexts) {\n\t\t\t\t\tvar renderType\t= drawContext\t.getRenderType\t\t();\n\t\t\t\t\trenderType\t\t\t\t\t\t.setupRenderState\t();\n\n\t\t\t\t\tvar mode\t= renderType\t.mode;\n\t\t\t\t\tvar shader\t= RenderSystem\t.getShader();\n\n\t\t\t\t\tshader.setDefaultUniforms(\n\t\t\t\t\t\t\tmode,\n\t\t\t\t\t\t\tRenderSystem\t\t\t.getModelViewMatrix\t(),\n\t\t\t\t\t\t\tRenderSystem\t\t\t.getProjectionMatrix(),\n\t\t\t\t\t\t\tMinecraft.getInstance()\t.getWindow\t\t\t()\n\t\t\t\t\t);\n\n\t\t\t\t\tshader\t\t.apply\t\t\t\t();\n\t\t\t\t\tdrawContext\t.drawElements\t\t(mode);\n\t\t\t\t\tshader\t\t.clear\t\t\t\t();\n\t\t\t\t\trenderType\t.clearRenderState\t();\n\t\t\t\t}\n\n\t\t\t\tfunction.runAfter\t\t\t();\n\t\t\t\tcontexts.reset\t\t\t\t();\n\t\t\t\tbuffer\t.unbindVertexArray\t();\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void clearBuffers() {\n\t\tif (!used) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (var buffer : buffers) {\n\t\t\tbuffer.reset\t\t();\n\t\t\tbuffer.setInFlight\t();\n\t\t}\n\n\t\tused\t\t\t= false;\n\t\tcurrentBuffer\t= ringBuffers\t.get\t(false);\n\t\tactiveBuilders\t\t\t\t\t.clear\t();\n\t\tactiveLayers\t\t\t\t\t.clear\t();\n\t\tbuffers\t\t\t\t\t\t\t.clear\t();\n\t\tbuffers\t\t\t\t\t\t\t.add\t(currentBuffer);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/AcceleratedRingBuffers.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.backends.Sync;\nimport com.github.argon4w.acceleratedrendering.core.backends.VertexArray;\nimport com.github.argon4w.acceleratedrendering.core.backends.buffers.MappedBuffer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerKey;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.functions.ILayerFunction;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.ILayerStorage;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.DrawContextPool;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.ElementBufferPool;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.StagingBufferPool;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.MeshUploaderPool;\nimport com.github.argon4w.acceleratedrendering.core.buffers.environments.IBufferEnvironment;\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout;\nimport com.github.argon4w.acceleratedrendering.core.utils.LoopResetPool;\nimport it.unimi.dsi.fastutil.ints.Int2ReferenceMap;\nimport it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;\nimport it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;\nimport lombok.Getter;\nimport org.apache.commons.lang3.mutable.MutableInt;\n\nimport java.util.Map;\n\nimport static org.lwjgl.opengl.GL15.GL_ELEMENT_ARRAY_BUFFER;\nimport static org.lwjgl.opengl.GL40.GL_DRAW_INDIRECT_BUFFER;\nimport static org.lwjgl.opengl.GL46.GL_ARRAY_BUFFER;\nimport static org.lwjgl.opengl.GL46.GL_SHADER_STORAGE_BUFFER;\n\npublic class AcceleratedRingBuffers extends LoopResetPool<AcceleratedRingBuffers.Buffers, IBufferEnvironment> {\n\n\tpublic AcceleratedRingBuffers(IBufferEnvironment bufferEnvironment) {\n\t\tsuper(CoreFeature.getPooledRingBufferSize(), bufferEnvironment);\n\t}\n\n\t@Override\n\tprotected Buffers create(IBufferEnvironment context, int i) {\n\t\treturn new Buffers(context);\n\t}\n\n\t@Override\n\tprotected void reset(Buffers buffers) {\n\n\t}\n\n\t@Override\n\tprotected void delete(Buffers buffers) {\n\t\tbuffers.delete();\n\t}\n\n\t@Override\n\tprotected boolean test(Buffers buffers) {\n\t\treturn buffers.isFree();\n\t}\n\n\t@Override\n\tpublic void init(Buffers buffers) {\n\t\tbuffers.setUsed();\n\t}\n\n\t@Override\n\tprotected Buffers fail(boolean force) {\n\t\tvar index = 0;\n\n\t\tif (force) {\n\t\t\tindex = size;\n\t\t\texpand();\n\t\t}\n\n\t\tvar buffer = at\t(index);\n\t\tbuffer.waitSync\t();\n\t\tbuffer.setUsed\t();\n\n\t\treturn buffer;\n\t}\n\n\tpublic static class Buffers {\n\n\t\tpublic static\tfinal\tint\t\t\t\t\t\t\t\t\t\t\t\t\t\tVERTEX_BUFFER_OUT_INDEX\t\t= 1;\n\t\tpublic static\tfinal\tint\t\t\t\t\t\t\t\t\t\t\t\t\t\tSHARING_BUFFER_INDEX\t\t= 2;\n\t\tpublic static\tfinal\tint\t\t\t\t\t\t\t\t\t\t\t\t\t\tVARYING_BUFFER_OUT_INDEX\t= 4;\n\t\tpublic static\tfinal\tint\t\t\t\t\t\t\t\t\t\t\t\t\t\tELEMENT_BUFFER_INDEX\t\t= 6;\n\n\t\tprivate\t\t\tfinal\tMeshUploaderPool\t\t\t\t\t\t\t\t\t\tmeshUploaderPool;\n\t\tprivate\t\t\tfinal \tDrawContextPool\t\t\t\t\t\t\t\t\t\t\tdrawContextPool;\n\t\tprivate\t\t\tfinal \tElementBufferPool\t\t\t\t\t\t\t\t\t\telementBufferPool;\n\t\tprivate\t\t\tfinal \tMappedBuffer\t\t\t\t\t\t\t\t\t\t\tsharingBuffer;\n\t\tprivate\t\t\tfinal \tStagingBufferPool\t\t\t\t\t\t\t\t\t\tvaryingBuffer;\n\t\tprivate\t\t\tfinal\tStagingBufferPool\t\t\t\t\t\t\t\t\t\tvertexBuffer;\n\t\tprivate\t\t\tfinal \tVertexArray\t\t\t\t\t\t\t\t\t\t\t\tvertexArray;\n\t\tprivate\t\t\tfinal \tSync\t\t\t\t\t\t\t\t\t\t\t\t\tsync;\n\t\tprivate\t\t\tfinal \tMutableInt\t\t\t\t\t\t\t\t\t\t\t\tsharing;\n\t\t@Getter\tprivate\tfinal\tMap\t\t\t\t<LayerKey, AcceleratedBufferBuilder>\tbuilders;\n\t\t@Getter\tprivate final\tInt2ReferenceMap<ILayerStorage>\t\t\t\t\t\t\tlayers;\n\t\t@Getter private final\tInt2ReferenceMap<ILayerFunction>\t\t\t\t\t\tfunctions;\n\t\t@Getter private\tfinal\tIBufferEnvironment\t\t\t\t\t\t\t\t\t\tbufferEnvironment;\n\t\t@Getter private\tfinal\tint\t\t\t\t\t\t\t\t\t\t\t\t\t\tsize;\n\n\t\tprivate \t\t\t\tboolean\t\t\t\t\t\t\t\t\t\t\t\t\tused;\n\t\tprivate\t\t\t\t\tVertexLayout\t\t\t\t\t\t\t\t\t\t\tlayout;\n\n\t\tpublic Buffers(IBufferEnvironment bufferEnvironment) {\n\t\t\tthis.size\t\t\t\t= CoreFeature.getPooledBatchingSize\t\t();\n\t\t\tthis.meshUploaderPool\t= new MeshUploaderPool\t\t\t\t\t();\n\t\t\tthis.drawContextPool\t= new DrawContextPool\t\t\t\t\t(size);\n\t\t\tthis.elementBufferPool\t= new ElementBufferPool\t\t\t\t\t(size);\n\t\t\tthis.sharingBuffer\t\t= new MappedBuffer\t\t\t\t\t\t(64L);\n\t\t\tthis.varyingBuffer\t\t= new StagingBufferPool\t\t\t\t\t(size);\n\t\t\tthis.vertexBuffer\t\t= new StagingBufferPool\t\t\t\t\t(size);\n\t\t\tthis.vertexArray\t\t= new VertexArray\t\t\t\t\t\t();\n\t\t\tthis.sync\t\t\t\t= new Sync\t\t\t\t\t\t\t\t();\n\t\t\tthis.sharing\t\t\t= new MutableInt\t\t\t\t\t\t(0);\n\t\t\tthis.builders\t\t\t= new Object2ObjectLinkedOpenHashMap<>\t();\n\t\t\tthis.layers\t\t\t\t= new Int2ReferenceOpenHashMap\t\t<>\t();\n\t\t\tthis.functions\t\t\t= new Int2ReferenceOpenHashMap\t\t<>\t();\n\t\t\tthis.bufferEnvironment\t= bufferEnvironment;\n\n\t\t\tthis.used\t\t\t\t= false;\n\t\t}\n\n\t\tpublic void reset() {\n\t\t\tmeshUploaderPool\t.reset\t\t();\n\t\t\tdrawContextPool\t\t.reset\t\t();\n\t\t\telementBufferPool\t.reset\t\t();\n\t\t\tvaryingBuffer\t\t.reset\t\t();\n\t\t\tsharingBuffer\t\t.reset\t\t();\n\t\t\tvertexBuffer\t\t.reset\t\t();\n\t\t\tsharing\t\t\t\t.setValue\t(0);\n\t\t\tbuilders\t\t\t.clear\t\t();\n\n\t\t\tfor (int i : layers.keySet()) {\n\t\t\t\tlayers\t\t.get(i).reset();\n\t\t\t\tfunctions\t.get(i).reset();\n\t\t\t}\n\t\t}\n\n\t\tpublic void bindTransformBuffers() {\n\t\t\tvertexBuffer\t.getBufferOut()\t.bindBase(GL_SHADER_STORAGE_BUFFER, VERTEX_BUFFER_OUT_INDEX);\n\t\t\tvaryingBuffer\t.getBufferOut()\t.bindBase(GL_SHADER_STORAGE_BUFFER, VARYING_BUFFER_OUT_INDEX);\n\t\t\tsharingBuffer\t\t\t\t\t.bindBase(GL_SHADER_STORAGE_BUFFER, SHARING_BUFFER_INDEX);\n\t\t}\n\n\t\tpublic void bindElementBuffer(ElementBufferPool.ElementSegment elementSegment) {\n\t\t\telementBufferPool\n\t\t\t\t\t.getElementBufferOut()\n\t\t\t\t\t.bindRange\t\t\t(\n\t\t\t\t\t\t\tGL_SHADER_STORAGE_BUFFER,\n\t\t\t\t\t\t\tELEMENT_BUFFER_INDEX,\n\t\t\t\t\t\t\telementSegment.getOffset(),\n\t\t\t\t\t\t\telementSegment.getSize\t()\n\t\t\t\t\t);\n\t\t}\n\n\t\tpublic void bindDrawBuffers() {\n\t\t\tvertexArray\t\t\t\t\t.bind();\n\t\t\tdrawContextPool.getContext().bind(GL_DRAW_INDIRECT_BUFFER);\n\n\t\t\tif (\t\t!\tbufferEnvironment\t.getLayout\t\t\t().equals\t(layout)\n\t\t\t\t\t||\t\tvertexBuffer\t\t.getBufferOut\t\t().isResized()\n\t\t\t\t\t||\t\telementBufferPool\t.getElementBufferOut().isResized()\n\t\t\t) {\n\t\t\t\tlayout = bufferEnvironment\t\t\t\t\t.getLayout\t\t\t();\n\t\t\t\telementBufferPool\t.getElementBufferOut()\t.bind\t\t\t\t(GL_ELEMENT_ARRAY_BUFFER);\n\t\t\t\telementBufferPool\t.getElementBufferOut()\t.resetResized\t\t();\n\t\t\t\tvertexBuffer\t\t.getBufferOut()\t\t\t.bind\t\t\t\t(GL_ARRAY_BUFFER);\n\t\t\t\tvertexBuffer\t\t.getBufferOut()\t\t\t.resetResized\t\t();\n\t\t\t\tbufferEnvironment\t\t\t\t\t\t\t.setupBufferState\t();\n\t\t\t}\n\t\t}\n\n\t\tpublic void prepare() {\n\t\t\tvertexBuffer\t\t.prepare();\n\t\t\tvaryingBuffer\t\t.prepare();\n\t\t\telementBufferPool\t.prepare();\n\t\t}\n\n\t\tpublic void unbindVertexArray() {\n\t\t\tvertexArray.unbind();\n\t\t}\n\n\t\tpublic MeshUploaderPool.MeshUploader getMeshUploader() {\n\t\t\treturn meshUploaderPool.get();\n\t\t}\n\n\t\tpublic StagingBufferPool.StagingBuffer getVertexBuffer() {\n\t\t\treturn vertexBuffer.get();\n\t\t}\n\n\t\tpublic StagingBufferPool.StagingBuffer getVaryingBuffer() {\n\t\t\treturn varyingBuffer.get();\n\t\t}\n\n\t\tpublic ElementBufferPool.ElementSegment getElementSegment() {\n\t\t\treturn elementBufferPool.get();\n\t\t}\n\n\t\tpublic DrawContextPool.DrawContext getDrawContext() {\n\t\t\treturn drawContextPool.get();\n\t\t}\n\n\t\tpublic long getVertexSize() {\n\t\t\treturn bufferEnvironment.getVertexSize();\n\t\t}\n\n\t\tpublic int getSharing() {\n\t\t\treturn sharing.getAndIncrement();\n\t\t}\n\n\t\tpublic long reserveSharing() {\n\t\t\treturn sharingBuffer.reserve(4L * 4L * 4L + 4L * 4L * 3L);\n\t\t}\n\n\t\tpublic void setUsed() {\n\t\t\tused = true;\n\t\t}\n\n\t\tpublic void setInFlight() {\n\t\t\tused = false;\n\t\t\tsync.setSync();\n\t\t}\n\n\t\tprotected void waitSync() {\n\t\t\tif (!sync.isSyncSet()) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!sync.isSyncSignaled()) {\n\t\t\t\tsync.waitSync();\n\t\t\t}\n\n\t\t\tsync.deleteSync\t();\n\t\t\tsync.resetSync\t();\n\t\t}\n\n\t\tpublic boolean isFree() {\n\t\t\tif (used) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (!sync.isSyncSet()) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif (!sync.isSyncSignaled()) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tsync.deleteSync\t();\n\t\t\tsync.resetSync\t();\n\n\t\t\treturn true;\n\t\t}\n\n\t\tpublic void delete() {\n\t\t\tmeshUploaderPool\t.delete\t();\n\t\t\tdrawContextPool\t\t.delete\t();\n\t\t\telementBufferPool\t.delete\t();\n\t\t\tsharingBuffer\t\t.delete\t();\n\t\t\tvaryingBuffer\t\t.delete\t();\n\t\t\tvertexBuffer\t\t.delete\t();\n\t\t\tvertexArray\t\t\t.delete\t();\n\t\t\twaitSync\t\t\t\t\t();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/IAcceleratedBufferSource.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder;\nimport net.minecraft.client.renderer.RenderType;\n\npublic interface IAcceleratedBufferSource {\n\n\tAcceleratedBufferBuilder getBuffer(RenderType renderType, Runnable before, Runnable after, int layer);\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/IAccelerationHolder.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport net.minecraft.client.renderer.RenderType;\n\nimport java.util.function.Supplier;\n\npublic interface IAccelerationHolder {\n\n\tVertexConsumer\t\t\t\tinitAcceleration(RenderType renderType, Supplier<IAcceleratedBufferSource> bufferSource);\n\tAcceleratedBufferBuilder\tgetAccelerated\t();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/AcceleratedBufferBuilder.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.AcceleratedRingBuffers;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.functions.ILayerFunction;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.ElementBufferPool;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.StagingBufferPool;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.MeshUploaderPool;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.*;\nimport com.github.argon4w.acceleratedrendering.core.meshes.ServerMesh;\nimport com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.programs.dispatchers.IPolygonProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.programs.overrides.ITransformShaderProgramOverride;\nimport com.github.argon4w.acceleratedrendering.core.programs.overrides.IUploadingShaderProgramOverride;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport com.mojang.blaze3d.vertex.VertexFormat;\nimport com.mojang.blaze3d.vertex.VertexFormatElement;\nimport it.unimi.dsi.fastutil.objects.Reference2ObjectLinkedOpenHashMap;\nimport lombok.EqualsAndHashCode;\nimport lombok.Getter;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.util.FastColor;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.lwjgl.system.MemoryUtil;\n\nimport java.nio.ByteBuffer;\nimport java.util.Map;\nimport java.util.function.LongSupplier;\n\n@EqualsAndHashCode(onlyExplicitlyIncluded = true)\npublic class AcceleratedBufferBuilder implements IAcceleratedVertexConsumer, VertexConsumer, LongSupplier {\n\n\tpublic static\t\t\t\t\t\t\t\tfinal\tlong\t\t\t\t\t\t\t\t\t\t\tSHARING_SIZE\t\t= 4L * 4L * 4L + 4L * 3L * 4L;\n\tpublic static\t\t\t\t\t\t\t\tfinal\tIMemoryInterface\t\t\t\t\t\t\t\tSHARING_TRANSFORM\t= new SimpleMemoryInterface\t\t\t(0L,\t\t\tSHARING_SIZE);\n\tpublic static\t\t\t\t\t\t\t\tfinal\tIMemoryInterface\t\t\t\t\t\t\t\tSHARING_NORMAL\t\t= new SimpleMemoryInterface\t\t\t(4L * 4L * 4L,\tSHARING_SIZE);\n\n\t@Getter public\t\t\t\t\t\t\t\tfinal\tIMemoryInterface\t\t\t\t\t\t\t\tvaryingOffset;\n\t@Getter public\t\t\t\t\t\t\t\tfinal\tIMemoryInterface\t\t\t\t\t\t\t\tvaryingSharing;\n\t@Getter public\t\t\t\t\t\t\t\tfinal\tIMemoryInterface\t\t\t\t\t\t\t\tvaryingMesh;\n\t@Getter public\t\t\t\t\t\t\t\tfinal\tIMemoryInterface\t\t\t\t\t\t\t\tvaryingShouldCull;\n\n\t@Getter private\t\t\t\t\t\t\t\tfinal\tMap<ServerMesh, MeshUploaderPool.MeshUploader>\tmeshUploaders;\n\t@Getter private\t\t\t\t\t\t\t\tfinal\tStagingBufferPool\t\t.StagingBuffer\t\t\tvertexBuffer;\n\t@Getter private\t\t\t\t\t\t\t\tfinal\tStagingBufferPool\t\t.StagingBuffer\t\t\tvaryingBuffer;\n\t@Getter private\t\t\t\t\t\t\t\tfinal\tElementBufferPool\t\t.ElementSegment\t\t\telementSegment;\n\t@Getter private\t\t\t\t\t\t\t\tfinal\tAcceleratedRingBuffers\t.Buffers\t\t\t\tbuffer;\n\t@Getter private\t\t\t\t\t\t\t\tfinal\tILayerFunction\t\t\t\t\t\t\t\t\tfunction;\n\n\n\t@EqualsAndHashCode.Include private\t\t\tfinal\tRenderType\t\t\t\t\t\t\t\t\t\trenderType;\n\t@Getter @EqualsAndHashCode.Include private\tfinal\tVertexLayout\t\t\t\t\t\t\t\t\tlayout;\n\t@Getter private\t\t\t\t\t\t\t\tfinal\tIPolygonProgramDispatcher\t\t\t\t\t\tpolygonProgramDispatcher;\n\t@Getter private\t\t\t\t\t\t\t\tfinal\tICullingProgramDispatcher\t\t\t\t\t\tcullingProgramDispatcher;\n\t@Getter private\t\t\t\t\t\t\t\tfinal\tITransformShaderProgramOverride\t\t\t\t\ttransformOverride;\n\t@Getter private\t\t\t\t\t\t\t\tfinal\tIUploadingShaderProgramOverride\t\t\t\t\tuploadingOverride;\n\t@Getter private\t\t\t\t\t\t\t\tfinal\tVertexFormat.Mode\t\t\t\t\t\t\t\tmode;\n\t@Getter private\t\t\t\t\t\t\t\tfinal\tint\t\t\t\t\t\t\t\t\t\t\t\tpolygonSize;\n\t@Getter private\t\t\t\t\t\t\t\tfinal\tint\t\t\t\t\t\t\t\t\t\t\t\tpolygonElementCount;\n\t@Getter private\t\t\t\t\t\t\t\tfinal\tlong\t\t\t\t\t\t\t\t\t\t\tvertexSize;\n\n\tprivate\t\t\t\t\t\t\t\t\t\tfinal\tIMemoryInterface\t\t\t\t\t\t\t\tposOffset;\n\t@Getter private\t\t\t\t\t\t\t\tfinal\tIMemoryInterface\t\t\t\t\t\t\t\tcolorOffset;\n\tprivate\t\t\t\t\t\t\t\t\t\tfinal\tIMemoryInterface\t\t\t\t\t\t\t\tuv0Offset;\n\t@Getter private\t\t\t\t\t\t\t\tfinal\tIMemoryInterface\t\t\t\t\t\t\t\tuv1Offset;\n\t@Getter private\t\t\t\t\t\t\t\tfinal\tIMemoryInterface\t\t\t\t\t\t\t\tuv2Offset;\n\tprivate\t\t\t\t\t\t\t\t\t\tfinal\tIMemoryInterface\t\t\t\t\t\t\t\tnormalOffset;\n\n\tprivate \t\t\t\t\t\t\t\t\tfinal\tMatrix4f\t\t\t\t\t\t\t\t\t\tcachedTransformValue;\n\tprivate\t\t\t\t\t\t\t\t\t\tfinal\tMatrix3f\t\t\t\t\t\t\t\t\t\tcachedNormalValue;\n\n\tprivate\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\t\t\t\t\t\t\t\t\telementCount;\n\t@Getter private\t\t\t\t\t\t\t\t\t\tint\t\t\t\t\t\t\t\t\t\t\t\tmeshVertexCount;\n\t@Getter private\t\t\t\t\t\t\t\t\t\tint\t\t\t\t\t\t\t\t\t\t\t\tvertexCount;\n\tprivate\t\t\t\t\t\t\t\t\t\t\t\tlong\t\t\t\t\t\t\t\t\t\t\tvertexAddress;\n\tprivate\t\t\t\t\t\t\t\t\t\t\t\tlong\t\t\t\t\t\t\t\t\t\t\tsharingAddress;\n\tprivate\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\t\t\t\t\t\t\t\t\tactiveSharing;\n\tprivate\t\t\t\t\t\t\t\t\t\t\t\tint\t\t\t\t\t\t\t\t\t\t\t\tcachedSharing;\n\t@Getter private\t\t \t\t\t\t\t\t\t\tboolean\t\t\t\t\t\t\t\t\t\t\toutdated;\n\n\tprivate\t\t\t\t\t\t\t\t\t\t\t\tMatrix4f\t\t\t\t\t\t\t\t\t\tcachedTransform;\n\tprivate\t\t\t\t\t\t\t\t\t\t\t\tMatrix3f\t\t\t\t\t\t\t\t\t\tcachedNormal;\n\n\tpublic AcceleratedBufferBuilder(\n\t\t\tStagingBufferPool\t\t.StagingBuffer\tvertexBuffer,\n\t\t\tStagingBufferPool\t\t.StagingBuffer\tvaryingBuffer,\n\t\t\tElementBufferPool\t\t.ElementSegment\telementSegment,\n\t\t\tAcceleratedRingBuffers\t.Buffers\t\tbuffer,\n\t\t\tILayerFunction\t\t\t\t\t\t\tlayerFunction,\n\t\t\tRenderType\t\t\t\t\t\t\t\trenderType\n\t) {\n\t\tvar environment\t\t\t\t\t= buffer.getBufferEnvironment();\n\n\t\tthis.varyingOffset\t\t\t\t= new SimpleDynamicMemoryInterface\t\t\t\t\t\t(0L * 4L, this);\n\t\tthis.varyingSharing\t\t\t\t= new SimpleDynamicMemoryInterface\t\t\t\t\t\t(1L * 4L, this);\n\t\tthis.varyingMesh\t\t\t\t= new SimpleDynamicMemoryInterface\t\t\t\t\t\t(2L * 4L, this);\n\t\tthis.varyingShouldCull\t\t\t= new SimpleDynamicMemoryInterface\t\t\t\t\t\t(3L * 4L, this);\n\n\t\tthis.meshUploaders\t\t\t\t= new Reference2ObjectLinkedOpenHashMap<>\t\t\t\t();\n\t\tthis.vertexBuffer\t\t\t\t= vertexBuffer;\n\t\tthis.varyingBuffer\t\t\t\t= varyingBuffer;\n\t\tthis.elementSegment\t\t\t\t= elementSegment;\n\t\tthis.buffer\t\t\t\t\t\t= buffer;\n\t\tthis.function\t\t\t\t\t= layerFunction;\n\n\t\tthis.renderType\t\t\t\t\t= renderType;\n\t\tthis.layout\t\t\t\t\t\t= environment\t\t.getLayout\t\t\t\t\t\t\t();\n\t\tthis.polygonProgramDispatcher\t= environment\t\t.selectProcessingProgramDispatcher\t(this.renderType.mode);\n\t\tthis.cullingProgramDispatcher\t= environment\t\t.selectCullingProgramDispatcher\t\t(this.renderType);\n\t\tthis.transformOverride\t\t\t= environment\t\t.getTransformProgramOverride\t\t(this.renderType);\n\t\tthis.uploadingOverride\t\t\t= environment\t\t.getUploadingProgramOverride\t\t(this.renderType);\n\n\t\tthis.mode\t\t\t\t\t\t= this.renderType\t.mode;\n\t\tthis.polygonSize\t\t\t\t= this.mode\t\t\t.primitiveLength;\n\t\tthis.polygonElementCount\t\t= this.mode\t\t\t.indexCount\t\t\t\t\t\t\t(this.polygonSize);\n\t\tthis.vertexSize\t\t\t\t\t= this.buffer\t\t.getVertexSize\t\t\t\t\t\t();\n\n\t\tthis.posOffset\t\t\t\t\t= this.layout\t\t.getElement\t\t\t\t\t\t\t(VertexFormatElement.POSITION);\n\t\tthis.colorOffset\t\t\t\t= this.layout\t\t.getElement\t\t\t\t\t\t\t(VertexFormatElement.COLOR);\n\t\tthis.uv0Offset\t\t\t\t\t= this.layout\t\t.getElement\t\t\t\t\t\t\t(VertexFormatElement.UV0);\n\t\tthis.uv1Offset\t\t\t\t\t= this.layout\t\t.getElement\t\t\t\t\t\t\t(VertexFormatElement.UV1);\n\t\tthis.uv2Offset\t\t\t\t\t= this.layout\t\t.getElement\t\t\t\t\t\t\t(VertexFormatElement.UV2);\n\t\tthis.normalOffset\t\t\t\t= this.layout\t\t.getElement\t\t\t\t\t\t\t(VertexFormatElement.NORMAL);\n\n\t\tthis.cachedTransformValue\t\t= new Matrix4f();\n\t\tthis.cachedNormalValue\t\t\t= new Matrix3f();\n\n\t\tthis.elementCount\t\t\t\t= 0;\n\t\tthis.meshVertexCount\t\t\t= 0;\n\t\tthis.vertexCount\t\t\t\t= 0;\n\t\tthis.vertexAddress\t\t\t\t= -1;\n\t\tthis.sharingAddress\t\t\t\t= -1;\n\t\tthis.activeSharing\t\t\t\t= -1;\n\t\tthis.cachedSharing\t\t\t\t= -1;\n\n\t\tthis.cachedTransform\t\t\t= null;\n\t\tthis.cachedNormal\t\t\t\t= null;\n\t}\n\n\t@Override\n\tpublic VertexConsumer addVertex(\n\t\t\tPoseStack.Pose\tpPose,\n\t\t\tfloat\t\t\tpX,\n\t\t\tfloat\t\t\tpY,\n\t\t\tfloat\t\t\tpZ\n\t) {\n\t\tbeginTransform(\n\t\t\t\tpPose.pose\t(),\n\t\t\t\tpPose.normal()\n\t\t);\n\n\t\treturn addVertex(\n\t\t\t\tpX,\n\t\t\t\tpY,\n\t\t\t\tpZ\n\t\t);\n\t}\n\n\t@Override\n\tpublic VertexConsumer addVertex(\n\t\t\tfloat pX,\n\t\t\tfloat pY,\n\t\t\tfloat pZ\n\t) {\n\t\tvar vertexAddress\t= vertexBuffer\t.reserve(getVertexSize\t());\n\t\tvar varyingAddress\t= varyingBuffer\t.reserve(getVaryingSize\t());\n\n\t\tthis.vertexAddress\t= vertexAddress;\n\n\t\tposOffset\t\t\t.putFloat\t\t(vertexAddress + 0L,\tpX);\n\t\tposOffset\t\t\t.putFloat\t\t(vertexAddress + 4L,\tpY);\n\t\tposOffset\t\t\t.putFloat\t\t(vertexAddress + 8L,\tpZ);\n\n\t\tvaryingOffset\t\t.putInt\t\t\t(varyingAddress,\t\t0);\n\t\tvaryingSharing\t\t.putInt\t\t\t(varyingAddress,\t\tactiveSharing);\n\t\tvaryingMesh\t\t\t.putInt\t\t\t(varyingAddress,\t\t-1);\n\t\tvaryingShouldCull\t.putInt\t\t\t(varyingAddress,\t\tcullingProgramDispatcher.shouldCull() ? 1 : 0);\n\t\ttransformOverride\t.uploadVarying\t(vertexAddress,\t\t\t0);\n\n\t\tvertexCount\t\t++;\n\t\telementCount\t++;\n\n\t\tif (elementCount >= polygonSize) {\n\t\t\telementSegment.countElements(polygonElementCount);\n\t\t\telementCount\t= 0;\n\t\t\tactiveSharing\t= -1;\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setColor(\n\t\t\tint pRed,\n\t\t\tint pGreen,\n\t\t\tint pBlue,\n\t\t\tint pAlpha\n\t) {\n\t\tif (vertexAddress == -1) {\n\t\t\tthrow new IllegalStateException(\"Vertex not building!\");\n\t\t}\n\n\t\tcolorOffset.putByte(vertexAddress + 0L, (byte) pRed);\n\t\tcolorOffset.putByte(vertexAddress + 1L, (byte) pGreen);\n\t\tcolorOffset.putByte(vertexAddress + 2L, (byte) pBlue);\n\t\tcolorOffset.putByte(vertexAddress + 3L, (byte) pAlpha);\n\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setUv(float pU, float pV) {\n\t\tif (vertexAddress == -1) {\n\t\t\tthrow new IllegalStateException(\"Vertex not building!\");\n\t\t}\n\n\t\tuv0Offset.putFloat(vertexAddress + 0L, pU);\n\t\tuv0Offset.putFloat(vertexAddress + 4L, pV);\n\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setUv1(int pU, int pV) {\n\t\tif (vertexAddress == -1) {\n\t\t\tthrow new IllegalStateException(\"Vertex not building!\");\n\t\t}\n\n\t\tuv1Offset.putShort(vertexAddress + 0L, (short) pU);\n\t\tuv1Offset.putShort(vertexAddress + 2L, (short) pV);\n\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setUv2(int pU, int pV) {\n\t\tif (vertexAddress == -1) {\n\t\t\tthrow new IllegalStateException(\"Vertex not building!\");\n\t\t}\n\n\t\tuv2Offset.putShort(vertexAddress + 0L, (short) pU);\n\t\tuv2Offset.putShort(vertexAddress + 2L, (short) pV);\n\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setNormal(\n\t\t\tPoseStack.Pose\tpPose,\n\t\t\tfloat\t\t\tpNormalX,\n\t\t\tfloat\t\t\tpNormalY,\n\t\t\tfloat\t\t\tpNormalZ\n\t) {\n\t\tvar normal = pPose.normal();\n\n\t\tif (activeSharing == -1) {\n\t\t\treturn VertexConsumer.super.setNormal(\n\t\t\t\t\tpPose,\n\t\t\t\t\tpNormalX,\n\t\t\t\t\tpNormalY,\n\t\t\t\t\tpNormalZ\n\t\t\t);\n\t\t}\n\n\t\tif (!normal.equals(cachedNormal)) {\n\t\t\tSHARING_NORMAL.putMatrix3f(sharingAddress, normal);\n\t\t}\n\n\t\treturn setNormal(\n\t\t\t\tpNormalX,\n\t\t\t\tpNormalY,\n\t\t\t\tpNormalZ\n\t\t);\n\t}\n\n\t@Override\n\tpublic VertexConsumer setNormal(\n\t\t\tfloat pNormalX,\n\t\t\tfloat pNormalY,\n\t\t\tfloat pNormalZ\n\t) {\n\t\tif (vertexAddress == -1) {\n\t\t\tthrow new IllegalStateException(\"Vertex not building!\");\n\t\t}\n\n\t\tnormalOffset.putNormal(vertexAddress + 0L, pNormalX);\n\t\tnormalOffset.putNormal(vertexAddress + 1L, pNormalY);\n\t\tnormalOffset.putNormal(vertexAddress + 2L, pNormalZ);\n\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic void addVertex(\n\t\t\tfloat\tpX,\n\t\t\tfloat\tpY,\n\t\t\tfloat\tpZ,\n\t\t\tint\t\tpColor,\n\t\t\tfloat\tpU,\n\t\t\tfloat\tpV,\n\t\t\tint\t\tpPackedOverlay,\n\t\t\tint\t\tpPackedLight,\n\t\t\tfloat\tpNormalX,\n\t\t\tfloat\tpNormalY,\n\t\t\tfloat\tpNormalZ\n\t) {\n\t\tvar vertexAddress\t= vertexBuffer\t.reserve(getVertexSize\t());\n\t\tvar varyingAddress\t= varyingBuffer\t.reserve(getVaryingSize\t());\n\n\t\tposOffset\t\t\t.putFloat\t\t(vertexAddress + 0L,\tpX);\n\t\tposOffset\t\t\t.putFloat\t\t(vertexAddress + 4L,\tpY);\n\t\tposOffset\t\t\t.putFloat\t\t(vertexAddress + 8L,\tpZ);\n\t\tcolorOffset\t\t\t.putInt\t\t\t(vertexAddress,\t\t\tFastColor.ABGR32.fromArgb32(pColor));\n\t\tuv0Offset\t\t\t.putFloat\t\t(vertexAddress + 0L,\tpU);\n\t\tuv0Offset\t\t\t.putFloat\t\t(vertexAddress + 4L,\tpV);\n\t\tuv1Offset\t\t\t.putInt\t\t\t(vertexAddress,\t\t\tpPackedOverlay);\n\t\tuv2Offset\t\t\t.putInt\t\t\t(vertexAddress,\t\t\tpPackedLight);\n\t\tnormalOffset\t\t.putNormal\t\t(vertexAddress + 0L,\tpNormalX);\n\t\tnormalOffset\t\t.putNormal\t\t(vertexAddress + 1L,\tpNormalY);\n\t\tnormalOffset\t\t.putNormal\t\t(vertexAddress + 2L,\tpNormalZ);\n\n\t\tvaryingOffset\t\t.putInt\t\t\t(varyingAddress,\t\t0);\n\t\tvaryingSharing\t\t.putInt\t\t\t(varyingAddress,\t\tactiveSharing);\n\t\tvaryingMesh\t\t\t.putInt\t\t\t(varyingAddress,\t\t-1);\n\t\tvaryingShouldCull\t.putInt\t\t\t(varyingAddress,\t\tcullingProgramDispatcher.shouldCull() ? 1 : 0);\n\t\ttransformOverride\t.uploadVarying\t(varyingAddress,\t\t0);\n\n\t\tvertexCount\t\t++;\n\t\telementCount\t++;\n\n\t\tif (elementCount >= polygonSize) {\n\t\t\telementSegment.countElements(polygonElementCount);\n\t\t\telementCount\t= 0;\n\t\t\tactiveSharing\t= -1;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void beginTransform(Matrix4f transform, Matrix3f normal) {\n\t\tif (\t\tCoreFeature\t.shouldCacheIdenticalPose\t()\n\t\t\t\t&&\ttransform\t.equals\t\t\t\t\t\t(cachedTransform)\n\t\t\t\t&&\tnormal\t\t.equals\t\t\t\t\t\t(cachedNormal)\n\t\t) {\n\t\t\tactiveSharing = cachedSharing;\n\t\t\treturn;\n\t\t}\n\n\t\tcachedTransform\t= cachedTransformValue\t.set\t\t\t(transform);\n\t\tcachedNormal\t= cachedNormalValue\t\t.set\t\t\t(normal);\n\n\t\tsharingAddress\t= buffer\t\t\t\t.reserveSharing\t();\n\t\tcachedSharing\t= buffer\t\t\t\t.getSharing\t\t();\n\t\tactiveSharing\t= cachedSharing;\n\n\t\tSHARING_TRANSFORM\t.putMatrix4f(sharingAddress, transform);\n\t\tSHARING_NORMAL\t\t.putMatrix3f(sharingAddress, normal);\n\t}\n\n\t@Override\n\tpublic void endTransform() {\n\t\tcachedTransform\t= null;\n\t\tcachedNormal\t= null;\n\t\tactiveSharing\t= -1;\n\t\tcachedSharing\t= -1;\n\t}\n\n\t@Override\n\tpublic void addClientMesh(\n\t\t\tByteBuffer\tmeshBuffer,\n\t\t\tint\t\t\tsize,\n\t\t\tint\t\t\tcolor,\n\t\t\tint\t\t\tlight,\n\t\t\tint\t\t\toverlay\n\t) {\n\t\tvar bufferSize\t\t= vertexSize * size;\n\t\tvar vertexAddress\t= vertexBuffer\t.reserve(bufferSize);\n\t\tvar varyingAddress\t= varyingBuffer\t.reserve(getVaryingSize() * size);\n\n\t\tMemoryUtil.memCopy(\n\t\t\t\tMemoryUtil.memAddress0(meshBuffer),\n\t\t\t\tvertexAddress,\n\t\t\t\tbufferSize\n\t\t);\n\n\t\tcolorOffset\t\t\t.putInt\t\t\t(vertexAddress,\t\tFastColor.ABGR32.fromArgb32(color));\n\t\tuv1Offset\t\t\t.putInt\t\t\t(vertexAddress,\t\toverlay);\n\t\tuv2Offset\t\t\t.putInt\t\t\t(vertexAddress,\t\tlight);\n\n\t\tvaryingSharing\t\t.putInt\t\t\t(varyingAddress,\tactiveSharing);\n\t\tvaryingMesh\t\t\t.putInt\t\t\t(varyingAddress,\t-1);\n\t\tvaryingShouldCull\t.putInt\t\t\t(varyingAddress,\tcullingProgramDispatcher.shouldCull() ? 1 : 0);\n\t\ttransformOverride\t.uploadVarying\t(varyingAddress,\t0);\n\n\t\tfor (var i = 0; i < size; i ++) {\n\t\t\tvaryingOffset.at(i).putInt(varyingAddress, i);\n\t\t}\n\n\t\telementSegment.countElements(mode.indexCount(size));\n\t\tvertexCount += size;\n\t}\n\n\t@Override\n\tpublic void addServerMesh(\n\t\t\tServerMesh\tserverMesh,\n\t\t\tint\t\t\tcolor,\n\t\t\tint\t\t\tlight,\n\t\t\tint\t\t\toverlay\n\t) {\n\t\tif (CoreFeature.shouldUploadMeshImmediately()) {\n\t\t\tvar meshSize\t\t= serverMesh\t.size\t();\n\t\t\tvar vertexAddress\t= vertexBuffer\t.reserve(getVertexSize\t() * meshSize);\n\t\t\tvar varyingAddress\t= varyingBuffer\t.reserve(getVaryingSize\t() * meshSize);\n\n\t\t\tcolorOffset\t\t\t.putInt\t\t\t(vertexAddress,\t\tFastColor.ABGR32.fromArgb32(color));\n\t\t\tuv1Offset\t\t\t.putInt\t\t\t(vertexAddress,\t\toverlay);\n\t\t\tuv2Offset\t\t\t.putInt\t\t\t(vertexAddress,\t\tlight);\n\n\t\t\tvaryingSharing\t\t.putInt\t\t\t(varyingAddress,\tactiveSharing);\n\t\t\tvaryingMesh\t\t\t.putInt\t\t\t(varyingAddress,\tserverMesh\t\t\t\t.offset\t\t());\n\t\t\tvaryingShouldCull\t.putInt\t\t\t(varyingAddress,\tcullingProgramDispatcher.shouldCull\t() ? 1 : 0);\n\t\t\ttransformOverride\t.uploadVarying\t(varyingAddress,\t0);\n\n\t\t\tfor (var i = 0; i < meshSize; i ++) {\n\t\t\t\tvaryingOffset.at(i).putInt(varyingAddress, i);\n\t\t\t}\n\n\t\t\telementSegment.countElements(mode.indexCount(meshSize));\n\t\t\tvertexCount += meshSize;\n\n\t\t\treturn;\n\t\t}\n\n\t\tvar meshSize\t\t= serverMesh\t.size\t();\n\t\tvar meshUploader\t= meshUploaders\t.get\t(serverMesh);\n\n\t\tif (meshUploader == null) {\n\t\t\tmeshUploader = buffer\t.getMeshUploader\t\t();\n\t\t\tmeshUploader\t\t\t.setServerMesh\t\t\t(serverMesh);\n\t\t\tmeshUploader\t\t\t.setUploadingOverride\t(uploadingOverride);\n\t\t\tmeshUploaders\t\t\t.put\t\t\t\t\t(serverMesh, meshUploader);\n\t\t}\n\n\t\telementSegment.countElements(mode.indexCount(meshSize));\n\t\tmeshVertexCount += meshSize;\n\n\t\tmeshUploader.addUpload(\n\t\t\t\tcolor,\n\t\t\t\tlight,\n\t\t\t\toverlay,\n\t\t\t\tactiveSharing,\n\t\t\t\tcullingProgramDispatcher.shouldCull() ? 1 : 0\n\t\t);\n\t}\n\n\t@Override\n\tpublic <T> void doRender(\n\t\t\tIAcceleratedRenderer<T>\trenderer,\n\t\t\tT\t\t\t\t\t\tcontext,\n\t\t\tMatrix4f\t\t\t\ttransform,\n\t\t\tMatrix3f\t\t\t\tnormal,\n\t\t\tint\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\t\tcolor\n\t) {\n\t\trenderer.render(\n\t\t\t\tthis,\n\t\t\t\tcontext,\n\t\t\t\ttransform,\n\t\t\t\tnormal,\n\t\t\t\tlight,\n\t\t\t\toverlay,\n\t\t\t\tcolor\n\t\t);\n\t}\n\n\t@Override\n\tpublic VertexConsumer decorate(VertexConsumer buffer) {\n\t\treturn buffer;\n\t}\n\n\t@Override\n\tpublic boolean isAccelerated() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic RenderType getRenderType() {\n\t\treturn renderType;\n\t}\n\n\t@Override\n\tpublic long getAsLong() {\n\t\treturn getVaryingSize();\n\t}\n\n\tpublic long getVaryingSize() {\n\t\treturn transformOverride.getVaryingSize();\n\t}\n\n\tpublic int getTotalVertexCount() {\n\t\treturn vertexCount + meshVertexCount;\n\t}\n\n\tpublic boolean isEmpty() {\n\t\treturn getTotalVertexCount() == 0;\n\t}\n\n\tpublic void setOutdated() {\n\t\toutdated = true;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/AcceleratedEntityOutlineGenerator.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders;\n\nimport com.github.argon4w.acceleratedrendering.core.meshes.ServerMesh;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.AllArgsConstructor;\nimport lombok.EqualsAndHashCode;\nimport lombok.experimental.ExtensionMethod;\n\nimport java.nio.ByteBuffer;\n\n\n@AllArgsConstructor\n@EqualsAndHashCode\t(callSuper = false)\n@ExtensionMethod\t(VertexConsumerExtension.class)\npublic class AcceleratedEntityOutlineGenerator extends AcceleratedVertexConsumerWrapper {\n\n\tprivate final VertexConsumer\tdelegate;\n\tprivate final int\t\t\t\tcolor;\n\n\t@Override\n\tpublic VertexConsumer getDelegate() {\n\t\treturn delegate;\n\t}\n\n\t@Override\n\tpublic VertexConsumer decorate(VertexConsumer buffer) {\n\t\treturn new AcceleratedEntityOutlineGenerator(\n\t\t\t\tgetDelegate\t\t\t\t()\n\t\t\t\t\t\t.getAccelerated\t()\n\t\t\t\t\t\t.decorate\t\t(buffer),\n\t\t\t\tcolor\n\t\t);\n\t}\n\n\t@Override\n\tpublic void addClientMesh(\n\t\t\tByteBuffer meshBuffer,\n\t\t\tint\t\t\tsize,\n\t\t\tint\t\t\tcolor,\n\t\t\tint\t\t\tlight,\n\t\t\tint\t\t\toverlay\n\t) {\n\t\tgetDelegate\t\t\t\t()\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.addClientMesh\t(\n\t\t\t\t\t\tmeshBuffer,\n\t\t\t\t\t\tsize,\n\t\t\t\t\t\tthis.color,\n\t\t\t\t\t\tlight,\n\t\t\t\t\t\toverlay\n\t\t\t\t);\n\t}\n\n\t@Override\n\tpublic void addServerMesh(\n\t\t\tServerMesh serverMesh,\n\t\t\tint\t\t\tcolor,\n\t\t\tint\t\t\tlight,\n\t\t\tint\t\t\toverlay\n\t) {\n\t\tgetDelegate\t\t\t\t()\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.addServerMesh\t(\n\t\t\t\t\t\tserverMesh,\n\t\t\t\t\t\tthis.color,\n\t\t\t\t\t\tlight,\n\t\t\t\t\t\toverlay\n\t\t\t\t);\n\t}\n\n\t@Override\n\tpublic VertexConsumer addVertex(\n\t\t\tfloat pX,\n\t\t\tfloat pY,\n\t\t\tfloat pZ\n\t) {\n\t\tdelegate.addVertex(\n\t\t\t\tpX,\n\t\t\t\tpY,\n\t\t\t\tpZ\n\t\t).setColor(color);\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer addVertex(\n\t\t\tPoseStack.Pose\tpPose,\n\t\t\tfloat\t\t\tpX,\n\t\t\tfloat\t\t\tpY,\n\t\t\tfloat\t\t\tpZ\n\t) {\n\t\tdelegate.addVertex(\n\t\t\t\tpPose,\n\t\t\t\tpX,\n\t\t\t\tpY,\n\t\t\t\tpZ\n\t\t).setColor(color);\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setColor(\n\t\t\tint pRed,\n\t\t\tint pGreen,\n\t\t\tint pBlue,\n\t\t\tint pAlpha\n\t) {\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setUv1(int pU, int pV) {\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setUv2(int pU, int pV) {\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setNormal(\n\t\t\tfloat pNormalX,\n\t\t\tfloat pNormalY,\n\t\t\tfloat pNormalZ\n\t) {\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setNormal(\n\t\t\tPoseStack.Pose\tpPose,\n\t\t\tfloat\t\t\tpNormalX,\n\t\t\tfloat\t\t\tpNormalY,\n\t\t\tfloat\t\t\tpNormalZ\n\t) {\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic void addVertex(\n\t\t\tfloat\tx,\n\t\t\tfloat\ty,\n\t\t\tfloat\tz,\n\t\t\tint\t\tcolor,\n\t\t\tfloat\tu,\n\t\t\tfloat\tv,\n\t\t\tint\t\tpackedOverlay,\n\t\t\tint\t\tpackedLight,\n\t\t\tfloat\tnormalX,\n\t\t\tfloat\tnormalY,\n\t\t\tfloat\tnormalZ\n\t) {\n\t\tgetDelegate().addVertex(\n\t\t\t\tx,\n\t\t\t\ty,\n\t\t\t\tz,\n\t\t\t\tthis.color,\n\t\t\t\tu,\n\t\t\t\tv,\n\t\t\t\tpackedOverlay,\n\t\t\t\tpackedLight,\n\t\t\t\tnormalX,\n\t\t\t\tnormalY,\n\t\t\t\tnormalZ\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/AcceleratedSheetedDecalTextureGenerator.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders;\n\nimport com.github.argon4w.acceleratedrendering.core.meshes.ServerMesh;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.EqualsAndHashCode;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.core.Direction;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.joml.Vector3f;\n\nimport java.nio.ByteBuffer;\n\n@ExtensionMethod\t(VertexConsumerExtension.class)\n@EqualsAndHashCode\t(\n\t\tonlyExplicitlyIncluded\t= true,\n\t\tcallSuper\t\t\t\t= false\n)\npublic class AcceleratedSheetedDecalTextureGenerator extends AcceleratedVertexConsumerWrapper {\n\n\t@EqualsAndHashCode.Include private\tfinal\tVertexConsumer\tdelegate;\n\t@EqualsAndHashCode.Include private\tfinal\tMatrix4f\t\tcameraInverse;\n\tprivate                             final\tMatrix3f\t\tnormalInverse;\n\tprivate\t\t\t\t\t\t\t\tfinal\tfloat\t\t\ttextureScale;\n\n\tprivate\t\t\t\t\t\t\t\tfinal\tVector3f\t\tcachedCamera;\n\tprivate\t\t\t\t\t\t\t\tfinal\tVector3f\t\tcachedNormal;\n\n\tprivate\t\t\t\t\t\t\t\t\t\tfloat\t\t\tvertexX;\n\tprivate\t\t\t\t\t\t\t\t\t\tfloat\t\t\tvertexY;\n\tprivate\t\t\t\t\t\t\t\t\t\tfloat\t\t\tvertexZ;\n\n\tpublic AcceleratedSheetedDecalTextureGenerator(\n\t\t\tVertexConsumer\tdelegate,\n\t\t\tMatrix4f\t\tcameraInverse,\n\t\t\tMatrix3f\t\tnormalInverse,\n\t\t\tfloat\t\t\ttextureScale\n\t) {\n\t\tthis.delegate\t\t= delegate;\n\t\tthis.cameraInverse\t= cameraInverse;\n\t\tthis.normalInverse\t= normalInverse;\n\t\tthis.textureScale\t= textureScale;\n\n\t\tthis.cachedCamera\t= new Vector3f();\n\t\tthis.cachedNormal\t= new Vector3f();\n\n\t\tthis.vertexX\t\t= 0;\n\t\tthis.vertexY\t\t= 0;\n\t\tthis.vertexZ\t\t= 0;\n\t}\n\n\t@Override\n\tprotected VertexConsumer getDelegate() {\n\t\treturn delegate;\n\t}\n\n\t@Override\n\tpublic VertexConsumer decorate(VertexConsumer buffer) {\n\t\treturn new AcceleratedSheetedDecalTextureGenerator(\n\t\t\t\tgetDelegate\t\t\t\t()\n\t\t\t\t\t\t.getAccelerated\t()\n\t\t\t\t\t\t.decorate\t\t(buffer),\n\t\t\t\tcameraInverse,\n\t\t\t\tnormalInverse,\n\t\t\t\ttextureScale\n\t\t);\n\t}\n\n\t@Override\n\tpublic void addClientMesh(\n\t\t\tByteBuffer\tmeshBuffer,\n\t\t\tint\t\t\tsize,\n\t\t\tint\t\t\tcolor,\n\t\t\tint\t\t\tlight,\n\t\t\tint\t\t\toverlay\n\t) {\n\t\tgetDelegate\t\t\t\t()\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.addClientMesh\t(\n\t\t\t\t\t\tmeshBuffer,\n\t\t\t\t\t\tsize,\n\t\t\t\t\t\t-1,\n\t\t\t\t\t\tlight,\n\t\t\t\t\t\toverlay\n\t\t\t\t);\n\t}\n\n\t@Override\n\tpublic void addServerMesh(\n\t\t\tServerMesh\tserverMesh,\n\t\t\tint\t\t\tcolor,\n\t\t\tint\t\t\tlight,\n\t\t\tint\t\t\toverlay\n\t) {\n\t\tgetDelegate\t\t\t\t()\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.addServerMesh\t(\n\t\t\t\t\t\tserverMesh,\n\t\t\t\t\t\t-1,\n\t\t\t\t\t\tlight,\n\t\t\t\t\t\toverlay\n\t\t\t\t);\n\t}\n\n\t@Override\n\tpublic VertexConsumer addVertex(\n\t\t\tfloat pX,\n\t\t\tfloat pY,\n\t\t\tfloat pZ\n\t) {\n\t\tvertexX = pX;\n\t\tvertexY = pY;\n\t\tvertexZ = pZ;\n\n\t\tdelegate.addVertex(\n\t\t\t\tpX,\n\t\t\t\tpY,\n\t\t\t\tpZ\n\t\t);\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setUv(float pU, float pV) {\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setColor(\n\t\t\tint pRed,\n\t\t\tint pGreen,\n\t\t\tint pBlue,\n\t\t\tint pAlpha\n\t) {\n\t\tdelegate.setColor(-1);\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setNormal(\n\t\t\tfloat pNormalX,\n\t\t\tfloat pNormalY,\n\t\t\tfloat pNormalZ\n\t) {\n\t\tdelegate.setNormal(\n\t\t\t\tpNormalX,\n\t\t\t\tpNormalY,\n\t\t\t\tpNormalZ\n\t\t);\n\n\t\tvar normal\t\t= normalInverse.transform(\n\t\t\t\tpNormalX,\n\t\t\t\tpNormalY,\n\t\t\t\tpNormalZ,\n\t\t\t\tcachedNormal\n\t\t);\n\n\t\tvar camera\t\t= cameraInverse.transformPosition(\n\t\t\t\tvertexX,\n\t\t\t\tvertexY,\n\t\t\t\tvertexZ,\n\t\t\t\tcachedCamera\n\t\t);\n\n\t\tvar direction\t= Direction.getNearest(\n\t\t\t\tnormal.x(),\n\t\t\t\tnormal.y(),\n\t\t\t\tnormal.z()\n\t\t);\n\n\t\tcamera\t.rotateY((float) \tMath.PI);\n\t\tcamera\t.rotateX((float) (-\tMath.PI / 2));\n\t\tcamera\t.rotate\t(direction.getRotation());\n\n\t\tdelegate.setUv\t(-camera.x() * textureScale, -camera.y() * textureScale);\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic void addVertex(\n\t\t\tfloat\tx,\n\t\t\tfloat\ty,\n\t\t\tfloat\tz,\n\t\t\tint\t\tcolor,\n\t\t\tfloat\tu,\n\t\t\tfloat\tv,\n\t\t\tint\t\tpackedOverlay,\n\t\t\tint\t\tpackedLight,\n\t\t\tfloat\tnormalX,\n\t\t\tfloat\tnormalY,\n\t\t\tfloat\tnormalZ\n\t) {\n\t\tthis\n\t\t\t\t.addVertex\t(x,\t\t\ty,\t\t\tz)\n\t\t\t\t.setColor\t(color)\n\t\t\t\t.setUv\t\t(u,\t\t\tv)\n\t\t\t\t.setOverlay\t(packedOverlay)\n\t\t\t\t.setLight\t(packedLight)\n\t\t\t\t.setNormal\t(normalX,\tnormalY,\tnormalZ);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/AcceleratedSpriteCoordinateExpander.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders;\n\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.AllArgsConstructor;\nimport lombok.EqualsAndHashCode;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\n\n@AllArgsConstructor\n@EqualsAndHashCode\t(callSuper = false)\n@ExtensionMethod\t(VertexConsumerExtension.class)\npublic class AcceleratedSpriteCoordinateExpander extends AcceleratedVertexConsumerWrapper {\n\n\tprivate final VertexConsumer\t\tdelegate;\n\tprivate final TextureAtlasSprite\tsprite;\n\n\t@Override\n\tpublic VertexConsumer getDelegate() {\n\t\treturn delegate;\n\t}\n\n\t@Override\n\tpublic VertexConsumer decorate(VertexConsumer buffer) {\n\t\treturn new AcceleratedSpriteCoordinateExpander(\n\t\t\t\tgetDelegate\t\t\t\t()\n\t\t\t\t\t\t.getAccelerated\t()\n\t\t\t\t\t\t.decorate\t\t(buffer),\n\t\t\t\tsprite\n\t\t);\n\t}\n\n\t@Override\n\tpublic VertexConsumer setUv(float pU, float pV) {\n\t\tdelegate.setUv(\n\t\t\t\tsprite.getU(pU),\n\t\t\t\tsprite.getV(pV)\n\t\t);\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic void addVertex(\n\t\t\tfloat\tpX,\n\t\t\tfloat\tpY,\n\t\t\tfloat\tpZ,\n\t\t\tint\t\tpColor,\n\t\t\tfloat\tpU,\n\t\t\tfloat\tpV,\n\t\t\tint\t\tpPackedOverlay,\n\t\t\tint\t\tpPackedLight,\n\t\t\tfloat\tpNormalX,\n\t\t\tfloat\tpNormalY,\n\t\t\tfloat\tpNormalZ\n\t) {\n\t\tdelegate.addVertex(\n\t\t\t\tpX,\n\t\t\t\tpY,\n\t\t\t\tpZ,\n\t\t\t\tpColor,\n\t\t\t\tsprite.getU(pU),\n\t\t\t\tsprite.getV(pV),\n\t\t\t\tpPackedOverlay,\n\t\t\t\tpPackedLight,\n\t\t\t\tpNormalX,\n\t\t\t\tpNormalY,\n\t\t\t\tpNormalZ\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/AcceleratedVertexConsumerWrapper.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout;\nimport com.github.argon4w.acceleratedrendering.core.meshes.ServerMesh;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.RenderType;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\nimport java.nio.ByteBuffer;\n\n@ExtensionMethod(VertexConsumerExtension.class)\npublic abstract class AcceleratedVertexConsumerWrapper implements IAcceleratedVertexConsumer, VertexConsumer {\n\n\t@Override\n\tpublic\t\tabstract VertexConsumer decorate\t(VertexConsumer buffer);\n\tprotected\tabstract VertexConsumer getDelegate\t();\n\n\t@Override\n\tpublic void beginTransform(Matrix4f transform, Matrix3f normal) {\n\t\tgetDelegate\t\t\t\t()\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.beginTransform\t(transform, normal);\n\t}\n\n\t@Override\n\tpublic void endTransform() {\n\t\tgetDelegate()\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.endTransform\t();\n\t}\n\n\t@Override\n\tpublic boolean isAccelerated() {\n\t\treturn getDelegate\t\t()\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.isAccelerated\t();\n\t}\n\n\t@Override\n\tpublic RenderType getRenderType() {\n\t\treturn getDelegate\t\t()\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.getRenderType\t();\n\t}\n\n\t@Override\n\tpublic VertexLayout getLayout() {\n\t\treturn getDelegate\t\t()\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.getLayout\t\t();\n\t}\n\n\t@Override\n\tpublic int getPolygonSize() {\n\t\treturn getDelegate\t\t()\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.getPolygonSize\t();\n\t}\n\n\t@Override\n\tpublic void addClientMesh(\n\t\t\tByteBuffer meshBuffer,\n\t\t\tint\t\t\tsize,\n\t\t\tint\t\t\tcolor,\n\t\t\tint\t\t\tlight,\n\t\t\tint\t\t\toverlay\n\t) {\n\t\tgetDelegate\t\t\t\t()\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.addClientMesh\t(\n\t\t\t\t\t\tmeshBuffer,\n\t\t\t\t\t\tsize,\n\t\t\t\t\t\tcolor,\n\t\t\t\t\t\tlight,\n\t\t\t\t\t\toverlay\n\t\t\t\t);\n\t}\n\n\t@Override\n\tpublic void addServerMesh(\n\t\t\tServerMesh\tserverMesh,\n\t\t\tint\t\t\tcolor,\n\t\t\tint\t\t\tlight,\n\t\t\tint\t\t\toverlay\n\t) {\n\t\tgetDelegate\t\t\t\t()\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.addServerMesh\t(\n\t\t\t\t\t\tserverMesh,\n\t\t\t\t\t\tcolor,\n\t\t\t\t\t\tlight,\n\t\t\t\t\t\toverlay\n\t\t\t\t);\n\t}\n\n\t@Override\n\tpublic <T> void doRender(\n\t\t\tIAcceleratedRenderer<T> renderer,\n\t\t\tT\t\t\t\t\t\tcontext,\n\t\t\tMatrix4f\t\t\t\ttransform,\n\t\t\tMatrix3f\t\t\t\tnormal,\n\t\t\tint\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\t\tcolor\n\t) {\n\t\trenderer.render(\n\t\t\t\tthis,\n\t\t\t\tcontext,\n\t\t\t\ttransform,\n\t\t\t\tnormal,\n\t\t\t\tlight,\n\t\t\t\toverlay,\n\t\t\t\tcolor\n\t\t);\n\t}\n\n\t@Override\n\tpublic VertexConsumer addVertex(\n\t\t\tfloat x,\n\t\t\tfloat y,\n\t\t\tfloat z\n\t) {\n\t\tgetDelegate().addVertex(\n\t\t\t\tx,\n\t\t\t\ty,\n\t\t\t\tz\n\t\t);\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer addVertex(\n\t\t\tPoseStack.Pose\tpose,\n\t\t\tfloat\t\t\tx,\n\t\t\tfloat\t\t\ty,\n\t\t\tfloat\t\t\tz\n\t) {\n\t\tgetDelegate().addVertex(\n\t\t\t\tpose,\n\t\t\t\tx,\n\t\t\t\ty,\n\t\t\t\tz\n\t\t);\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setColor(\n\t\t\tint red,\n\t\t\tint green,\n\t\t\tint blue,\n\t\t\tint alpha\n\t) {\n\t\tgetDelegate().setColor(\n\t\t\t\tred,\n\t\t\t\tgreen,\n\t\t\t\tblue,\n\t\t\t\talpha\n\t\t);\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setUv(float u, float v) {\n\t\tgetDelegate().setUv(u, v);\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setUv1(int u, int v) {\n\t\tgetDelegate().setUv1(u, v);\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setUv2(int u, int v) {\n\t\tgetDelegate().setUv2(u, v);\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setNormal(\n\t\t\tfloat normalX,\n\t\t\tfloat normalY,\n\t\t\tfloat normalZ\n\t) {\n\t\tgetDelegate().setNormal(\n\t\t\t\tnormalX,\n\t\t\t\tnormalY,\n\t\t\t\tnormalZ\n\t\t);\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setNormal(\n\t\t\tPoseStack.Pose\tpose,\n\t\t\tfloat\t\t\tnormalX,\n\t\t\tfloat\t\t\tnormalY,\n\t\t\tfloat\t\t\tnormalZ\n\t) {\n\t\tgetDelegate().setNormal(\n\t\t\t\tpose,\n\t\t\t\tnormalX,\n\t\t\t\tnormalY,\n\t\t\t\tnormalZ\n\t\t);\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic void addVertex(\n\t\t\tfloat\tx,\n\t\t\tfloat\ty,\n\t\t\tfloat\tz,\n\t\t\tint\t\tcolor,\n\t\t\tfloat\tu,\n\t\t\tfloat\tv,\n\t\t\tint\t\tpackedOverlay,\n\t\t\tint\t\tpackedLight,\n\t\t\tfloat\tnormalX,\n\t\t\tfloat\tnormalY,\n\t\t\tfloat\tnormalZ\n\t) {\n\t\tgetDelegate().addVertex(\n\t\t\t\tx,\n\t\t\t\ty,\n\t\t\t\tz,\n\t\t\t\tcolor,\n\t\t\t\tu,\n\t\t\t\tv,\n\t\t\t\tpackedOverlay,\n\t\t\t\tpackedLight,\n\t\t\t\tnormalX,\n\t\t\t\tnormalY,\n\t\t\t\tnormalZ\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/BufferSourceExtension.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders;\n\nimport net.minecraft.client.renderer.MultiBufferSource;\n\npublic class BufferSourceExtension {\n\n\tpublic static IAcceleratableBufferSource getAcceleratable(MultiBufferSource in) {\n\t\treturn (IAcceleratableBufferSource) in;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/IAcceleratableBufferSource.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAcceleratedBufferSource;\n\nimport java.util.function.Supplier;\n\npublic interface IAcceleratableBufferSource {\n\n\tSupplier<IAcceleratedBufferSource>\tgetBoundAcceleratedBufferSource\t();\n\tboolean\t\t\t\t\t\t\t\tisBufferSourceAcceleratable\t\t();\n\tvoid\t\t\t\t\t\t\t\tbindAcceleratedBufferSource\t\t(Supplier<IAcceleratedBufferSource> bufferSource);\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/IAcceleratedVertexConsumer.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IBufferDecorator;\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout;\nimport com.github.argon4w.acceleratedrendering.core.meshes.ServerMesh;\nimport com.github.argon4w.acceleratedrendering.core.utils.TextureUtils;\nimport com.mojang.blaze3d.platform.NativeImage;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport net.minecraft.client.renderer.RenderType;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\nimport java.nio.ByteBuffer;\n\npublic interface IAcceleratedVertexConsumer extends IBufferDecorator, IBufferGraph {\n\n\t@Override\n\tdefault VertexConsumer decorate(VertexConsumer buffer) {\n\t\tthrow new UnsupportedOperationException(\"Unsupported Operation.\");\n\t}\n\n\tdefault void beginTransform(Matrix4f transform,\tMatrix3f normal) {\n\t\tthrow new UnsupportedOperationException(\"Unsupported Operation.\");\n\t}\n\n\tdefault void endTransform() {\n\t\tthrow new UnsupportedOperationException(\"Unsupported Operation.\");\n\t}\n\n\tdefault boolean isAccelerated() {\n\t\tthrow new UnsupportedOperationException(\"Unsupported Operation.\");\n\t}\n\n\tdefault RenderType getRenderType() {\n\t\tthrow new UnsupportedOperationException(\"Unsupported Operation.\");\n\t}\n\n\tdefault VertexLayout getLayout() {\n\t\tthrow new UnsupportedOperationException(\"Unsupported Operation.\");\n\t}\n\n\tdefault int getPolygonSize() {\n\t\tthrow new UnsupportedOperationException(\"Unsupported Operation.\");\n\t}\n\n\tdefault NativeImage downloadTexture() {\n\t\treturn TextureUtils.downloadTexture(getRenderType(), 0);\n\t}\n\n\tdefault <T> void doRender(\n\t\t\tIAcceleratedRenderer<T>\trenderer,\n\t\t\tT\t\t\t\t\t\tcontext,\n\t\t\tMatrix4f\t\t\t\ttransform,\n\t\t\tMatrix3f\t\t\t\tnormal,\n\t\t\tint\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\t\tcolor\n\t) {\n\t\tthrow new UnsupportedOperationException(\"Unsupported Operation.\");\n\t}\n\n\tdefault void addClientMesh(\n\t\t\tByteBuffer\tmeshBuffer,\n\t\t\tint\t\t\tsize,\n\t\t\tint\t\t\tcolor,\n\t\t\tint\t\t\tlight,\n\t\t\tint\t\t\toverlay\n\t) {\n\t\tthrow new UnsupportedOperationException(\"Unsupported Operation.\");\n\t}\n\n\tdefault void addServerMesh(\n\t\t\tServerMesh\tserverMesh,\n\t\t\tint\t\t\tcolor,\n\t\t\tint\t\t\tlight,\n\t\t\tint\t\t\toverlay\n\t) {\n\t\tthrow new UnsupportedOperationException(\"Unsupported Operation.\");\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/IBufferGraph.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders;\n\npublic interface IBufferGraph {\n\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/VertexConsumerExtension.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAccelerationHolder;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\n\npublic class VertexConsumerExtension {\n\n\tpublic static IAcceleratedVertexConsumer getAccelerated(VertexConsumer in) {\n\t\treturn (IAcceleratedVertexConsumer) in;\n\t}\n\n\tpublic static IAccelerationHolder getHolder(VertexConsumer in) {\n\t\treturn (IAccelerationHolder) in;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/LayerDrawType.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers;\n\npublic enum LayerDrawType {\n\n\tTRANSLUCENT,\n\tOPAQUE,\n\tALL\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/LayerKey.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers;\n\nimport net.minecraft.client.renderer.RenderType;\n\npublic record LayerKey(int layer, RenderType renderType) {\n\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/functions/CustomLayerFunction.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.functions;\n\nimport it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet;\n\nimport java.util.Set;\nimport java.util.function.Consumer;\n\npublic class CustomLayerFunction implements ILayerFunction, Consumer<Runnable> {\n\n\tprivate final Set<Runnable> before;\n\tprivate final Set<Runnable> after;\n\n\tpublic CustomLayerFunction() {\n\t\tthis.before\t= new ReferenceLinkedOpenHashSet<>();\n\t\tthis.after\t= new ReferenceLinkedOpenHashSet<>();\n\t}\n\n\t@Override\n\tpublic void addBefore(Runnable before) {\n\t\tthis.before.add(before);\n\t}\n\n\t@Override\n\tpublic void addAfter(Runnable after) {\n\t\tthis.after.add(after);\n\t}\n\n\t@Override\n\tpublic void runBefore() {\n\t\tbefore.forEach(this);\n\t}\n\n\t@Override\n\tpublic void runAfter() {\n\t\tafter.forEach(this);\n\t}\n\n\t@Override\n\tpublic void reset() {\n\t\tbefore\t.clear();\n\t\tafter\t.clear();\n\t}\n\n\t@Override\n\tpublic void accept(Runnable runnable) {\n\t\trunnable.run();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/functions/EmptyLayerFunction.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.functions;\n\npublic class EmptyLayerFunction implements ILayerFunction {\n\n\tpublic static final ILayerFunction INSTANCE = new EmptyLayerFunction();\n\n\t@Override\n\tpublic void addBefore(Runnable before) {\n\n\t}\n\n\t@Override\n\tpublic void addAfter(Runnable after) {\n\n\t}\n\n\t@Override\n\tpublic void runBefore() {\n\n\t}\n\n\t@Override\n\tpublic void runAfter() {\n\n\t}\n\n\t@Override\n\tpublic void reset() {\n\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/functions/ILayerFunction.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.functions;\n\npublic interface ILayerFunction {\n\n\tvoid addBefore\t(Runnable before);\n\tvoid addAfter\t(Runnable after);\n\tvoid runBefore\t();\n\tvoid runAfter\t();\n\tvoid reset\t\t();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/storage/ILayerContexts.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.DrawContextPool;\n\npublic interface ILayerContexts extends Iterable<DrawContextPool.DrawContext> {\n\n\tvoid\tadd\t\t(DrawContextPool.DrawContext drawContext);\n\tvoid\treset\t();\n\tvoid\tprepare\t();\n\tboolean\tisEmpty\t();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/storage/ILayerStorage.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType;\n\npublic interface ILayerStorage {\n\n\tILayerContexts\tget\t\t(LayerDrawType type);\n\tvoid\t\t\treset\t();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/storage/LayerStorageType.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.sorted.SortedLayerStorage;\n\npublic enum LayerStorageType {\n\n\tSORTED,\n\tSEPARATED;\n\n\tpublic ILayerStorage create(int size) {\n\t\treturn create(this, size);\n\t}\n\n\tpublic static ILayerStorage create(LayerStorageType type, int size) {\n\t\treturn switch (type) {\n\t\t\tcase SORTED\t\t-> new SortedLayerStorage\t(size);\n\t\t\tcase SEPARATED\t-> new SeparatedLayerStorage(size);\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/storage/SeparatedLayerStorage.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.DrawContextPool;\nimport com.google.common.collect.Iterators;\n\nimport java.util.Iterator;\n\npublic class SeparatedLayerStorage implements ILayerStorage {\n\n\tprivate final ILayerContexts[]\tcontexts;\n\tprivate final ILayerContexts\topaqueContexts;\n\tprivate final ILayerContexts\ttranslucentContexts;\n\n\tpublic SeparatedLayerStorage(int size) {\n\t\tthis.contexts\t\t\t\t= new ILayerContexts\t\t[3];\n\t\tthis.opaqueContexts\t\t\t= new SimpleLayerContexts\t(size);\n\t\tthis.translucentContexts\t= new SimpleLayerContexts\t(size);\n\n\t\tcontexts[0] = this.translucentContexts;\n\t\tcontexts[1] = this.opaqueContexts;\n\t\tcontexts[2] = new AllContexts();\n\t}\n\n\t@Override\n\tpublic ILayerContexts get(LayerDrawType type) {\n\t\treturn contexts[type.ordinal()];\n\t}\n\n\t@Override\n\tpublic void reset() {\n\t\topaqueContexts\t\t.reset();\n\t\ttranslucentContexts\t.reset();\n\t}\n\n\tpublic class AllContexts implements ILayerContexts {\n\n\t\t@Override\n\t\tpublic void add(DrawContextPool.DrawContext drawContext) {\n\t\t\tthrow new UnsupportedOperationException(\"Unsupported Operation.\");\n\t\t}\n\n\t\t@Override\n\t\tpublic void reset() {\n\t\t\topaqueContexts\t\t.reset();\n\t\t\ttranslucentContexts\t.reset();\n\t\t}\n\n\t\t@Override\n\t\tpublic void prepare() {\n\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isEmpty() {\n\t\t\treturn\t\topaqueContexts\t\t.isEmpty()\n\t\t\t\t\t&&\ttranslucentContexts\t.isEmpty();\n\t\t}\n\n\t\t@Override\n\t\tpublic Iterator<DrawContextPool.DrawContext> iterator() {\n\t\t\treturn Iterators.concat(\n\t\t\t\t\topaqueContexts\t\t.iterator(),\n\t\t\t\t\ttranslucentContexts\t.iterator()\n\t\t\t);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/storage/SimpleLayerContexts.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.DrawContextPool;\nimport it.unimi.dsi.fastutil.objects.ReferenceArrayList;\n\nimport java.util.Iterator;\n\npublic class SimpleLayerContexts implements ILayerContexts {\n\n\tprotected final ReferenceArrayList<DrawContextPool.DrawContext> contexts;\n\n\tpublic SimpleLayerContexts(int size) {\n\t\tcontexts = new ReferenceArrayList<>(size);\n\t}\n\n\t@Override\n\tpublic void add(DrawContextPool.DrawContext drawContext) {\n\t\tcontexts.add(drawContext);\n\t}\n\n\t@Override\n\tpublic void reset() {\n\t\tcontexts.clear();\n\t}\n\n\t@Override\n\tpublic void prepare() {\n\n\t}\n\n\t@Override\n\tpublic boolean isEmpty() {\n\t\treturn contexts.isEmpty();\n\t}\n\n\t@Override\n\tpublic Iterator<DrawContextPool.DrawContext> iterator() {\n\t\treturn contexts.iterator();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/storage/empty/EmptyLayerContexts.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.empty;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.ILayerContexts;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.DrawContextPool;\nimport com.github.argon4w.acceleratedrendering.core.utils.EmptyIterator;\n\nimport java.util.Iterator;\n\npublic class EmptyLayerContexts implements ILayerContexts {\n\n\tpublic static final EmptyLayerContexts INSTANCE = new EmptyLayerContexts();\n\n\t@Override\n\tpublic void add(DrawContextPool.DrawContext drawContext) {\n\n\t}\n\n\t@Override\n\tpublic void reset() {\n\n\t}\n\n\t@Override\n\tpublic void prepare() {\n\n\t}\n\n\t@Override\n\tpublic boolean isEmpty() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic Iterator<DrawContextPool.DrawContext> iterator() {\n\t\treturn EmptyIterator.of();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/storage/empty/EmptyLayerStorage.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.empty;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.ILayerContexts;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.ILayerStorage;\n\npublic class EmptyLayerStorage implements ILayerStorage {\n\n\tpublic static final EmptyLayerStorage INSTANCE = new EmptyLayerStorage();\n\n\t@Override\n\tpublic ILayerContexts get(LayerDrawType type) {\n\t\treturn EmptyLayerContexts.INSTANCE;\n\t}\n\n\t@Override\n\tpublic void reset() {\n\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/storage/sorted/SortedLayerContexts.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.sorted;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.SimpleLayerContexts;\n\nimport java.util.Comparator;\n\npublic class SortedLayerContexts extends SimpleLayerContexts {\n\n\tpublic SortedLayerContexts(int size) {\n\t\tsuper(size);\n\t}\n\n\t@Override\n\tpublic void prepare() {\n\t\tcontexts.sort(Comparator.naturalOrder());\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/storage/sorted/SortedLayerStorage.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.sorted;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.ILayerContexts;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.ILayerStorage;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.SimpleLayerContexts;\n\npublic class SortedLayerStorage implements ILayerStorage {\n\n\tprivate final SimpleLayerContexts contexts;\n\n\tpublic SortedLayerStorage(int size) {\n\t\tthis.contexts = new SortedLayerContexts(size);\n\t}\n\n\t@Override\n\tpublic ILayerContexts get(LayerDrawType type) {\n\t\treturn contexts;\n\t}\n\n\t@Override\n\tpublic void reset() {\n\t\tcontexts.reset();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/DrawContextPool.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.buffers.MappedBuffer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.IMemoryInterface;\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.SimpleMemoryInterface;\nimport com.github.argon4w.acceleratedrendering.core.utils.SimpleResetPool;\nimport com.mojang.blaze3d.vertex.VertexFormat;\nimport lombok.Getter;\nimport lombok.Setter;\nimport net.minecraft.client.renderer.RenderType;\n\nimport static org.lwjgl.opengl.GL46.*;\n\npublic class DrawContextPool extends SimpleResetPool<DrawContextPool.DrawContext, MappedBuffer> {\n\n\tpublic DrawContextPool(int size) {\n\t\tsuper(size, new MappedBuffer(20L * size));\n\t}\n\n\t@Override\n\tprotected DrawContext create(MappedBuffer buffer, int i) {\n\t\treturn new DrawContext(i);\n\t}\n\n\t@Override\n\tprotected void reset(DrawContext drawContext) {\n\n\t}\n\n\t@Override\n\tprotected void delete(DrawContext drawContext) {\n\n\t}\n\n\t@Override\n\tpublic void delete() {\n\t\tgetContext().delete();\n\t}\n\n\t@Override\n\tpublic DrawContext fail() {\n\t\texpand();\n\t\treturn get();\n\t}\n\n\t@Getter\n\t@Setter\n\tpublic class DrawContext implements Comparable<DrawContext> {\n\n\t\tpublic static\tfinal\tint\t\t\t\t\tELEMENT_COUNT_INDEX\t\t= 0;\n\t\tpublic static\tfinal\tIMemoryInterface\tINDIRECT_COUNT\t\t\t= new SimpleMemoryInterface(0L * 4L, 4);\n\t\tpublic static\tfinal\tIMemoryInterface\tINDIRECT_INSTANCE_COUNT\t= new SimpleMemoryInterface(1L * 4L, 4);\n\t\tpublic static\tfinal\tIMemoryInterface\tINDIRECT_FIRST_INDEX\t= new SimpleMemoryInterface(2L * 4L, 4);\n\t\tpublic static\tfinal\tIMemoryInterface\tINDIRECT_BASE_INDEX\t\t= new SimpleMemoryInterface(3L * 4L, 4);\n\t\tpublic static\tfinal\tIMemoryInterface\tINDIRECT_BASE_INSTANCE\t= new SimpleMemoryInterface(4L * 4L, 4);\n\n\t\tprivate\t\t\tfinal\tlong\t\t\t\tcommandOffset;\n\t\tprivate\t\t\t\t\tRenderType\t\t\trenderType;\n\n\t\tpublic DrawContext(int index) {\n\t\t\tthis.commandOffset\t= index * 20L;\n\t\t\tthis.renderType\t\t= null;\n\n\t\t\tvar address\t\t\t= context\t\t.reserve(20L);\n\n\t\t\tINDIRECT_COUNT\t\t\t\t\t\t.putInt\t(address, 0);\n\t\t\tINDIRECT_INSTANCE_COUNT\t\t\t\t.putInt\t(address, 1);\n\t\t\tINDIRECT_FIRST_INDEX\t\t\t\t.putInt\t(address, 0);\n\t\t\tINDIRECT_BASE_INDEX\t\t\t\t\t.putInt\t(address, 0);\n\t\t\tINDIRECT_BASE_INSTANCE\t\t\t\t.putInt\t(address, 0);\n\t\t}\n\n\t\tpublic void bindComputeBuffers(ElementBufferPool.ElementSegment elementSegmentIn) {\n\t\t\tvar elementOffset\t= elementSegmentIn\t.getOffset\t();\n\t\t\tvar commandAddress\t= context\t\t\t.addressAt\t(commandOffset);\n\n\t\t\tINDIRECT_COUNT\t\t.putInt\t\t(commandAddress, 0);\n\t\t\tINDIRECT_FIRST_INDEX.putInt\t\t(commandAddress, elementOffset / 4);\n\t\t\tcontext\t\t\t\t.bindRange\t(\n\t\t\t\t\tGL_ATOMIC_COUNTER_BUFFER,\n\t\t\t\t\tELEMENT_COUNT_INDEX,\n\t\t\t\t\tcommandOffset,\n\t\t\t\t\t4\n\t\t\t);\n\t\t}\n\n\t\tpublic void drawElements(VertexFormat.Mode mode) {\n\t\t\tglDrawElementsIndirect(\n\t\t\t\t\tmode.asGLMode,\n\t\t\t\t\tGL_UNSIGNED_INT,\n\t\t\t\t\tcommandOffset\n\t\t\t);\n\t\t}\n\n\t\t@Override\n\t\tpublic int compareTo(DrawContext that) {\n\t\t\treturn Boolean.compare(\n\t\t\t\t\tthis.renderType.sortOnUpload,\n\t\t\t\t\tthat.renderType.sortOnUpload\n\t\t\t);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/ElementBufferPool.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.GLConstants;\nimport com.github.argon4w.acceleratedrendering.core.backends.buffers.MutableBuffer;\nimport com.github.argon4w.acceleratedrendering.core.utils.MutableSize;\nimport com.github.argon4w.acceleratedrendering.core.utils.SimpleResetPool;\nimport lombok.Getter;\nimport org.apache.commons.lang3.mutable.MutableLong;\n\nimport static org.lwjgl.opengl.GL44.GL_DYNAMIC_STORAGE_BIT;\n\npublic class ElementBufferPool extends SimpleResetPool<ElementBufferPool.ElementSegment, Void> {\n\n\t@Getter private\tfinal MutableBuffer elementBufferOut;\n\tprivate\t\t\tfinal MutableLong\telementBufferSegments;\n\tprivate\t\t\tfinal MutableLong\telementBufferOutSize;\n\tprivate\t\t\tfinal MutableLong\telementBufferOutUsedSize;\n\n\tpublic ElementBufferPool(int size) {\n\t\tsuper(size, null);\n\n\t\tthis.elementBufferOut\t\t\t= new MutableBuffer\t(64L * size, GL_DYNAMIC_STORAGE_BIT);\n\t\tthis.elementBufferSegments\t\t= new MutableLong\t(0L);\n\t\tthis.elementBufferOutSize\t\t= new MutableLong\t(64L * size);\n\t\tthis.elementBufferOutUsedSize\t= new MutableLong\t(64L * size);\n\t}\n\n\tpublic void prepare() {\n\t\telementBufferOut.resizeTo(elementBufferOutSize.getValue());\n\t}\n\n\t@Override\n\tpublic void reset() {\n\t\telementBufferOutUsedSize.setValue\t(0L);\n\t\telementBufferSegments\t.setValue\t(0L);\n\t\tsuper\t\t\t\t\t.reset\t\t();\n\t}\n\n\t@Override\n\tpublic void delete() {\n\t\telementBufferOut.delete();\n\t}\n\n\t@Override\n\tprotected ElementSegment create(Void value, int i) {\n\t\treturn new ElementSegment();\n\t}\n\n\t@Override\n\tprotected void reset(ElementSegment elementSegment) {\n\t\telementSegment.reset();\n\t}\n\n\t@Override\n\tprotected void delete(ElementSegment elementSegment) {\n\n\t}\n\n\t@Override\n\tpublic boolean test(ElementSegment elementSegment) {\n\t\treturn elementBufferOutUsedSize.addAndGet(elementSegment.getSize()) <= GLConstants.MAX_SHADER_STORAGE_BLOCK_SIZE;\n\t}\n\n\t@Getter\n\tpublic class ElementSegment extends MutableSize {\n\n\t\tprivate long bytes;\n\t\tprivate long offset;\n\n\t\tpublic ElementSegment() {\n\t\t\tsuper(64L);\n\t\t\tthis.bytes\t= 0L;\n\t\t\tthis.offset\t= -1L;\n\t\t}\n\n\t\t@Override\n\t\tpublic void onExpand(long bytes) {\n\t\t\telementBufferOutSize\t.add(bytes);\n\t\t\telementBufferOutUsedSize.add(bytes);\n\t\t}\n\n\t\tprivate void reset() {\n\t\t\tbytes = 0L;\n\t\t}\n\n\t\tpublic void allocateOffset() {\n\t\t\toffset = elementBufferSegments.getAndAdd(size);\n\t\t}\n\n\t\tpublic void countElements(int count) {\n\t\t\tbytes += count * 4L;\n\n\t\t\tif (bytes > size) {\n\t\t\t\tresize(bytes);\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/StagingBufferPool.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.GLConstants;\nimport com.github.argon4w.acceleratedrendering.core.backends.buffers.MappedBuffer;\nimport com.github.argon4w.acceleratedrendering.core.backends.buffers.MutableBuffer;\nimport com.github.argon4w.acceleratedrendering.core.utils.SimpleResetPool;\nimport lombok.Getter;\nimport org.apache.commons.lang3.mutable.MutableLong;\n\nimport static org.lwjgl.opengl.GL44.GL_DYNAMIC_STORAGE_BIT;\n\npublic class StagingBufferPool extends SimpleResetPool<StagingBufferPool.StagingBuffer, Void> {\n\n\t@Getter private\tfinal MutableBuffer\tbufferOut;\n\tprivate\t\t\tfinal MutableLong\tbufferSegments;\n\tprivate\t\t\tfinal MutableLong\tbufferOutSize;\n\tprivate\t\t\tfinal MutableLong\tbufferOutUsedSize;\n\n\tpublic StagingBufferPool(int size) {\n\t\tsuper(size, null);\n\n\t\tthis.bufferOut\t\t\t= new MutableBuffer\t(64L * size, GL_DYNAMIC_STORAGE_BIT);\n\t\tthis.bufferSegments\t\t= new MutableLong\t(0L);\n\t\tthis.bufferOutSize\t\t= new MutableLong\t(64L * size);\n\t\tthis.bufferOutUsedSize\t= new MutableLong\t(0L);\n\t}\n\n\tpublic void prepare() {\n\t\tbufferOut.resizeTo(bufferOutSize.getValue());\n\t}\n\n\t@Override\n\tpublic void delete() {\n\t\tbufferOut\t.delete();\n\t\tsuper\t\t.delete();\n\t}\n\n\t@Override\n\tpublic void reset() {\n\t\tbufferOutUsedSize\t.setValue\t(0L);\n\t\tbufferSegments\t\t.setValue\t(0L);\n\t\tsuper\t\t\t\t.reset\t\t();\n\t}\n\n\t@Override\n\tprotected StagingBuffer create(Void context, int i) {\n\t\treturn new StagingBuffer();\n\t}\n\n\t@Override\n\tprotected void reset(StagingBuffer stagingBuffer) {\n\t\tstagingBuffer.poolReset();\n\t}\n\n\t@Override\n\tprotected void delete(StagingBuffer stagingBuffer) {\n\t\tstagingBuffer.poolDelete();\n\t}\n\n\t@Override\n\tpublic boolean test(StagingBuffer stagingBuffer) {\n\t\treturn bufferOutUsedSize.addAndGet(stagingBuffer.getSize()) <= GLConstants.MAX_SHADER_STORAGE_BLOCK_SIZE;\n\t}\n\n\t@Getter\n\tpublic class StagingBuffer extends MappedBuffer {\n\n\t\tprivate long offset;\n\n\t\tpublic StagingBuffer() {\n\t\t\tsuper(64L);\n\t\t\tthis.offset = -1;\n\t\t}\n\n\t\t@Override\n\t\tpublic void onExpand(long bytes) {\n\t\t\tbufferOutSize\t\t.add(bytes);\n\t\t\tbufferOutUsedSize\t.add(bytes);\n\t\t}\n\n\t\t@Override\n\t\tpublic void delete() {\n\t\t\tthrow new IllegalStateException(\"Pooled buffers cannot be deleted directly.\");\n\t\t}\n\n\t\t@Override\n\t\tpublic void reset() {\n\t\t\tthrow new IllegalStateException(\"Pooled buffers cannot be reset directly.\");\n\t\t}\n\n\t\tprivate void poolDelete() {\n\t\t\tsuper.delete();\n\t\t}\n\n\t\tprivate void poolReset() {\n\t\t\tsuper.reset();\n\t\t}\n\n\t\tpublic void allocateOffset() {\n\t\t\toffset = bufferSegments.getAndAdd(position);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/meshes/FlattenMeshInfoCache.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes;\n\nimport java.lang.invoke.MethodHandles;\nimport java.lang.invoke.VarHandle;\nimport java.util.Arrays;\n\npublic class FlattenMeshInfoCache implements IMeshInfoCache {\n\n\tpublic static final VarHandle\tHANDLE\t\t\t\t= MethodHandles.arrayElementVarHandle(int[].class).withInvokeExactBehavior();\n\tpublic static final int\t\t\tMESH_INFO_SIZE\t\t= 5;\n\tpublic static final int\t\t\tCOLOR_OFFSET\t\t= 0;\n\tpublic static final int\t\t\tLIGHT_OFFSET\t\t= 1;\n\tpublic static final int\t\t\tOVERLAY_OFFSET\t\t= 2;\n\tpublic static final int\t\t\tSHARING_OFFSET\t\t= 3;\n\tpublic static final int\t\t\tSHOULD_CULL_OFFSET\t= 4;\n\n\tprivate\t\t\t\tint[]\t\tcache;\n\tprivate\t\t\t\tint\t\t\tsize;\n\tprivate\t\t\t\tint\t\t\tcount;\n\n\tpublic FlattenMeshInfoCache() {\n\t\tthis.size\t= 128;\n\t\tthis.cache\t= new int[this.size * MESH_INFO_SIZE];\n\t\tthis.count\t= 0;\n\t}\n\n\t@Override\n\tpublic void reset() {\n\t\tcount = 0;\n\t}\n\n\t@Override\n\tpublic void delete() {\n\n\t}\n\n\t@Override\n\tpublic void setup(\n\t\t\tint color,\n\t\t\tint light,\n\t\t\tint overlay,\n\t\t\tint sharing,\n\t\t\tint shouldCull\n\t) {\n\t\tif (count >= size) {\n\t\t\tsize\t= size * 2;\n\t\t\tcache\t= Arrays.copyOf(cache, size * MESH_INFO_SIZE);\n\t\t}\n\n\t\tvar infoIndex = count * MESH_INFO_SIZE;\n\n\t\tHANDLE.set(cache, infoIndex + COLOR_OFFSET,\t\t\tcolor);\n\t\tHANDLE.set(cache, infoIndex + LIGHT_OFFSET,\t\t\tlight);\n\t\tHANDLE.set(cache, infoIndex + OVERLAY_OFFSET,\t\toverlay);\n\t\tHANDLE.set(cache, infoIndex + SHARING_OFFSET,\t\tsharing);\n\t\tHANDLE.set(cache, infoIndex + SHOULD_CULL_OFFSET,\tshouldCull);\n\n\t\tcount ++;\n\t}\n\n\t@Override\n\tpublic int getMeshCount() {\n\t\treturn count;\n\t}\n\n\t@Override\n\tpublic int getSharing(int i) {\n\t\treturn (int) HANDLE.get(cache, i * MESH_INFO_SIZE + SHARING_OFFSET);\n\t}\n\n\t@Override\n\tpublic int getShouldCull(int i) {\n\t\treturn (int) HANDLE.get(cache, i * MESH_INFO_SIZE + SHOULD_CULL_OFFSET);\n\t}\n\n\t@Override\n\tpublic int getColor(int i) {\n\t\treturn (int) HANDLE.get(cache, i * MESH_INFO_SIZE + COLOR_OFFSET);\n\t}\n\n\t@Override\n\tpublic int getLight(int i) {\n\t\treturn (int) HANDLE.get(cache, i * MESH_INFO_SIZE + LIGHT_OFFSET);\n\t}\n\n\t@Override\n\tpublic int getOverlay(int i) {\n\t\treturn (int) HANDLE.get(cache, i * MESH_INFO_SIZE + OVERLAY_OFFSET);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/meshes/IMeshInfoCache.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes;\n\npublic interface IMeshInfoCache {\n\n\tvoid\treset\t\t\t();\n\tvoid\tdelete\t\t\t();\n\tvoid\tsetup\t\t\t(int color, int light, int overlay, int sharing, int shouldCull);\n\tint\t\tgetMeshCount\t();\n\tint\t\tgetSharing\t\t(int i);\n\tint\t\tgetShouldCull\t(int i);\n\tint\t\tgetColor\t\t(int i);\n\tint\t\tgetLight\t\t(int i);\n\tint\t\tgetOverlay\t\t(int i);\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/meshes/MeshInfoCacheType.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes;\n\npublic enum MeshInfoCacheType {\n\n\tSIMPLE,\n\tHANDLE,\n\tUNSAFE;\n\n\tpublic IMeshInfoCache create() {\n\t\treturn create(this);\n\t}\n\n\tpublic static IMeshInfoCache create(MeshInfoCacheType type) {\n\t\treturn switch (type) {\n\t\t\tcase SIMPLE -> new SimpleMeshInfoCache\t\t\t();\n\t\t\tcase HANDLE -> new FlattenMeshInfoCache\t\t\t();\n\t\t\tcase UNSAFE -> new UnsafeMemoryMeshInfoCache\t();\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/meshes/MeshUploaderPool.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.backends.buffers.MappedBuffer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.IMemoryInterface;\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.SimpleDynamicMemoryInterface;\nimport com.github.argon4w.acceleratedrendering.core.meshes.ServerMesh;\nimport com.github.argon4w.acceleratedrendering.core.programs.overrides.IUploadingShaderProgramOverride;\nimport com.github.argon4w.acceleratedrendering.core.utils.SimpleResetPool;\nimport lombok.Getter;\nimport lombok.Setter;\nimport net.minecraft.util.FastColor;\n\nimport java.util.function.LongSupplier;\n\nimport static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BUFFER;\n\npublic class MeshUploaderPool extends SimpleResetPool<MeshUploaderPool.MeshUploader, Void> {\n\n\tpublic MeshUploaderPool() {\n\t\tsuper(128, null);\n\t}\n\n\t@Override\n\tprotected MeshUploader create(Void context, int i) {\n\t\treturn new MeshUploader();\n\t}\n\n\t@Override\n\tprotected void reset(MeshUploader meshUploader) {\n\t\tmeshUploader.reset();\n\t}\n\n\t@Override\n\tprotected void delete(MeshUploader meshUploader) {\n\t\tmeshUploader.delete();\n\t}\n\n\t@Override\n\tpublic MeshUploader fail() {\n\t\texpand();\n\t\treturn get();\n\t}\n\n\tpublic static class MeshUploader implements LongSupplier {\n\n\t\tpublic static\tfinal\tint\t\t\t\t\t\t\t\tMESH_INFO_BUFFER_INDEX\t= 8;\n\n\t\tpublic\t\t\tfinal\tIMemoryInterface\t\t\t\tmeshInfoSharing;\n\t\tpublic\t\t\tfinal\tIMemoryInterface\t\t\t\tmeshInfoNoCull;\n\t\tpublic\t\t\tfinal\tIMemoryInterface\t\t\t\tmeshInfoColor;\n\t\tpublic\t\t\tfinal\tIMemoryInterface\t\t\t\tmeshInfoOverlay;\n\t\tpublic\t\t\tfinal\tIMemoryInterface\t\t\t\tmeshInfoLight;\n\n\t\tprivate\t\t\tfinal\tMappedBuffer \t\t\t\t\tmeshInfoBuffer;\n\t\t@Getter private\tfinal\tIMeshInfoCache\t\t\t\t\tmeshInfos;\n\n\t\t@Getter\t@Setter private\tServerMesh\t\t\t\t\t\tserverMesh;\n\t\t@Getter @Setter private IUploadingShaderProgramOverride\tuploadingOverride;\n\n\t\tpublic MeshUploader() {\n\t\t\tthis.meshInfoSharing\t= new SimpleDynamicMemoryInterface\t(0L * 4L, this);\n\t\t\tthis.meshInfoNoCull\t\t= new SimpleDynamicMemoryInterface\t(1L * 4L, this);\n\t\t\tthis.meshInfoColor\t\t= new SimpleDynamicMemoryInterface\t(2L * 4L, this);\n\t\t\tthis.meshInfoOverlay\t= new SimpleDynamicMemoryInterface\t(3L * 4L, this);\n\t\t\tthis.meshInfoLight\t\t= new SimpleDynamicMemoryInterface\t(4L * 4L, this);\n\n\t\t\tthis.meshInfoBuffer\t\t= new MappedBuffer\t\t\t\t\t(64L);\n\t\t\tthis.meshInfos\t\t\t= CoreFeature.createMeshInfoCache\t();\n\n\t\t\tthis.serverMesh\t\t\t= null;\n\t\t\tthis.uploadingOverride\t= null;\n\t\t}\n\n\t\tpublic void addUpload(\n\t\t\t\tint color,\n\t\t\t\tint light,\n\t\t\t\tint overlay,\n\t\t\t\tint sharing,\n\t\t\t\tint shouldCull\n\t\t) {\n\t\t\tmeshInfos.setup(\n\t\t\t\t\tcolor,\n\t\t\t\t\tlight,\n\t\t\t\t\toverlay,\n\t\t\t\t\tsharing,\n\t\t\t\t\tshouldCull\n\t\t\t);\n\t\t}\n\n\t\tpublic void upload() {\n\t\t\tvar meshCount\t\t\t= meshInfos\t\t.getMeshCount\t();\n\t\t\tvar meshInfoAddress\t\t= meshInfoBuffer.reserve\t\t(getAsLong() * meshCount);\n\n\t\t\tfor (var i = 0; i < meshCount; i ++) {\n\t\t\t\tmeshInfoSharing\t\t.at(i)\t.putInt\t\t\t(meshInfoAddress, meshInfos\t\t\t.getSharing\t\t(i));\n\t\t\t\tmeshInfoNoCull\t\t.at(i)\t.putInt\t\t\t(meshInfoAddress, meshInfos\t\t\t.getShouldCull\t(i));\n\t\t\t\tmeshInfoColor\t\t.at(i)\t.putInt\t\t\t(meshInfoAddress, FastColor.ABGR32\t.fromArgb32\t\t(meshInfos.getColor(i)));\n\t\t\t\tmeshInfoOverlay\t\t.at(i)\t.putInt\t\t\t(meshInfoAddress, meshInfos\t\t\t.getOverlay\t\t(i));\n\t\t\t\tmeshInfoLight\t\t.at(i)\t.putInt\t\t\t(meshInfoAddress, meshInfos\t\t\t.getLight\t\t(i));\n\t\t\t\tuploadingOverride\t\t\t.uploadMeshInfo\t(meshInfoAddress, i);\n\t\t\t}\n\t\t}\n\n\t\tpublic void bindBuffers() {\n\t\t\tmeshInfoBuffer.bindBase(GL_SHADER_STORAGE_BUFFER, MESH_INFO_BUFFER_INDEX);\n\t\t}\n\n\t\tpublic void reset() {\n\t\t\tmeshInfos\t\t.reset();\n\t\t\tmeshInfoBuffer\t.reset();\n\t\t}\n\n\t\tpublic void delete() {\n\t\t\tmeshInfos\t\t.delete();\n\t\t\tmeshInfoBuffer\t.delete();\n\t\t}\n\n\t\t@Override\n\t\tpublic long getAsLong() {\n\t\t\treturn uploadingOverride.getMeshInfoSize();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/meshes/SimpleMeshInfo.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes;\n\nimport com.github.argon4w.acceleratedrendering.core.utils.SimpleCachedArray;\nimport lombok.Getter;\n\n@Getter\npublic class SimpleMeshInfo implements SimpleCachedArray.Element {\n\n\tprivate int color;\n\tprivate int light;\n\tprivate int overlay;\n\tprivate int sharing;\n\tprivate int shouldCull;\n\n\tpublic SimpleMeshInfo() {\n\t\tthis.color\t\t= -1;\n\t\tthis.light\t\t= -1;\n\t\tthis.overlay\t= -1;\n\t\tthis.sharing\t= -1;\n\t}\n\n\tpublic void setupMeshInfo(\n\t\t\tint color,\n\t\t\tint light,\n\t\t\tint overlay,\n\t\t\tint sharing,\n\t\t\tint shouldCull\n\t) {\n\t\tthis.color\t\t= color;\n\t\tthis.light\t\t= light;\n\t\tthis.overlay\t= overlay;\n\t\tthis.sharing\t= sharing;\n\t\tthis.shouldCull\t= shouldCull;\n\t}\n\n\t@Override\n\tpublic void reset() {\n\n\t}\n\n\t@Override\n\tpublic void delete() {\n\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/meshes/SimpleMeshInfoCache.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes;\n\nimport com.github.argon4w.acceleratedrendering.core.utils.SimpleCachedArray;\n\nimport java.util.function.IntFunction;\n\npublic class SimpleMeshInfoCache implements IMeshInfoCache, IntFunction<SimpleMeshInfo> {\n\n\tprivate final SimpleCachedArray<SimpleMeshInfo> meshInfos;\n\n\tpublic SimpleMeshInfoCache() {\n\t\tthis.meshInfos = new SimpleCachedArray<>(128, this);\n\t}\n\n\t@Override\n\tpublic void setup(\n\t\t\tint color,\n\t\t\tint light,\n\t\t\tint overlay,\n\t\t\tint sharing,\n\t\t\tint shouldCull\n\t) {\n\t\tmeshInfos.get().setupMeshInfo(\n\t\t\t\tcolor,\n\t\t\t\tlight,\n\t\t\t\toverlay,\n\t\t\t\tsharing,\n\t\t\t\tshouldCull\n\t\t);\n\t}\n\n\t@Override\n\tpublic void reset() {\n\t\tmeshInfos.reset();\n\t}\n\n\t@Override\n\tpublic void delete() {\n\t\tmeshInfos.delete();\n\t}\n\n\t@Override\n\tpublic int getMeshCount() {\n\t\treturn meshInfos.getCursor();\n\t}\n\n\t@Override\n\tpublic int getSharing(int i) {\n\t\treturn meshInfos.at(i).getSharing();\n\t}\n\n\t@Override\n\tpublic int getShouldCull(int i) {\n\t\treturn meshInfos.at(i).getShouldCull();\n\t}\n\n\t@Override\n\tpublic int getColor(int i) {\n\t\treturn meshInfos.at(i).getColor();\n\t}\n\n\t@Override\n\tpublic int getLight(int i) {\n\t\treturn meshInfos.at(i).getLight();\n\t}\n\n\t@Override\n\tpublic int getOverlay(int i) {\n\t\treturn meshInfos.at(i).getOverlay();\n\t}\n\n\t@Override\n\tpublic SimpleMeshInfo apply(int value) {\n\t\treturn new SimpleMeshInfo();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/meshes/UnsafeMemoryMeshInfoCache.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes;\n\nimport io.netty.util.internal.shaded.org.jctools.util.UnsafeAccess;\nimport sun.misc.Unsafe;\n\npublic class UnsafeMemoryMeshInfoCache implements IMeshInfoCache {\n\n\tpublic static final Unsafe\t\tUNSAFE\t\t\t\t= UnsafeAccess.UNSAFE;\n\tpublic static final long\t\tMESH_INFO_SIZE\t\t= 5L * 4L;\n\tpublic static final long\t\tCOLOR_OFFSET\t\t= 0L * 4L;\n\tpublic static final long\t\tLIGHT_OFFSET\t\t= 1L * 4L;\n\tpublic static final long\t\tOVERLAY_OFFSET\t\t= 2L * 4L;\n\tpublic static final long\t\tSHARING_OFFSET\t\t= 3L * 4L;\n\tpublic static final long\t\tSHOULD_CULL_OFFSET\t= 4L * 4L;\n\n\tprivate\t\t\t\tlong\t\taddress;\n\tprivate\t\t\t\tint\t\t\tsize;\n\tprivate\t\t\t\tint\t\t\tcount;\n\n\tpublic UnsafeMemoryMeshInfoCache() {\n\t\tthis.size\t\t= 128;\n\t\tthis.address\t= UNSAFE.allocateMemory(this.size * MESH_INFO_SIZE);\n\t\tthis.count\t\t= 0;\n\t}\n\n\t@Override\n\tpublic void reset() {\n\t\tcount = 0;\n\t}\n\n\t@Override\n\tpublic void delete() {\n\t\tUNSAFE.freeMemory(address);\n\t}\n\n\t@Override\n\tpublic void setup(\n\t\t\tint color,\n\t\t\tint light,\n\t\t\tint overlay,\n\t\t\tint sharing,\n\t\t\tint shouldCull\n\t) {\n\t\tif (count >= size) {\n\t\t\tsize\t= size * 2;\n\t\t\taddress\t= UNSAFE.reallocateMemory(address, size * MESH_INFO_SIZE);\n\t\t}\n\n\t\tvar infoAddress = address + count * MESH_INFO_SIZE;\n\n\t\tUNSAFE.putInt(infoAddress + COLOR_OFFSET,\t\tcolor);\n\t\tUNSAFE.putInt(infoAddress + LIGHT_OFFSET,\t\tlight);\n\t\tUNSAFE.putInt(infoAddress + OVERLAY_OFFSET,\t\toverlay);\n\t\tUNSAFE.putInt(infoAddress + SHARING_OFFSET,\t\tsharing);\n\t\tUNSAFE.putInt(infoAddress + SHOULD_CULL_OFFSET,\tshouldCull);\n\n\t\tcount ++;\n\t}\n\n\t@Override\n\tpublic int getMeshCount() {\n\t\treturn count;\n\t}\n\n\t@Override\n\tpublic int getSharing(int i) {\n\t\treturn UNSAFE.getInt(address + i * MESH_INFO_SIZE + SHARING_OFFSET);\n\t}\n\n\t@Override\n\tpublic int getShouldCull(int i) {\n\t\treturn UNSAFE.getInt(address + i * MESH_INFO_SIZE + SHOULD_CULL_OFFSET);\n\t}\n\n\t@Override\n\tpublic int getColor(int i) {\n\t\treturn UNSAFE.getInt(address + i * MESH_INFO_SIZE + COLOR_OFFSET);\n\t}\n\n\t@Override\n\tpublic int getLight(int i) {\n\t\treturn UNSAFE.getInt(address + i * MESH_INFO_SIZE + LIGHT_OFFSET);\n\t}\n\n\t@Override\n\tpublic int getOverlay(int i) {\n\t\treturn UNSAFE.getInt(address + i * MESH_INFO_SIZE + OVERLAY_OFFSET);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/renderers/DecoratedRenderer.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers;\n\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.AllArgsConstructor;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\n@AllArgsConstructor\npublic class DecoratedRenderer<T> implements IAcceleratedRenderer<T> {\n\n\tprivate final IAcceleratedRenderer<T>\trenderer;\n\tprivate final IBufferDecorator\t\t\tbufferDecorator;\n\n\t@Override\n\tpublic void render(\n\t\t\tVertexConsumer\tvertexConsumer,\n\t\t\tT\t\t\t\tcontext,\n\t\t\tMatrix4f\t\ttransform,\n\t\t\tMatrix3f\t\tnormal,\n\t\t\tint\t\t\t\tlight,\n\t\t\tint\t\t\t\toverlay,\n\t\t\tint\t\t\t\tcolor\n\t) {\n\t\trenderer.render(\n\t\t\t\tbufferDecorator.decorate(vertexConsumer),\n\t\t\t\tcontext,\n\t\t\t\ttransform,\n\t\t\t\tnormal,\n\t\t\t\tlight,\n\t\t\t\toverlay,\n\t\t\t\tcolor\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/renderers/IAcceleratedRenderer.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers;\n\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\npublic interface IAcceleratedRenderer<T> {\n\n\tvoid render(VertexConsumer vertexConsumer, T context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color);\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/renderers/IBufferDecorator.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers;\n\nimport com.mojang.blaze3d.vertex.VertexConsumer;\n\npublic interface IBufferDecorator {\n\n\tVertexConsumer decorate(VertexConsumer buffer);\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/renderers/SheetedDecalTextureRenderer.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedSheetedDecalTextureGenerator;\nimport com.github.argon4w.acceleratedrendering.core.utils.FuzzyMatrix4f;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\npublic class SheetedDecalTextureRenderer<T> implements IAcceleratedRenderer<T> {\n\n\tprivate final IAcceleratedRenderer<T>\trenderer;\n\tprivate final Matrix4f\t\t\t\t\tcameraInverse;\n\tprivate final Matrix3f\t\t\t\t\tnormalInverse;\n\tprivate final float\t\t\t\t\t\ttextureScale;\n\n\tpublic SheetedDecalTextureRenderer(\n\t\t\tIAcceleratedRenderer<T>\trenderer,\n\t\t\tMatrix4f\t\t\t\tcameraInverse,\n\t\t\tMatrix3f\t\t\t\tnormalInverse,\n\t\t\tfloat\t\t\t\t\ttextureScale\n\t) {\n\t\tthis.renderer\t\t= renderer;\n\t\tthis.cameraInverse\t= cameraInverse;\n\t\tthis.normalInverse\t= normalInverse;\n\t\tthis.textureScale\t= textureScale;\n\t}\n\n\t@Override\n\tpublic void render(\n\t\t\tVertexConsumer\tvertexConsumer,\n\t\t\tT\t\t\t\tcontext,\n\t\t\tMatrix4f\t\ttransform,\n\t\t\tMatrix3f\t\tnormal,\n\t\t\tint\t\t\t\tlight,\n\t\t\tint\t\t\t\toverlay,\n\t\t\tint\t\t\t\tcolor\n\t) {\n\t\trenderer.render(\n\t\t\t\tnew AcceleratedSheetedDecalTextureGenerator(\n\t\t\t\t\t\tvertexConsumer,\n\t\t\t\t\t\tnew FuzzyMatrix4f\t(cameraInverse).mul(transform),\n\t\t\t\t\t\tnew Matrix3f\t\t(normalInverse).mul(normal),\n\t\t\t\t\t\ttextureScale\n\t\t\t\t),\n\t\t\t\tcontext,\n\t\t\t\ttransform,\n\t\t\t\tnormal,\n\t\t\t\tlight,\n\t\t\t\toverlay,\n\t\t\t\tcolor\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/environments/IBufferEnvironment.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.environments;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.buffers.IServerBuffer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout;\nimport com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderPrograms;\nimport com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.programs.dispatchers.IPolygonProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.programs.dispatchers.MeshUploadingProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.programs.dispatchers.TransformProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.programs.overrides.ITransformShaderProgramOverride;\nimport com.github.argon4w.acceleratedrendering.core.programs.overrides.IUploadingShaderProgramOverride;\nimport com.mojang.blaze3d.vertex.DefaultVertexFormat;\nimport com.mojang.blaze3d.vertex.VertexFormat;\nimport net.minecraft.client.renderer.RenderType;\n\nimport java.util.Set;\n\npublic interface IBufferEnvironment {\n\n\tint\t\t\t\t\t\t\t\t\tgetVertexSize\t\t\t\t\t\t();\n\tSet<VertexFormat>\t\t\t\t\tgetVertexFormats\t\t\t\t\t();\n\tVertexLayout\t\t\t\t\t\tgetLayout\t\t\t\t\t\t\t();\n\tIServerBuffer\t\t\t\t\t\tgetImmediateMeshBuffer\t\t\t\t();\n\tMeshUploadingProgramDispatcher\t\tselectMeshUploadingProgramDispatcher();\n\tTransformProgramDispatcher\t\t\tselectTransformProgramDispatcher\t();\n\tITransformShaderProgramOverride\t\tgetTransformProgramOverride\t\t\t(RenderType\t\t\trenderType);\n\tIUploadingShaderProgramOverride\t\tgetUploadingProgramOverride\t\t\t(RenderType\t\t\trenderType);\n\tICullingProgramDispatcher\t\t\tselectCullingProgramDispatcher\t\t(RenderType\t\t\trenderType);\n\tIPolygonProgramDispatcher\t\t\tselectProcessingProgramDispatcher\t(VertexFormat.Mode\tmode);\n\tboolean\t\t\t\t\t\t\t\tisAccelerated\t\t\t\t\t\t(VertexFormat\t\tvertexFormat);\n\tvoid\t\t\t\t\t\t\t\tsetupBufferState\t\t\t\t\t();\n\n\tclass Presets {\n\n\t\tpublic static final IBufferEnvironment BLOCK\t\t\t\t= new VanillaBufferEnvironment(DefaultVertexFormat.BLOCK,\t\t\t\t\t\tComputeShaderPrograms.CORE_BLOCK_MESH_UPLOADING_KEY,\t\t\t\tComputeShaderPrograms.CORE_BLOCK_VERTEX_TRANSFORM_KEY);\n\t\tpublic static final IBufferEnvironment ENTITY\t\t\t\t= new VanillaBufferEnvironment(DefaultVertexFormat.NEW_ENTITY,\t\t\t\t\tComputeShaderPrograms.CORE_ENTITY_MESH_UPLOADING_KEY,\t\t\t\tComputeShaderPrograms.CORE_ENTITY_VERTEX_TRANSFORM_KEY);\n\t\tpublic static final IBufferEnvironment POS\t\t\t\t\t= new VanillaBufferEnvironment(DefaultVertexFormat.POSITION,\t\t\t\t\tComputeShaderPrograms.CORE_POS_MESH_UPLOADING_KEY,\t\t\t\t\tComputeShaderPrograms.CORE_POS_VERTEX_TRANSFORM_KEY);\n\t\tpublic static final IBufferEnvironment POS_COLOR\t\t\t= new VanillaBufferEnvironment(DefaultVertexFormat.POSITION_COLOR,\t\t\t\tComputeShaderPrograms.CORE_POS_COLOR_MESH_UPLOADING_KEY,\t\t\tComputeShaderPrograms.CORE_POS_COLOR_VERTEX_TRANSFORM_KEY);\n\t\tpublic static final IBufferEnvironment POS_TEX\t\t\t\t= new VanillaBufferEnvironment(DefaultVertexFormat.POSITION_TEX,\t\t\t\tComputeShaderPrograms.CORE_POS_TEX_MESH_UPLOADING_KEY,\t\t\t\tComputeShaderPrograms.CORE_POS_TEX_VERTEX_TRANSFORM_KEY);\n\t\tpublic static final IBufferEnvironment POS_TEX_COLOR\t\t= new VanillaBufferEnvironment(DefaultVertexFormat.POSITION_TEX_COLOR,\t\t\tComputeShaderPrograms.CORE_POS_TEX_COLOR_MESH_UPLOADING_KEY,\t\tComputeShaderPrograms.CORE_POS_TEX_COLOR_VERTEX_TRANSFORM_KEY);\n\t\tpublic static final IBufferEnvironment POS_COLOR_TEX_LIGHT\t= new VanillaBufferEnvironment(DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP,\tComputeShaderPrograms.CORE_POS_COLOR_TEX_LIGHT_MESH_UPLOADING_KEY,\tComputeShaderPrograms.CORE_POS_COLOR_TEX_LIGHT_VERTEX_TRANSFORM_KEY);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/environments/VanillaBufferEnvironment.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.environments;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.buffers.IServerBuffer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout;\nimport com.github.argon4w.acceleratedrendering.core.meshes.ServerMesh;\nimport com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramSelector;\nimport com.github.argon4w.acceleratedrendering.core.programs.culling.LoadCullingProgramSelectorEvent;\nimport com.github.argon4w.acceleratedrendering.core.programs.dispatchers.IPolygonProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.programs.dispatchers.MeshUploadingProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.programs.dispatchers.TransformProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.programs.overrides.IShaderProgramOverrides;\nimport com.github.argon4w.acceleratedrendering.core.programs.overrides.ITransformShaderProgramOverride;\nimport com.github.argon4w.acceleratedrendering.core.programs.overrides.IUploadingShaderProgramOverride;\nimport com.github.argon4w.acceleratedrendering.core.programs.overrides.LoadShaderProgramOverridesEvent;\nimport com.github.argon4w.acceleratedrendering.core.programs.processing.IPolygonProcessor;\nimport com.github.argon4w.acceleratedrendering.core.programs.processing.LoadPolygonProcessorEvent;\nimport com.mojang.blaze3d.vertex.VertexFormat;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.fml.ModLoader;\n\nimport java.util.Set;\n\npublic class VanillaBufferEnvironment implements IBufferEnvironment {\n\n\tprivate final VertexFormat\t\t\t\t\t\tvertexFormat;\n\tprivate final VertexLayout\t\t\t\t\t\tlayout;\n\n\tprivate final IShaderProgramOverrides\t\t\tshaderProgramOverrides;\n\tprivate final MeshUploadingProgramDispatcher\tmeshUploadingProgramDispatcher;\n\tprivate final TransformProgramDispatcher\t\ttransformProgramDispatcher;\n\tprivate final ICullingProgramSelector\t\t\tcullingProgramSelector;\n\tprivate final IPolygonProcessor\t\t\t\t\tpolygonProcessor;\n\n\tpublic VanillaBufferEnvironment(\n\t\t\tVertexFormat\t\tvertexFormat,\n\t\t\tResourceLocation\tuploadingProgramKey,\n\t\t\tResourceLocation\ttransformProgramKey\n\t) {\n\t\tvar defaultTransformOverride\t\t= new TransformProgramDispatcher\t.Default(transformProgramKey, 4L * 4L);\n\t\tvar defaultUploadingOverride\t\t= new MeshUploadingProgramDispatcher.Default(uploadingProgramKey, 5L * 4L);\n\n\t\tthis.vertexFormat\t\t\t\t\t= vertexFormat;\n\t\tthis.layout\t\t\t\t\t\t\t= new VertexLayout(vertexFormat);\n\n\t\tthis.shaderProgramOverrides\t\t\t= ModLoader.postEventWithReturn(new LoadShaderProgramOverridesEvent\t(this.vertexFormat)).getOverrides\t(defaultTransformOverride, defaultUploadingOverride);\n\t\tthis.cullingProgramSelector\t\t\t= ModLoader.postEventWithReturn(new LoadCullingProgramSelectorEvent\t(this.vertexFormat)).getSelector\t();\n\t\tthis.polygonProcessor\t\t\t\t= ModLoader.postEventWithReturn(new LoadPolygonProcessorEvent\t\t(this.vertexFormat)).getProcessor\t();\n\n\t\tthis.meshUploadingProgramDispatcher\t= new MeshUploadingProgramDispatcher();\n\t\tthis.transformProgramDispatcher\t\t= new TransformProgramDispatcher\t();\n\t}\n\n\t@Override\n\tpublic void setupBufferState() {\n\t\tvertexFormat.setupBufferState();\n\t}\n\n\t@Override\n\tpublic Set<VertexFormat> getVertexFormats() {\n\t\treturn Set.of(vertexFormat);\n\t}\n\n\t@Override\n\tpublic VertexLayout getLayout() {\n\t\treturn layout;\n\t}\n\n\t@Override\n\tpublic IServerBuffer getImmediateMeshBuffer() {\n\t\treturn ServerMesh.Builder.BUFFERS.get(layout).getFirst();\n\t}\n\n\t@Override\n\tpublic ITransformShaderProgramOverride getTransformProgramOverride(RenderType renderType) {\n\t\treturn shaderProgramOverrides.getTransformOverrides().get(renderType);\n\t}\n\n\t@Override\n\tpublic IUploadingShaderProgramOverride getUploadingProgramOverride(RenderType renderType) {\n\t\treturn shaderProgramOverrides.getUploadingOverrides().get(renderType);\n\t}\n\n\t@Override\n\tpublic MeshUploadingProgramDispatcher selectMeshUploadingProgramDispatcher() {\n\t\treturn meshUploadingProgramDispatcher;\n\t}\n\n\t@Override\n\tpublic TransformProgramDispatcher selectTransformProgramDispatcher() {\n\t\treturn transformProgramDispatcher;\n\t}\n\n\t@Override\n\tpublic ICullingProgramDispatcher selectCullingProgramDispatcher(RenderType renderType) {\n\t\treturn cullingProgramSelector.select(renderType);\n\t}\n\n\t@Override\n\tpublic IPolygonProgramDispatcher selectProcessingProgramDispatcher(VertexFormat.Mode mode) {\n\t\treturn polygonProcessor.select(mode);\n\t}\n\n\t@Override\n\tpublic boolean isAccelerated(VertexFormat vertexFormat) {\n\t\treturn this.vertexFormat == vertexFormat;\n\t}\n\n\t@Override\n\tpublic int getVertexSize() {\n\t\treturn vertexFormat.getVertexSize();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/memory/IMemoryInterface.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.memory;\n\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\npublic interface IMemoryInterface {\n\n\tvoid\t\t\t\tputByte\t\t(long\taddress,\tbyte\t\tvalue);\n\tvoid\t\t\t\tputShort\t(long\taddress,\tshort\t\tvalue);\n\tvoid\t\t\t\tputInt\t\t(long\taddress,\tint\t\t\tvalue);\n\tvoid\t\t\t\tputInt\t\t(long\taddress,\tlong\t\tvalue);\n\tvoid\t\t\t\tputFloat\t(long\taddress,\tfloat\t\tvalue);\n\tvoid\t\t\t\tputNormal\t(long\taddress,\tfloat\t\tvalue);\n\tvoid\t\t\t\tputMatrix4f\t(long\taddress,\tMatrix4f\tvalue);\n\tvoid\t\t\t\tputMatrix3f\t(long\taddress,\tMatrix3f\tvalue);\n\tIMemoryInterface\tat\t\t\t(int\tindex);\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/memory/IMemoryLayout.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.memory;\n\npublic interface IMemoryLayout<T> {\n\n\tIMemoryInterface\tgetElement\t\t(T element);\n\tint\t\t\t\t\tgetElementOffset(T element);\n\tboolean\t\t\t\tcontainsElement\t(T element);\n\tlong\t\t\t\tgetSize\t\t\t();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/memory/NullMemoryInterface.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.memory;\n\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\npublic class NullMemoryInterface implements IMemoryInterface {\n\n\tpublic static final NullMemoryInterface INSTANCE = new NullMemoryInterface();\n\n\t@Override\n\tpublic void putByte(long address, byte value) {\n\n\t}\n\n\t@Override\n\tpublic void putShort(long address, short value) {\n\n\t}\n\n\t@Override\n\tpublic void putInt(long address, int value) {\n\n\t}\n\n\t@Override\n\tpublic void putInt(long address, long value) {\n\n\t}\n\n\t@Override\n\tpublic void putFloat(long address, float value) {\n\n\t}\n\n\t@Override\n\tpublic void putNormal(long address, float value) {\n\n\t}\n\n\t@Override\n\tpublic void putMatrix4f(long address, Matrix4f value) {\n\n\t}\n\n\t@Override\n\tpublic void putMatrix3f(long address, Matrix3f value) {\n\n\t}\n\n\t@Override\n\tpublic IMemoryInterface at(int index) {\n\t\treturn INSTANCE;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/memory/SimpleDynamicMemoryInterface.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.memory;\n\nimport com.github.argon4w.acceleratedrendering.core.utils.MemUtils;\nimport lombok.AllArgsConstructor;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.lwjgl.system.MemoryUtil;\n\nimport java.util.function.LongSupplier;\n\n@AllArgsConstructor\npublic class SimpleDynamicMemoryInterface implements IMemoryInterface {\n\n\tprivate final long\t\t\toffset;\n\tprivate final LongSupplier\tsize;\n\n\t@Override\n\tpublic void putByte(long address, byte value) {\n\t\tMemoryUtil.memPutByte(address + offset, value);\n\t}\n\n\t@Override\n\tpublic void putShort(long address, short value) {\n\t\tMemoryUtil.memPutShort(address + offset, value);\n\t}\n\n\t@Override\n\tpublic void putInt(long address, int value) {\n\t\tMemoryUtil.memPutInt(address + offset, value);\n\t}\n\n\t@Override\n\tpublic void putInt(long address, long value) {\n\t\tMemoryUtil.memPutInt(address + offset, (int) value);\n\t}\n\n\t@Override\n\tpublic void putFloat(long address, float value) {\n\t\tMemoryUtil.memPutFloat(address + offset, value);\n\t}\n\n\t@Override\n\tpublic void putNormal(long address, float value) {\n\t\tMemUtils.putNormal(address + offset, value);\n\t}\n\n\t@Override\n\tpublic void putMatrix4f(long address, Matrix4f value) {\n\t\tMemUtils.putMatrix4f(address + offset, value);\n\t}\n\n\t@Override\n\tpublic void putMatrix3f(long address, Matrix3f value) {\n\t\tMemUtils.putMatrix3f(address + offset, value);\n\t}\n\n\t@Override\n\tpublic IMemoryInterface at(int index) {\n\t\treturn new SimpleDynamicMemoryInterface(index * size.getAsLong() + offset, size);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/memory/SimpleMemoryInterface.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.memory;\n\nimport com.github.argon4w.acceleratedrendering.core.utils.MemUtils;\nimport lombok.AllArgsConstructor;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.lwjgl.system.MemoryUtil;\n\n@AllArgsConstructor\npublic class SimpleMemoryInterface implements IMemoryInterface {\n\n\tprivate final long offset;\n\tprivate final long size;\n\n\t@Override\n\tpublic void putByte(long address, byte value) {\n\t\tMemoryUtil.memPutByte(address + offset, value);\n\t}\n\n\t@Override\n\tpublic void putShort(long address, short value) {\n\t\tMemoryUtil.memPutShort(address + offset, value);\n\t}\n\n\t@Override\n\tpublic void putInt(long address, int value) {\n\t\tMemoryUtil.memPutInt(address + offset, value);\n\t}\n\n\t@Override\n\tpublic void putInt(long address, long value) {\n\t\tMemoryUtil.memPutInt(address + offset, (int) value);\n\t}\n\n\t@Override\n\tpublic void putFloat(long address, float value) {\n\t\tMemoryUtil.memPutFloat(address + offset, value);\n\t}\n\n\t@Override\n\tpublic void putNormal(long address, float value) {\n\t\tMemUtils.putNormal(address + offset, value);\n\t}\n\n\t@Override\n\tpublic void putMatrix4f(long address, Matrix4f value) {\n\t\tMemUtils.putMatrix4f(address + offset, value);\n\t}\n\n\t@Override\n\tpublic void putMatrix3f(long address, Matrix3f value) {\n\t\tMemUtils.putMatrix3f(address + offset, value);\n\t}\n\n\t@Override\n\tpublic IMemoryInterface at(int index) {\n\t\treturn new SimpleMemoryInterface(index * size + offset, size);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/memory/VertexLayout.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.buffers.memory;\n\nimport com.mojang.blaze3d.vertex.VertexFormat;\nimport com.mojang.blaze3d.vertex.VertexFormatElement;\n\npublic class VertexLayout implements IMemoryLayout<VertexFormatElement> {\n\n\tprivate final long\t\t\t\t\tsize;\n\tprivate final int\t\t\t\t\tmask;\n\tprivate final int\t\t\t\t[]\toffsets;\n\tprivate final IMemoryInterface\t[]\tinterfaces;\n\n\tpublic VertexLayout(VertexFormat vertexFormat) {\n\t\tvar offsets\t= vertexFormat\t.getOffsetsByElement();\n\t\tvar count\t= offsets\t\t.length;\n\n\t\tthis.size = vertexFormat.getVertexSize\t();\n\t\tthis.mask = vertexFormat.getElementsMask();\n\n\t\tthis.offsets\t= new int\t\t\t\t[count];\n\t\tthis.interfaces\t= new IMemoryInterface\t[count];\n\n\t\tfor (var i = 0; i < count; i ++) {\n\t\t\tvar offset = offsets[i];\n\n\t\t\tthis.interfaces\t[i]\t= offset == -1 ? NullMemoryInterface.INSTANCE : new SimpleMemoryInterface(offset, size);\n\t\t\tthis.offsets\t[i]\t= offset;\n\t\t}\n\t}\n\n\t@Override\n\tpublic IMemoryInterface getElement(VertexFormatElement element) {\n\t\treturn interfaces[element.id()];\n\t}\n\n\t@Override\n\tpublic int getElementOffset(VertexFormatElement element) {\n\t\treturn offsets[element.id()];\n\t}\n\n\t@Override\n\tpublic boolean containsElement(VertexFormatElement element) {\n\t\treturn (mask & element.mask()) != 0;\n\t}\n\n\t@Override\n\tpublic long getSize() {\n\t\treturn size;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/ClientMesh.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.meshes;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.core.meshes.collectors.IMeshCollector;\nimport com.github.argon4w.acceleratedrendering.core.meshes.data.cache.MeshDataCaches;\nimport com.mojang.blaze3d.vertex.ByteBufferBuilder;\nimport it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet;\nimport lombok.AllArgsConstructor;\n\nimport java.nio.ByteBuffer;\nimport java.util.Set;\n\n@AllArgsConstructor\npublic class ClientMesh implements IMesh {\n\n\tprivate final int\t\t\tsize;\n\tprivate final ByteBuffer\tvertexBuffer;\n\n\t@Override\n\tpublic void write(\n\t\t\tIAcceleratedVertexConsumer\textension,\n\t\t\tint\t\t\t\t\t\t\tcolor,\n\t\t\tint\t\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\t\toverlay\n\t) {\n\t\textension.addClientMesh(\n\t\t\t\tvertexBuffer,\n\t\t\t\tsize,\n\t\t\t\tcolor,\n\t\t\t\tlight,\n\t\t\t\toverlay\n\t\t);\n\t}\n\n\tpublic static class Builder implements IMesh.Builder {\n\n\t\tpublic static\tfinal Builder\t\t\t\t\tINSTANCE = new Builder();\n\n\t\tprivate\t\t\tfinal Set<ByteBufferBuilder>\tbuilders;\n\n\t\tprivate Builder() {\n\t\t\tthis.builders = new ReferenceLinkedOpenHashSet<>();\n\t\t}\n\n\t\t@Override\n\t\tpublic IMesh build(IMeshCollector collector) {\n\t\t\tvar vertexCount = collector.getVertexCount();\n\n\t\t\tif (vertexCount == 0) {\n\t\t\t\treturn EmptyMesh.INSTANCE;\n\t\t\t}\n\n\t\t\tvar builder\t\t= collector\t\t\t\t.getBuffer\t\t();\n\t\t\tvar layout\t\t= collector\t\t\t\t.getLayout\t\t();\n\t\t\tvar data\t\t= collector\t\t\t\t.getData\t\t();\n\t\t\tvar mesh\t\t= MeshDataCaches.CLIENT\t.get\t\t\t(layout, data);\n\n\t\t\tif (mesh != null) {\n\t\t\t\tbuilder.discard\t();\n\t\t\t\tbuilder.clear\t();\n\n\t\t\t\treturn mesh;\n\t\t\t}\n\n\t\t\tvar result = builder.build();\n\n\t\t\tif (result == null) {\n\t\t\t\tbuilder.discard\t();\n\t\t\t\tbuilder.close\t();\n\t\t\t\treturn EmptyMesh.INSTANCE;\n\t\t\t}\n\n\t\t\tbuilders.add(builder);\n\n\t\t\tmesh = new ClientMesh(vertexCount, result.byteBuffer());\n\n\t\t\tMeshDataCaches.CLIENT.set(\n\t\t\t\t\tlayout,\n\t\t\t\t\tdata,\n\t\t\t\t\tmesh\n\t\t\t);\n\n\t\t\treturn mesh;\n\t\t}\n\n\t\t@Override\n\t\tpublic IMesh build(IMeshCollector collector, boolean forceDense) {\n\t\t\treturn build(collector);\n\t\t}\n\n\t\t@Override\n\t\tpublic void delete() {\n\t\t\tfor (var builder : builders) {\n\t\t\t\tbuilder.discard\t();\n\t\t\t\tbuilder.close\t();\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/EmptyMesh.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.meshes;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\n\npublic class EmptyMesh implements IMesh {\n\n\tpublic static final EmptyMesh INSTANCE = new EmptyMesh();\n\n\t@Override\n\tpublic void write(\n\t\t\tIAcceleratedVertexConsumer\textension,\n\t\t\tint\t\t\t\t\t\t\tcolor,\n\t\t\tint\t\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\t\toverlay\n\t) {\n\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/IMesh.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.meshes;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.core.meshes.collectors.IMeshCollector;\n\npublic interface IMesh {\n\n\tvoid write(IAcceleratedVertexConsumer extension, int color, int light, int overlay);\n\n\tinterface Builder {\n\n\t\tIMesh\tbuild\t(IMeshCollector collector);\n\t\tIMesh\tbuild\t(IMeshCollector collector, boolean forceDense);\n\t\tvoid\tdelete\t();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/MeshType.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.meshes;\n\nimport lombok.Getter;\n\n@Getter\npublic enum MeshType {\n\n\tSERVER(ServerMesh.Builder.INSTANCE),\n\tCLIENT(ClientMesh.Builder.INSTANCE);\n\n\tprivate final IMesh.Builder builder;\n\n\tMeshType(IMesh.Builder builder) {\n\t\tthis.builder = builder;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/ServerMesh.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.meshes;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.backends.GLConstants;\nimport com.github.argon4w.acceleratedrendering.core.backends.buffers.EmptyServerBuffer;\nimport com.github.argon4w.acceleratedrendering.core.backends.buffers.IServerBuffer;\nimport com.github.argon4w.acceleratedrendering.core.backends.buffers.MappedBuffer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout;\nimport com.github.argon4w.acceleratedrendering.core.meshes.collectors.IMeshCollector;\nimport com.github.argon4w.acceleratedrendering.core.meshes.data.cache.MeshDataCaches;\nimport it.unimi.dsi.fastutil.objects.Reference2ObjectMap;\nimport it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;\nimport it.unimi.dsi.fastutil.objects.ReferenceArrayList;\nimport it.unimi.dsi.fastutil.objects.ReferenceLists;\nimport net.minecraft.CrashReport;\nimport net.minecraft.ReportedException;\nimport org.lwjgl.system.MemoryUtil;\n\nimport java.util.List;\n\npublic record ServerMesh(\n\t\tint\t\t\t\tsize,\n\t\tlong\t\t\toffset,\n\t\tboolean\t\t\tforceDense,\n\t\tIServerBuffer\tmeshBuffer\n) implements IMesh {\n\n\t@Override\n\tpublic void write(\n\t\t\tIAcceleratedVertexConsumer\textension,\n\t\t\tint\t\t\t\t\t\t\tcolor,\n\t\t\tint\t\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\t\toverlay\n\t) {\n\t\textension.addServerMesh(\n\t\t\t\tthis,\n\t\t\t\tcolor,\n\t\t\t\tlight,\n\t\t\t\toverlay\n\t\t);\n\t}\n\n\tpublic static class Builder implements IMesh.Builder {\n\n\t\tpublic static final Builder\t\t\t\t\t\t\t\t\t\t\t\t\tINSTANCE;\n\t\tpublic static final Reference2ObjectMap<VertexLayout, List<IServerBuffer>>\tBUFFERS;\n\n\t\tstatic {\n\t\t\tINSTANCE\t= new Builder\t\t\t\t\t\t();\n\t\t\tBUFFERS\t\t= new Reference2ObjectOpenHashMap<>\t();\n\t\t\tBUFFERS.defaultReturnValue\t\t\t\t\t\t(ReferenceLists.singleton(EmptyServerBuffer.INSTANCE));\n\t\t}\n\n\t\tprivate Builder() {\n\n\t\t}\n\n\t\t@Override\n\t\tpublic IMesh build(IMeshCollector collector, boolean forceDense) {\n\t\t\tvar vertexCount\t= collector.getVertexCount\t();\n\n\t\t\tif (vertexCount == 0) {\n\t\t\t\treturn EmptyMesh.INSTANCE;\n\t\t\t}\n\n\t\t\tvar builder\t\t= collector\t\t\t\t.getBuffer\t\t();\n\t\t\tvar layout\t\t= collector\t\t\t\t.getLayout\t\t();\n\t\t\tvar data\t\t= collector\t\t\t\t.getData\t\t();\n\t\t\tvar mesh\t\t= MeshDataCaches.SERVER\t.get\t\t\t(layout, data);\n\n\t\t\tif (mesh != null) {\n\t\t\t\tbuilder.discard\t();\n\t\t\t\tbuilder.close\t();\n\n\t\t\t\treturn mesh;\n\t\t\t}\n\n\t\t\tvar builderResult = builder.build();\n\n\t\t\tif (builderResult == null) {\n\t\t\t\tbuilder.discard\t();\n\t\t\t\tbuilder.close\t();\n\n\t\t\t\treturn EmptyMesh.INSTANCE;\n\t\t\t}\n\n\t\t\tvar byteBuffer\t\t= builderResult\t.byteBuffer\t\t();\n\t\t\tvar capacity\t\t= byteBuffer\t.capacity\t\t();\n\t\t\tvar meshBuffers\t\t= BUFFERS\t\t.getOrDefault\t(layout, null);\n\t\t\tvar meshBuffer\t\t= (MappedBuffer) null;\n\n\t\t\tif (meshBuffers == null) {\n\t\t\t\tmeshBuffers = new ReferenceArrayList<>\t();\n\t\t\t\tmeshBuffer\t= new MappedBuffer\t\t\t(64L);\n\t\t\t\tmeshBuffers\t.add\t\t\t\t\t\t(meshBuffer);\n\t\t\t\tBUFFERS\t\t.put \t\t\t\t\t\t(layout, meshBuffers);\n\t\t\t} else {\n\t\t\t\tmeshBuffer = (MappedBuffer) meshBuffers.getLast();\n\t\t\t}\n\n\t\t\tif (meshBuffer.getPosition() + capacity >= GLConstants.MAX_SHADER_STORAGE_BLOCK_SIZE) {\n\t\t\t\tif (CoreFeature.shouldUploadMeshImmediately()) {\n\t\t\t\t\tcollector\n\t\t\t\t\t\t\t.getBuffer\t()\n\t\t\t\t\t\t\t.close\t\t();\n\n\t\t\t\t\tvar crashReport\t= CrashReport\t.forThrowable\t(new OutOfMemoryError(\"Mesh buffer size exceeds limits.\"), \"Exception in building meshes.\");\n\t\t\t\t\tvar category\t= crashReport\t.addCategory\t(\"Mesh being built\");\n\n\t\t\t\t\tcategory.setDetail(\"Mesh type\",\t\t\t\t\t\t\"Server side mesh\");\n\t\t\t\t\tcategory.setDetail(\"Mesh layout size (bytes)\",\t\tcollector.getLayout()\t.getSize\t\t());\n\t\t\t\t\tcategory.setDetail(\"Mesh size (vertices)\",\t\t\tcollector\t\t\t\t.getVertexCount\t());\n\t\t\t\t\tcategory.setDetail(\"Mesh buffer limits (bytes)\",\tGLConstants\t\t\t\t.MAX_SHADER_STORAGE_BLOCK_SIZE);\n\n\t\t\t\t\tthrow new ReportedException(crashReport);\n\t\t\t\t}\n\n\t\t\t\tmeshBuffer = new MappedBuffer\t(64L);\n\t\t\t\tmeshBuffers.add\t\t\t\t\t(meshBuffer);\n\t\t\t}\n\n\t\t\tvar position\t= meshBuffer.getPosition();\n\t\t\tvar srcAddress\t= MemoryUtil.memAddress0(byteBuffer);\n\t\t\tvar destAddress\t= meshBuffer.reserve\t(capacity);\n\n\t\t\tMemoryUtil.memCopy(\n\t\t\t\t\tsrcAddress,\n\t\t\t\t\tdestAddress,\n\t\t\t\t\tcapacity\n\t\t\t);\n\n\t\t\tbuilder.discard\t();\n\t\t\tbuilder.close\t();\n\n\t\t\tmesh = new ServerMesh(\n\t\t\t\t\tvertexCount,\n\t\t\t\t\tposition / layout.getSize(),\n\t\t\t\t\tforceDense,\n\t\t\t\t\tmeshBuffer\n\t\t\t);\n\n\t\t\tMeshDataCaches.SERVER.set(\n\t\t\t\t\tlayout,\n\t\t\t\t\tdata,\n\t\t\t\t\tmesh\n\t\t\t);\n\n\t\t\treturn mesh;\n\t\t}\n\n\t\t@Override\n\t\tpublic IMesh build(IMeshCollector collector) {\n\t\t\treturn build(collector, false);\n\t\t}\n\n\t\t@Override\n\t\tpublic void delete() {\n\t\t\tfor (\t\tvar buffers\t: BUFFERS.values()) {\n\t\t\t\tfor (\tvar buffer\t: buffers) {\n\t\t\t\t\tbuffer.delete();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/collectors/CulledMeshCollector.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.meshes.collectors;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout;\nimport com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData;\nimport com.github.argon4w.acceleratedrendering.core.utils.CullerUtils;\nimport com.github.argon4w.acceleratedrendering.core.utils.Vertex;\nimport com.mojang.blaze3d.platform.NativeImage;\nimport com.mojang.blaze3d.vertex.ByteBufferBuilder;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport net.minecraft.client.renderer.texture.OverlayTexture;\n\npublic class CulledMeshCollector implements VertexConsumer, IMeshCollector {\n\n\tprivate final\tint\t\t\t\t\tpolygonSize;\n\tprivate final\tNativeImage\t\t\ttexture;\n\tprivate\tfinal\tVertexLayout\t\tlayout;\n\tprivate final\tSimpleMeshCollector\tmeshCollector;\n\tprivate final\tVertex[]\t\t\tpolygon;\n\n\tprivate\t\t\tint\t\t\t\t\tvertexIndex;\n\n\tpublic CulledMeshCollector(IAcceleratedVertexConsumer vertexConsumer) {\n\t\tthis.polygonSize\t= vertexConsumer\t.getPolygonSize\t();\n\t\tthis.texture\t\t= vertexConsumer\t.downloadTexture();\n\t\tthis.layout\t\t\t= vertexConsumer\t.getLayout\t\t();\n\t\tthis.meshCollector\t= new SimpleMeshCollector\t\t\t(this.layout);\n\t\tthis.polygon\t\t= new Vertex\t\t\t\t\t\t[this.polygonSize];\n\n\t\tthis.vertexIndex\t= -1;\n\t}\n\n\t@Override\n\tpublic void flush() {\n\t\tif (vertexIndex >= polygonSize - 1) {\n\t\t\tvertexIndex = -1;\n\n\t\t\tif (!CullerUtils.shouldCull(polygon, texture)) {\n\t\t\t\tfor (var vertex : polygon) {\n\t\t\t\t\tvar vertexPosition\t= vertex.getPosition();\n\t\t\t\t\tvar vertexUV\t\t= vertex.getUv\t\t();\n\t\t\t\t\tvar vertexNormal\t= vertex.getNormal\t();\n\n\t\t\t\t\tmeshCollector.addVertex(\n\t\t\t\t\t\t\tvertexPosition\t.x,\n\t\t\t\t\t\t\tvertexPosition\t.y,\n\t\t\t\t\t\t\tvertexPosition\t.z,\n\t\t\t\t\t\t\tvertex\t\t\t.getPackedColor(),\n\t\t\t\t\t\t\tvertexUV\t\t.x,\n\t\t\t\t\t\t\tvertexUV\t\t.y,\n\t\t\t\t\t\t\tOverlayTexture\t.NO_OVERLAY,\n\t\t\t\t\t\t\tvertex\t\t\t.getPackedLight(),\n\t\t\t\t\t\t\tvertexNormal\t.x,\n\t\t\t\t\t\t\tvertexNormal\t.y,\n\t\t\t\t\t\t\tvertexNormal\t.z\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic VertexConsumer addVertex(\n\t\t\tfloat pX,\n\t\t\tfloat pY,\n\t\t\tfloat pZ\n\t) {\n\t\tflush();\n\t\tpolygon[++ vertexIndex]\t\t\t\t\t= new Vertex();\n\t\tpolygon[vertexIndex].getPosition().x\t= pX;\n\t\tpolygon[vertexIndex].getPosition().y\t= pY;\n\t\tpolygon[vertexIndex].getPosition().z\t= pZ;\n\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setColor(\n\t\t\tint pRed,\n\t\t\tint pGreen,\n\t\t\tint pBlue,\n\t\t\tint pAlpha\n\t) {\n\t\tif (vertexIndex < 0) {\n\t\t\tthrow new IllegalStateException(\"Vertex not building!\");\n\t\t}\n\n\t\tpolygon[vertexIndex].getColor().x = pRed;\n\t\tpolygon[vertexIndex].getColor().y = pGreen;\n\t\tpolygon[vertexIndex].getColor().z = pBlue;\n\t\tpolygon[vertexIndex].getColor().w = pAlpha;\n\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setUv(float pU, float pV) {\n\t\tif (vertexIndex < 0) {\n\t\t\tthrow new IllegalStateException(\"Vertex not building!\");\n\t\t}\n\n\t\tpolygon[vertexIndex].getUv().x = pU;\n\t\tpolygon[vertexIndex].getUv().y = pV;\n\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setUv1(int pU, int pV) {\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setUv2(int pU, int pV) {\n\t\tif (vertexIndex < 0) {\n\t\t\tthrow new IllegalStateException(\"Vertex not building!\");\n\t\t}\n\n\t\tpolygon[vertexIndex].getLight().x = pU;\n\t\tpolygon[vertexIndex].getLight().y = pV;\n\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setNormal(\n\t\t\tfloat pNormalX,\n\t\t\tfloat pNormalY,\n\t\t\tfloat pNormalZ\n\t) {\n\t\tif (vertexIndex < 0) {\n\t\t\tthrow new IllegalStateException(\"Vertex not building!\");\n\t\t}\n\n\t\tpolygon[vertexIndex].getNormal().x = pNormalX;\n\t\tpolygon[vertexIndex].getNormal().y = pNormalY;\n\t\tpolygon[vertexIndex].getNormal().z = pNormalZ;\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic MeshData getData() {\n\t\treturn meshCollector.getData();\n\t}\n\n\t@Override\n\tpublic ByteBufferBuilder getBuffer() {\n\t\treturn meshCollector.getBuffer();\n\t}\n\n\t@Override\n\tpublic VertexLayout getLayout() {\n\t\treturn meshCollector.getLayout();\n\t}\n\n\t@Override\n\tpublic int getVertexCount() {\n\t\treturn meshCollector.getVertexCount();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/collectors/IMeshCollector.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.meshes.collectors;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout;\nimport com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData;\nimport com.mojang.blaze3d.vertex.ByteBufferBuilder;\n\npublic interface IMeshCollector {\n\n\tMeshData\t\t\tgetData\t\t\t();\n\tByteBufferBuilder\tgetBuffer\t\t();\n\tVertexLayout\t\tgetLayout\t\t();\n\tint\t\t\t\t\tgetVertexCount\t();\n\tvoid\t\t\t\tflush\t\t\t();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/collectors/SimpleMeshCollector.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.meshes.collectors;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.IMemoryInterface;\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout;\nimport com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData;\nimport com.github.argon4w.acceleratedrendering.core.utils.PackedVector2i;\nimport com.mojang.blaze3d.vertex.ByteBufferBuilder;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport com.mojang.blaze3d.vertex.VertexFormatElement;\nimport lombok.Getter;\nimport net.minecraft.util.FastColor;\n\npublic class SimpleMeshCollector implements VertexConsumer, IMeshCollector {\n\n\t@Getter private\tfinal\tVertexLayout\t\tlayout;\n\t@Getter private\tfinal\tByteBufferBuilder\tbuffer;\n\n\tprivate\t\t\tfinal\tlong\t\t\t\tvertexSize;\n\tprivate\t\t\tfinal\tIMemoryInterface\tposOffset;\n\tprivate\t\t\tfinal\tIMemoryInterface\tcolorOffset;\n\tprivate\t\t\tfinal\tIMemoryInterface\tuv0Offset;\n\tprivate\t\t\tfinal\tIMemoryInterface\tuv2Offset;\n\tprivate\t\t\tfinal\tIMemoryInterface\tnormalOffset;\n\tprivate\t\t\tfinal\tMeshData.Builder\tbuilder;\n\n\tprivate\t\t\t\t\tMeshData\t\t\tmeshData;\n\t@Getter private\t\t\tlong\t\t\t\tvertexAddress;\n\t@Getter private\t\t\tint\t\t\t\t\tvertexCount;\n\n\tpublic SimpleMeshCollector(VertexLayout layout) {\n\t\tthis.layout\t\t\t= layout;\n\t\tthis.buffer\t\t\t= new ByteBufferBuilder\t(1024);\n\n\t\tthis.vertexSize\t\t= this.layout\t.getSize\t\t();\n\t\tthis.posOffset\t\t= this.layout\t.getElement\t\t(VertexFormatElement.POSITION);\n\t\tthis.colorOffset\t= this.layout\t.getElement\t\t(VertexFormatElement.COLOR);\n\t\tthis.uv0Offset\t\t= this.layout\t.getElement\t\t(VertexFormatElement.UV);\n\t\tthis.uv2Offset\t\t= this.layout\t.getElement\t\t(VertexFormatElement.UV2);\n\t\tthis.normalOffset\t= this.layout\t.getElement\t\t(VertexFormatElement.NORMAL);\n\t\tthis.builder\t\t= MeshData\t\t.builder\t\t();\n\n\t\tthis.vertexAddress\t= -1L;\n\t\tthis.vertexCount\t= 0;\n\t}\n\n\t@Override\n\tpublic void flush() {\n\t\tbuilder.addVertex();\n\t}\n\n\t@Override\n\tpublic VertexConsumer addVertex(\n\t\t\tfloat pX,\n\t\t\tfloat pY,\n\t\t\tfloat pZ\n\t) {\n\t\tif (vertexCount != 0) {\n\t\t\tbuilder.addVertex();\n\t\t}\n\n\t\tvertexCount ++;\n\t\tvertexAddress = buffer.reserve((int) vertexSize);\n\n\t\tposOffset.putFloat(vertexAddress + 0L, pX);\n\t\tposOffset.putFloat(vertexAddress + 4L, pY);\n\t\tposOffset.putFloat(vertexAddress + 8L, pZ);\n\n\t\tbuilder.setPosition(\n\t\t\t\tpX,\n\t\t\t\tpY,\n\t\t\t\tpZ\n\t\t);\n\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setColor(\n\t\t\tint pRed,\n\t\t\tint pGreen,\n\t\t\tint pBlue,\n\t\t\tint pAlpha\n\t) {\n\t\tif (vertexAddress == -1) {\n\t\t\tthrow new IllegalStateException(\"Vertex not building!\");\n\t\t}\n\n\t\tcolorOffset.putByte(vertexAddress + 0L, (byte) pRed);\n\t\tcolorOffset.putByte(vertexAddress + 1L, (byte) pGreen);\n\t\tcolorOffset.putByte(vertexAddress + 2L, (byte) pBlue);\n\t\tcolorOffset.putByte(vertexAddress + 3L, (byte) pAlpha);\n\n\t\tbuilder.setColor(\n\t\t\t\tpRed,\n\t\t\t\tpGreen,\n\t\t\t\tpBlue,\n\t\t\t\tpAlpha\n\t\t);\n\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setUv(float pU, float pV) {\n\t\tif (vertexAddress == -1) {\n\t\t\tthrow new IllegalStateException(\"Vertex not building!\");\n\t\t}\n\n\t\tuv0Offset.putFloat(vertexAddress + 0L, pU);\n\t\tuv0Offset.putFloat(vertexAddress + 4L, pV);\n\n\t\tbuilder.setUv(pU, pV);\n\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setUv1(int pU, int pV) {\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setUv2(int pU, int pV) {\n\t\tif (vertexAddress == -1) {\n\t\t\tthrow new IllegalStateException(\"Vertex not building!\");\n\t\t}\n\n\t\tuv2Offset.putShort(vertexAddress + 0L, (short) pU);\n\t\tuv2Offset.putShort(vertexAddress + 2L, (short) pV);\n\n\t\tbuilder.setUv2(pU, pV);\n\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic VertexConsumer setNormal(\n\t\t\tfloat pNormalX,\n\t\t\tfloat pNormalY,\n\t\t\tfloat pNormalZ\n\t) {\n\t\tif (vertexAddress == -1) {\n\t\t\tthrow new IllegalStateException(\"Vertex not building!\");\n\t\t}\n\n\t\tnormalOffset.putNormal(vertexAddress + 0L, pNormalX);\n\t\tnormalOffset.putNormal(vertexAddress + 1L, pNormalY);\n\t\tnormalOffset.putNormal(vertexAddress + 2L, pNormalZ);\n\n\t\tbuilder.setNormal(\n\t\t\t\tpNormalX,\n\t\t\t\tpNormalY,\n\t\t\t\tpNormalZ\n\t\t);\n\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic void addVertex(\n\t\t\tfloat\tpX,\n\t\t\tfloat\tpY,\n\t\t\tfloat\tpZ,\n\t\t\tint\t\tpColor,\n\t\t\tfloat\tpU,\n\t\t\tfloat\tpV,\n\t\t\tint\t\tpPackedOverlay,\n\t\t\tint\t\tpPackedLight,\n\t\t\tfloat\tpNormalX,\n\t\t\tfloat\tpNormalY,\n\t\t\tfloat\tpNormalZ\n\t) {\n\t\tvertexCount++;\n\t\tvertexAddress = buffer.reserve((int) vertexSize);\n\n\t\tposOffset\t.putFloat\t(vertexAddress + 0L,\tpX);\n\t\tposOffset\t.putFloat\t(vertexAddress + 4L,\tpY);\n\t\tposOffset\t.putFloat\t(vertexAddress + 8L,\tpZ);\n\t\tcolorOffset\t.putInt\t\t(vertexAddress,\t\t\tFastColor.ABGR32.fromArgb32(pColor));\n\t\tuv0Offset\t.putFloat\t(vertexAddress + 0L,\tpU);\n\t\tuv0Offset\t.putFloat\t(vertexAddress + 4L,\tpV);\n\t\tuv2Offset\t.putInt\t\t(vertexAddress,\t\t\tpPackedLight);\n\t\tnormalOffset.putNormal\t(vertexAddress + 0L,\tpNormalX);\n\t\tnormalOffset.putNormal\t(vertexAddress + 1L,\tpNormalY);\n\t\tnormalOffset.putNormal\t(vertexAddress + 2L,\tpNormalZ);\n\n\t\tbuilder.addVertex(\n\t\t\t\tpX,\n\t\t\t\tpY,\n\t\t\t\tpZ,\n\t\t\t\tpU,\n\t\t\t\tpV,\n\t\t\t\tFastColor.ARGB32.red\t(pColor),\n\t\t\t\tFastColor.ARGB32.green\t(pColor),\n\t\t\t\tFastColor.ARGB32.blue\t(pColor),\n\t\t\t\tFastColor.ARGB32.alpha\t(pColor),\n\t\t\t\tPackedVector2i\t.unpackU(pPackedLight),\n\t\t\t\tPackedVector2i\t.unpackV(pPackedLight),\n\t\t\t\tpNormalX,\n\t\t\t\tpNormalY,\n\t\t\t\tpNormalZ\n\t\t);\n\t}\n\n\t@Override\n\tpublic MeshData getData() {\n\t\tif (meshData == null) {\n\t\t\tmeshData = builder.build();\n\t\t}\n\n\t\treturn meshData;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/data/MeshData.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.meshes.data;\n\nimport com.github.argon4w.acceleratedrendering.core.utils.Vertex;\nimport it.unimi.dsi.fastutil.objects.ReferenceArrayList;\nimport lombok.EqualsAndHashCode;\n\nimport java.util.List;\n\n//@EqualsAndHashCode\npublic class MeshData {\n\n\tprivate final int[] data;\n\n\tprivate MeshData(int[] data) {\n\t\tthis.data = data;\n\t}\n\n\tpublic static Builder builder() {\n\t\treturn new Builder();\n\t}\n\n\tpublic static class Builder {\n\n\t\tprivate final List<Vertex>\tvertices;\n\t\tprivate final Vertex\t\tscratch;\n\n\t\tpublic Builder() {\n\t\t\tthis.vertices\t= new ReferenceArrayList<>\t();\n\t\t\tthis.scratch\t= new Vertex\t\t\t\t();\n\t\t}\n\n\t\tpublic Builder setPosition(\n\t\t\t\tfloat positionX,\n\t\t\t\tfloat positionY,\n\t\t\t\tfloat positionZ\n\t\t) {\n\t\t\tscratch.getPosition().set(\n\t\t\t\t\tpositionX,\n\t\t\t\t\tpositionY,\n\t\t\t\t\tpositionZ\n\t\t\t);\n\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic Builder setColor(\n\t\t\t\tint colorRed,\n\t\t\t\tint colorGreen,\n\t\t\t\tint colorBlue,\n\t\t\t\tint colorAlpha\n\t\t) {\n\t\t\tscratch.getColor().set(\n\t\t\t\t\tcolorRed,\n\t\t\t\t\tcolorGreen,\n\t\t\t\t\tcolorBlue,\n\t\t\t\t\tcolorAlpha\n\t\t\t);\n\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic Builder setNormal(\n\t\t\t\tfloat normalX,\n\t\t\t\tfloat normalY,\n\t\t\t\tfloat normalZ\n\t\t) {\n\t\t\tscratch.getNormal().set(\n\t\t\t\t\tnormalX,\n\t\t\t\t\tnormalY,\n\t\t\t\t\tnormalZ\n\t\t\t);\n\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic Builder setUv(float u, float v) {\n\t\t\tscratch.getUv().set(u, v);\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic Builder setUv2(int u, int v) {\n\t\t\tscratch.getLight().set(u, v);\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic Builder addVertex() {\n\t\t\tvertices.add(new Vertex(scratch));\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic Builder addVertex(\n\t\t\t\tfloat\tposX,\n\t\t\t\tfloat\tposY,\n\t\t\t\tfloat\tposZ,\n\t\t\t\tfloat\ttexU,\n\t\t\t\tfloat\ttexV,\n\t\t\t\tint\t\tcolorR,\n\t\t\t\tint\t\tcolorG,\n\t\t\t\tint\t\tcolorB,\n\t\t\t\tint\t\tcolorA,\n\t\t\t\tint\t\tlightU,\n\t\t\t\tint\t\tlightV,\n\t\t\t\tfloat\tnormalX,\n\t\t\t\tfloat\tnormalY,\n\t\t\t\tfloat\tnormalZ\n\t\t) {\n\t\t\tvar vertex = new Vertex();\n\n\t\t\tvertex.getPosition().x = posX;\n\t\t\tvertex.getPosition().y = posY;\n\t\t\tvertex.getPosition().z = posZ;\n\n\t\t\tvertex.getUv()\t\t.x = texU;\n\t\t\tvertex.getUv()\t\t.y = texV;\n\n\t\t\tvertex.getColor()\t.w = colorA;\n\t\t\tvertex.getColor()\t.x = colorR;\n\t\t\tvertex.getColor()\t.y = colorG;\n\t\t\tvertex.getColor()\t.z = colorB;\n\n\t\t\tvertex.getLight()\t.x = lightU;\n\t\t\tvertex.getLight()\t.y = lightV;\n\n\t\t\tvertex.getNormal()\t.x = normalX;\n\t\t\tvertex.getNormal()\t.y = normalY;\n\t\t\tvertex.getNormal()\t.z = normalZ;\n\n\t\t\tvertices.add(vertex);\n\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic MeshData build() {\n\t\t\tvar data = new int[vertices.size() * 8];\n\n\t\t\tfor (var i = 0; i < vertices.size(); i++) {\n\t\t\t\tvar vertex = vertices.get(i);\n\n\t\t\t\tdata[i * 8 + 0] = Float\t.floatToRawIntBits\t(vertex.getPosition().x);\n\t\t\t\tdata[i * 8 + 1] = Float\t.floatToRawIntBits\t(vertex.getPosition().y);\n\t\t\t\tdata[i * 8 + 2] = Float\t.floatToRawIntBits\t(vertex.getPosition().z);\n\t\t\t\tdata[i * 8 + 3] = vertex.getPackedColor\t\t();\n\t\t\t\tdata[i * 8 + 4] = Float\t.floatToRawIntBits\t(vertex.getUv().x);\n\t\t\t\tdata[i * 8 + 5] = Float\t.floatToRawIntBits\t(vertex.getUv().y);\n\t\t\t\tdata[i * 8 + 6] = vertex.getPackedLight\t\t();\n\t\t\t\tdata[i * 8 + 7] = vertex.getPackedNormal\t();\n\t\t\t}\n\n\t\t\treturn new MeshData(data);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/data/cache/IMeshDataCache.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.meshes.data.cache;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout;\nimport com.github.argon4w.acceleratedrendering.core.meshes.IMesh;\nimport com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData;\n\npublic interface IMeshDataCache {\n\n\tvoid\tset\t\t(VertexLayout layout, MeshData data, IMesh mesh);\n\tIMesh\tget\t\t(VertexLayout layout, MeshData data);\n\tint\t\tcount\t(VertexLayout layout, MeshData data);\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/data/cache/IgnoreMeshDataCache.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.meshes.data.cache;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout;\nimport com.github.argon4w.acceleratedrendering.core.meshes.IMesh;\nimport com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData;\n\npublic class IgnoreMeshDataCache implements IMeshDataCache {\n\n\t@Override\n\tpublic void set(\n\t\t\tVertexLayout\tlayout,\n\t\t\tMeshData\t\tdata,\n\t\t\tIMesh\t\t\tmesh\n\t) {\n\n\t}\n\n\t@Override\n\tpublic IMesh get(VertexLayout layout, MeshData meshData) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic int count(VertexLayout layout, MeshData data) {\n\t\treturn 0;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/data/cache/MeshDataCacheType.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.meshes.data.cache;\n\npublic enum MeshDataCacheType {\n\n\tIGNORED,\n\tMERGED;\n\n\tpublic IMeshDataCache create() {\n\t\treturn create(this);\n\t}\n\n\tpublic static IMeshDataCache create(MeshDataCacheType type) {\n\t\treturn switch (type) {\n\t\t\tcase IGNORED\t-> new IgnoreMeshDataCache();\n\t\t\tcase MERGED\t\t-> new SimpleMeshDataCache();\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/data/cache/MeshDataCaches.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.meshes.data.cache;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\n\npublic class MeshDataCaches {\n\n\tpublic static final IMeshDataCache SERVER = CoreFeature.createMeshDataCache();\n\tpublic static final IMeshDataCache CLIENT = CoreFeature.createMeshDataCache();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/data/cache/SimpleMeshDataCache.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.meshes.data.cache;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout;\nimport com.github.argon4w.acceleratedrendering.core.meshes.IMesh;\nimport com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData;\nimport it.unimi.dsi.fastutil.objects.*;\n\npublic class SimpleMeshDataCache implements IMeshDataCache {\n\n\tprivate final Object2ReferenceMap<VertexLayout, Object2ReferenceMap\t<MeshData, IMesh>>\tmeshes;\n\tprivate final Object2ReferenceMap<VertexLayout, Object2IntMap\t\t<MeshData>>\t\t\tcounts;\n\n\tpublic SimpleMeshDataCache() {\n\t\tthis.meshes = new Object2ReferenceOpenHashMap<>();\n\t\tthis.counts = new Object2ReferenceOpenHashMap<>();\n\n\t\tthis.meshes.defaultReturnValue(Object2ReferenceMaps\t.emptyMap());\n\t\tthis.counts.defaultReturnValue(Object2IntMaps\t\t.emptyMap());\n\t}\n\n\t@Override\n\tpublic void set(\n\t\t\tVertexLayout\tlayout,\n\t\t\tMeshData\t\tdata,\n\t\t\tIMesh\t\t\tmesh\n\t) {\n\t\tvar meshCache\t= meshes.getOrDefault(layout, null);\n\t\tvar countCache\t= counts.getOrDefault(layout, null);\n\n\t\tif (meshCache == null) {\n\t\t\tmeshCache\t= new Object2ReferenceOpenHashMap\t<>();\n\t\t\tcountCache\t= new Object2IntOpenHashMap\t\t\t<>();\n\n\t\t\tmeshes.put(layout, meshCache);\n\t\t\tcounts.put(layout, countCache);\n\t\t}\n\n\t\tmeshCache\t.putIfAbsent(data, mesh);\n\t\tcountCache\t.put\t\t(data, countCache.getInt(data) + 1);\n\t}\n\n\t@Override\n\tpublic IMesh get(VertexLayout layout, MeshData meshData) {\n\t\treturn meshes.get(layout).get(meshData);\n\t}\n\n\t@Override\n\tpublic int count(VertexLayout layout, MeshData data) {\n\t\treturn counts.get(layout).getInt(data);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/GameRendererMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.mixins;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreBuffers;\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.CoreStates;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType;\nimport net.minecraft.client.Camera;\nimport net.minecraft.client.renderer.GameRenderer;\nimport org.joml.Matrix4f;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@Mixin(GameRenderer.class)\npublic class GameRendererMixin {\n\n\t@Inject(\n\t\t\tmethod = \"renderItemInHand\",\n\t\t\tat = @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/minecraft/client/renderer/ItemInHandRenderer;renderHandsWithItems(FLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/player/LocalPlayer;I)V\",\n\t\t\t\t\tshift\t= At.Shift.BEFORE\n\t\t\t)\n\t)\n\tpublic void startRenderItemInHandsFast(\n\t\t\tCamera\t\t\tcamera,\n\t\t\tfloat\t\t\tpartialTick,\n\t\t\tMatrix4f\t\tprojectionMatrix,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tCoreFeature.setRenderingHand();\n\t}\n\n\t@Inject(\n\t\t\tmethod = \"renderItemInHand\",\n\t\t\tat = @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/minecraft/client/renderer/ItemInHandRenderer;renderHandsWithItems(FLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/player/LocalPlayer;I)V\",\n\t\t\t\t\tshift\t= At.Shift.AFTER\n\t\t\t)\n\t)\n\tpublic void stopRenderItemInHandsFast(\n\t\t\tCamera\t\t\tcamera,\n\t\t\tfloat\t\t\tpartialTick,\n\t\t\tMatrix4f\t\tprojectionMatrix,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tCoreFeature\t\t\t\t\t\t.resetRenderingHand\t();\n\n\t\tCoreStates\t\t\t\t\t\t.recordBuffers\t\t();\n\t\tCoreBuffers.ENTITY\t\t\t\t.prepareBuffers\t\t();\n\t\tCoreBuffers.BLOCK\t\t\t\t.prepareBuffers\t\t();\n\t\tCoreBuffers.POS\t\t\t\t\t.prepareBuffers\t\t();\n\t\tCoreBuffers.POS_COLOR\t\t\t.prepareBuffers\t\t();\n\t\tCoreBuffers.POS_TEX\t\t\t\t.prepareBuffers\t\t();\n\t\tCoreBuffers.POS_TEX_COLOR\t\t.prepareBuffers\t\t();\n\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.prepareBuffers\t\t();\n\t\tCoreStates\t\t\t\t\t\t.restoreBuffers\t\t();\n\n\t\tCoreBuffers.ENTITY\t\t\t\t.drawBuffers\t\t(LayerDrawType.ALL);\n\t\tCoreBuffers.BLOCK\t\t\t\t.drawBuffers\t\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS\t\t\t\t\t.drawBuffers\t\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS_COLOR\t\t\t.drawBuffers\t\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS_TEX\t\t\t\t.drawBuffers\t\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS_TEX_COLOR\t\t.drawBuffers\t\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.drawBuffers\t\t(LayerDrawType.ALL);\n\n\t\tCoreBuffers.ENTITY\t\t\t\t.clearBuffers\t\t();\n\t\tCoreBuffers.BLOCK\t\t\t\t.clearBuffers\t\t();\n\t\tCoreBuffers.POS\t\t\t\t\t.clearBuffers\t\t();\n\t\tCoreBuffers.POS_COLOR\t\t\t.clearBuffers\t\t();\n\t\tCoreBuffers.POS_TEX\t\t\t\t.clearBuffers\t\t();\n\t\tCoreBuffers.POS_TEX_COLOR\t\t.clearBuffers\t\t();\n\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.clearBuffers\t\t();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/LevelRendererMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.mixins;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreBuffers;\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.CoreStates;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType;\nimport com.github.argon4w.acceleratedrendering.core.meshes.ClientMesh;\nimport com.github.argon4w.acceleratedrendering.core.meshes.ServerMesh;\nimport com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderProgramLoader;\nimport com.github.argon4w.acceleratedrendering.features.items.gui.GuiBatchingController;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;\nimport net.minecraft.client.Camera;\nimport net.minecraft.client.DeltaTracker;\nimport net.minecraft.client.renderer.GameRenderer;\nimport net.minecraft.client.renderer.LevelRenderer;\nimport net.minecraft.client.renderer.LightTexture;\nimport net.minecraft.client.renderer.MultiBufferSource;\nimport org.joml.Matrix4f;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@Mixin(\n\t\tvalue\t\t= LevelRenderer.class,\n\t\tpriority\t= 998\n)\npublic class LevelRendererMixin {\n\n\t@Inject(\n\t\t\tmethod\t= \"renderLevel\",\n\t\t\tat\t\t= @At(\"HEAD\")\n\t)\n\tpublic void startRenderLevel(\n\t\t\tDeltaTracker\tdeltaTracker,\n\t\t\tboolean\t\t\trenderBlockOutline,\n\t\t\tCamera\t\t\tcamera,\n\t\t\tGameRenderer\tgameRenderer,\n\t\t\tLightTexture\tlightTexture,\n\t\t\tMatrix4f\t\tfrustumMatrix,\n\t\t\tMatrix4f\t\tprojectionMatrix,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tCoreFeature.setRenderingLevel();\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"renderLevel\",\n\t\t\tat\t\t= @At(\"RETURN\")\n\t)\n\tpublic void stopRenderLevel(\n\t\t\tDeltaTracker\tdeltaTracker,\n\t\t\tboolean\t\t\trenderBlockOutline,\n\t\t\tCamera\t\t\tcamera,\n\t\t\tGameRenderer\tgameRenderer,\n\t\t\tLightTexture\tlightTexture,\n\t\t\tMatrix4f\t\tfrustumMatrix,\n\t\t\tMatrix4f\t\tprojectionMatrix,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tCoreFeature.resetRenderingLevel();\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"renderLevel\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/minecraft/client/renderer/OutlineBufferSource;endOutlineBatch()V\"\n\t\t\t)\n\t)\n\tpublic void endOutlineBatches(\n\t\t\tDeltaTracker\tpDeltaTracker,\n\t\t\tboolean\t\t\tpRenderBlockOutline,\n\t\t\tCamera\t\t\tpCamera,\n\t\t\tGameRenderer\tpGameRenderer,\n\t\t\tLightTexture\tpLightTexture,\n\t\t\tMatrix4f\t\tpFrustumMatrix,\n\t\t\tMatrix4f\t\tpProjectionMatrix,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tCoreStates\t\t\t\t\t\t\t.recordBuffers\t();\n\t\tCoreBuffers.POS_TEX_COLOR_OUTLINE\t.prepareBuffers\t();\n\t\tCoreStates\t\t\t\t\t\t\t.restoreBuffers\t();\n\n\t\tCoreBuffers.POS_TEX_COLOR_OUTLINE\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS_TEX_COLOR_OUTLINE\t.clearBuffers\t();\n\t}\n\n\t@WrapOperation(\n\t\t\tmethod\t= \"renderLevel\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;endLastBatch()V\"\n\t\t\t)\n\t)\n\tpublic void drawCoreBuffers(MultiBufferSource.BufferSource instance, Operation<Void> original) {\n\t\tCoreStates\t\t\t\t\t\t.recordBuffers\t();\n\t\tCoreBuffers.ENTITY\t\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.BLOCK\t\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS\t\t\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS_COLOR\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS_TEX\t\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS_TEX_COLOR\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.prepareBuffers\t();\n\t\tCoreStates\t\t\t\t\t\t.restoreBuffers\t();\n\n\t\tCoreBuffers.ENTITY\t\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tCoreBuffers.BLOCK\t\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS\t\t\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS_COLOR\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS_TEX\t\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS_TEX_COLOR\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.drawBuffers\t(LayerDrawType.ALL);\n\n\t\tCoreBuffers.ENTITY\t\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.BLOCK\t\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS\t\t\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS_COLOR\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS_TEX\t\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS_TEX_COLOR\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.clearBuffers\t();\n\n\t\toriginal.call(instance);\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"close\",\n\t\t\tat\t\t= @At(\"TAIL\")\n\t)\n\tpublic void deleteBuffers(CallbackInfo ci) {\n\t\tCoreBuffers.ENTITY\t\t\t\t.delete();\n\t\tCoreBuffers.BLOCK\t\t\t\t.delete();\n\t\tCoreBuffers.POS\t\t\t\t\t.delete();\n\t\tCoreBuffers.POS_COLOR\t\t\t.delete();\n\t\tCoreBuffers.POS_TEX\t\t\t\t.delete();\n\t\tCoreBuffers.POS_TEX_COLOR\t\t.delete();\n\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.delete();\n\t\tCoreStates\t\t\t\t\t\t.delete();\n\t\tGuiBatchingController.INSTANCE\t.delete();\n\t\tComputeShaderProgramLoader\t\t.delete();\n\t\tServerMesh.Builder.INSTANCE\t\t.delete();\n\t\tClientMesh.Builder.INSTANCE\t\t.delete();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/BufferBuilderMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.mixins.buffers;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.buffers.EmptyAcceleratedBufferSources;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAcceleratedBufferSource;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAccelerationHolder;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.mojang.blaze3d.vertex.BufferBuilder;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport net.minecraft.client.renderer.RenderType;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Unique;\n\nimport java.util.function.Supplier;\n\n@Mixin(BufferBuilder.class)\npublic class BufferBuilderMixin implements IAccelerationHolder, IAcceleratedVertexConsumer {\n\n\t@Unique private IAcceleratedBufferSource\tbufferSources = EmptyAcceleratedBufferSources.INSTANCE;\n\t@Unique private RenderType\t\t\t\t\trenderType;\n\t@Unique private AcceleratedBufferBuilder\tacceleration;\n\n\t@Unique\n\t@Override\n\tpublic VertexConsumer initAcceleration(RenderType renderType, Supplier<IAcceleratedBufferSource> bufferSource) {\n\t\tif (CoreFeature.isLoaded()) {\n\t\t\tthis.bufferSources\t= bufferSource.get();\n\t\t\tthis.renderType\t\t= renderType;\n\t\t\tthis.acceleration\t= null;\n\t\t}\n\n\t\treturn (VertexConsumer) this;\n\t}\n\n\t@Unique\n\t@Override\n\tpublic boolean isAccelerated() {\n\t\treturn bufferSources != EmptyAcceleratedBufferSources.INSTANCE && getAccelerated() != null;\n\t}\n\n\t@Unique\n\t@Override\n\tpublic <T> void doRender(\n\t\t\tIAcceleratedRenderer<T>\trenderer,\n\t\t\tT\t\t\t\t\t\tcontext,\n\t\t\tMatrix4f\t\t\t\ttransform,\n\t\t\tMatrix3f\t\t\t\tnormal,\n\t\t\tint\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\t\tcolor\n\t) {\n\t\tgetAccelerated().doRender(\n\t\t\t\trenderer,\n\t\t\t\tcontext,\n\t\t\t\ttransform,\n\t\t\t\tnormal,\n\t\t\t\tlight,\n\t\t\t\toverlay,\n\t\t\t\tcolor\n\t\t);\n\t}\n\n\t@Unique\n\t@Override\n\tpublic AcceleratedBufferBuilder getAccelerated() {\n\t\tif (\t\tacceleration == null\n\t\t\t\t||\tacceleration.isOutdated()\n\t\t) {\n\t\t\tacceleration = bufferSources.getBuffer(\n\t\t\t\t\trenderType,\n\t\t\t\t\tCoreFeature.getDefaultLayerBeforeFunction\t(),\n\t\t\t\t\tCoreFeature.getDefaultLayerAfterFunction\t(),\n\t\t\t\t\tCoreFeature.getDefaultLayer\t\t\t\t\t()\n\t\t\t);\n\t\t}\n\n\t\treturn acceleration;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/BufferSourceMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.mixins.buffers;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreBuffersProvider;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAcceleratedBufferSource;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratableBufferSource;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.llamalad7.mixinextras.injector.ModifyReturnValue;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.MultiBufferSource;\nimport net.minecraft.client.renderer.RenderType;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Unique;\nimport org.spongepowered.asm.mixin.injection.At;\n\nimport java.util.function.Supplier;\n\n@ExtensionMethod(VertexConsumerExtension\t\t.class)\n@Mixin\t\t\t(MultiBufferSource.BufferSource\t.class)\npublic class BufferSourceMixin implements IAcceleratableBufferSource {\n\n\t@Unique private Supplier<IAcceleratedBufferSource> bufferSource = CoreBuffersProvider.EMPTY;\n\n\t@Unique\n\t@Override\n\tpublic Supplier<IAcceleratedBufferSource> getBoundAcceleratedBufferSource() {\n\t\treturn bufferSource;\n\t}\n\n\t@Override\n\tpublic boolean isBufferSourceAcceleratable() {\n\t\treturn bufferSource != CoreBuffersProvider.EMPTY;\n\t}\n\n\t@Unique\n\t@Override\n\tpublic void bindAcceleratedBufferSource(Supplier<IAcceleratedBufferSource> bufferSource) {\n\t\tthis.bufferSource = bufferSource;\n\t}\n\n\t@ModifyReturnValue(\n\t\t\tmethod\t= \"getBuffer\",\n\t\t\tat\t\t= @At(\"RETURN\")\n\t)\n\tpublic VertexConsumer initAcceleration(VertexConsumer original, RenderType renderType) {\n\t\treturn original\n\t\t\t\t.getHolder\t\t\t()\n\t\t\t\t.initAcceleration\t(renderType, bufferSource);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/EntityOutlineGeneratorMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.mixins.buffers;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedEntityOutlineGenerator;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.DecoratedRenderer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.OutlineBufferSource;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.Unique;\n\n@ExtensionMethod(VertexConsumerExtension\t\t\t\t\t.class)\n@Mixin\t\t\t(OutlineBufferSource.EntityOutlineGenerator\t.class)\npublic class EntityOutlineGeneratorMixin implements IAcceleratedVertexConsumer {\n\n\t@Shadow @Final private VertexConsumer   delegate;\n\t@Shadow @Final private int              color;\n\n\t@Unique\n\t@Override\n\tpublic VertexConsumer decorate(VertexConsumer buffer) {\n\t\treturn new AcceleratedEntityOutlineGenerator(buffer, color);\n\t}\n\n\t@Unique\n\t@Override\n\tpublic boolean isAccelerated() {\n\t\treturn delegate\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.isAccelerated\t();\n\t}\n\n\t@Unique\n\t@Override\n\tpublic <T>  void doRender(\n\t\t\tIAcceleratedRenderer<T>\trenderer,\n\t\t\tT\t\t\t\t\t\tcontext,\n\t\t\tMatrix4f\t\t\t\ttransform,\n\t\t\tMatrix3f\t\t\t\tnormal,\n\t\t\tint\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\t\tcolor\n\t) {\n\t\tdelegate\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.doRender\t\t(\n\t\t\t\t\t\tnew DecoratedRenderer<>(renderer, this),\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\ttransform,\n\t\t\t\t\t\tnormal,\n\t\t\t\t\t\tlight,\n\t\t\t\t\t\toverlay,\n\t\t\t\t\t\tcolor\n\t\t\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/MinecraftMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.mixins.buffers;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreBuffersProvider;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.BufferSourceExtension;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.main.GameConfig;\nimport net.minecraft.client.renderer.RenderBuffers;\nimport org.objectweb.asm.Opcodes;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@ExtensionMethod(BufferSourceExtension\t.class)\n@Mixin\t\t\t(Minecraft\t\t\t\t.class)\npublic class MinecraftMixin {\n\n\t@Shadow\n\t@Final\n\tprivate RenderBuffers renderBuffers;\n\n\t@Inject(\n\t\t\tmethod\t= \"<init>\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"FIELD\",\n\t\t\t\t\ttarget\t= \"Lnet/minecraft/client/Minecraft;renderBuffers:Lnet/minecraft/client/renderer/RenderBuffers;\",\n\t\t\t\t\topcode\t= Opcodes.PUTFIELD,\n\t\t\t\t\tshift\t= At.Shift.AFTER\n\t\t\t)\n\t)\n\tpublic void bindAcceleratedBufferSources(GameConfig gameConfig, CallbackInfo ci) {\n\t\tCoreBuffersProvider.bindAcceleratedBufferSources(renderBuffers);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/OutlineBufferSourceMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.mixins.buffers;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAcceleratedBufferSource;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.BufferSourceExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratableBufferSource;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.MultiBufferSource;\nimport net.minecraft.client.renderer.OutlineBufferSource;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.Unique;\n\nimport java.util.function.Supplier;\n\n@ExtensionMethod(BufferSourceExtension.class)\n@Mixin\t\t\t(OutlineBufferSource\t.class)\npublic class OutlineBufferSourceMixin implements IAcceleratableBufferSource {\n\n\t@Shadow @Final private MultiBufferSource.BufferSource outlineBufferSource;\n\n\t@Unique\n\t@Override\n\tpublic Supplier<IAcceleratedBufferSource> getBoundAcceleratedBufferSource() {\n\t\treturn outlineBufferSource\n\t\t\t\t.getAcceleratable\t\t\t\t()\n\t\t\t\t.getBoundAcceleratedBufferSource();\n\t}\n\n\t@Unique\n\t@Override\n\tpublic boolean isBufferSourceAcceleratable() {\n\t\treturn outlineBufferSource\n\t\t\t\t.getAcceleratable\t\t\t()\n\t\t\t\t.isBufferSourceAcceleratable();\n\t}\n\n\t@Unique\n\t@Override\n\tpublic void bindAcceleratedBufferSource(Supplier<IAcceleratedBufferSource> supplier) {\n\t\toutlineBufferSource\n\t\t\t\t.getAcceleratable\t\t\t()\n\t\t\t\t.bindAcceleratedBufferSource(supplier);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/SheetedDecalTextureGeneratorMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.mixins.buffers;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.SheetedDecalTextureRenderer;\nimport com.mojang.blaze3d.vertex.SheetedDecalTextureGenerator;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.experimental.ExtensionMethod;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.Unique;\n\n@ExtensionMethod(VertexConsumerExtension\t\t.class)\n@Mixin\t\t\t(SheetedDecalTextureGenerator\t.class)\npublic class SheetedDecalTextureGeneratorMixin implements IAcceleratedVertexConsumer {\n\n\t@Shadow @Final private VertexConsumer\tdelegate;\n\t@Shadow @Final private Matrix4f\t\t\tcameraInversePose;\n\t@Shadow @Final private Matrix3f\t\t\tnormalInversePose;\n\t@Shadow @Final private float\t\t\ttextureScale;\n\n\t@Unique\n\t@Override\n\tpublic boolean isAccelerated() {\n\t\treturn delegate\n\t\t\t\t.getAccelerated()\n\t\t\t\t.isAccelerated();\n\t}\n\n\t@Unique\n\t@Override\n\tpublic <T>  void doRender(\n\t\t\tIAcceleratedRenderer<T>\trenderer,\n\t\t\tT\t\t\t\t\t\tcontext,\n\t\t\tMatrix4f\t\t\t\ttransform,\n\t\t\tMatrix3f\t\t\t\tnormal,\n\t\t\tint\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\t\tcolor\n\t) {\n\t\tdelegate\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.doRender\t\t(\n\t\t\t\t\t\tnew SheetedDecalTextureRenderer<>(\n\t\t\t\t\t\t\t\trenderer,\n\t\t\t\t\t\t\t\tcameraInversePose,\n\t\t\t\t\t\t\t\tnormalInversePose,\n\t\t\t\t\t\t\t\ttextureScale\n\t\t\t\t\t\t),\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\ttransform,\n\t\t\t\t\t\tnormal,\n\t\t\t\t\t\tlight,\n\t\t\t\t\t\toverlay,\n\t\t\t\t\t\tcolor\n\t\t\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/SpriteCoordinateExpanderMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.mixins.buffers;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedSpriteCoordinateExpander;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.DecoratedRenderer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.SpriteCoordinateExpander;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.Unique;\n\n@ExtensionMethod(VertexConsumerExtension\t.class)\n@Mixin\t\t\t(SpriteCoordinateExpander\t.class)\npublic class SpriteCoordinateExpanderMixin implements IAcceleratedVertexConsumer {\n\n\t@Shadow @Final private VertexConsumer\t\tdelegate;\n\t@Shadow @Final private TextureAtlasSprite\tsprite;\n\n\t@Unique\n\t@Override\n\tpublic VertexConsumer decorate(VertexConsumer buffer) {\n\t\treturn new AcceleratedSpriteCoordinateExpander(buffer, sprite);\n\t}\n\n\t@Unique\n\t@Override\n\tpublic boolean isAccelerated() {\n\t\treturn delegate\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.isAccelerated\t();\n\t}\n\n\t@Unique\n\t@Override\n\tpublic <T>  void doRender(\n\t\t\tIAcceleratedRenderer<T>\trenderer,\n\t\t\tT\t\t\t\t\t\tcontext,\n\t\t\tMatrix4f\t\t\t\ttransform,\n\t\t\tMatrix3f\t\t\t\tnormal,\n\t\t\tint\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\t\tcolor\n\t) {\n\t\tdelegate\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.doRender\t\t(\n\t\t\t\t\t\tnew DecoratedRenderer<>(renderer, this),\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\ttransform,\n\t\t\t\t\t\tnormal,\n\t\t\t\t\t\tlight,\n\t\t\t\t\t\toverlay,\n\t\t\t\t\t\tcolor\n\t\t\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/VertexConsumerMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.mixins.buffers;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Unique;\n\n@Mixin(VertexConsumer.class)\npublic interface VertexConsumerMixin extends IAcceleratedVertexConsumer {\n\n\t@Unique\n\t@Override\n\tdefault boolean isAccelerated() {\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/VertexDoubleConsumerMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.mixins.buffers;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.experimental.ExtensionMethod;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.Unique;\n\n@ExtensionMethod(VertexConsumerExtension.class)\n@Mixin\t\t\t(targets = \"com.mojang.blaze3d.vertex.VertexMultiConsumer$Double\")\npublic class VertexDoubleConsumerMixin implements IAcceleratedVertexConsumer {\n\n\t@Shadow @Final private VertexConsumer first;\n\t@Shadow @Final private VertexConsumer second;\n\n\t@Unique\n\t@Override\n\tpublic boolean isAccelerated() {\n\t\treturn \t\tfirst\t.getAccelerated().isAccelerated()\n\t\t\t\t&&\tsecond\t.getAccelerated().isAccelerated();\n\t}\n\n\t@Unique\n\t@Override\n\tpublic <T>  void doRender(\n\t\t\tIAcceleratedRenderer<T>\trenderer,\n\t\t\tT\t\t\t\t\t\tcontext,\n\t\t\tMatrix4f\t\t\t\ttransform,\n\t\t\tMatrix3f\t\t\t\tnormal,\n\t\t\tint\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\t\tcolor\n\t) {\n\t\tfirst\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.doRender\t\t(\n\t\t\t\t\t\trenderer,\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\ttransform,\n\t\t\t\t\t\tnormal,\n\t\t\t\t\t\tlight,\n\t\t\t\t\t\toverlay,\n\t\t\t\t\t\tcolor\n\t\t\t\t);\n\t\tsecond\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.doRender\t\t(\n\t\t\t\t\t\trenderer,\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\ttransform,\n\t\t\t\t\t\tnormal,\n\t\t\t\t\t\tlight,\n\t\t\t\t\t\toverlay,\n\t\t\t\t\t\tcolor\n\t\t\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/VertexMultipleConsumerMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.mixins.buffers;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.experimental.ExtensionMethod;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.Unique;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@ExtensionMethod(VertexConsumerExtension.class)\n@Mixin\t\t\t(targets = \"com.mojang.blaze3d.vertex.VertexMultiConsumer$Multiple\")\npublic class VertexMultipleConsumerMixin implements IAcceleratedVertexConsumer {\n\n\t@Shadow @Final private\tVertexConsumer[]\tdelegates;\n\n\t@Unique private\t\t\tboolean\t\t\t\taccelerated = true;\n\n\t@Inject(\n\t\t\tmethod\t= \"<init>\",\n\t\t\tat\t\t= @At(\"TAIL\")\n\t)\n\tpublic void constructor(VertexConsumer[] delegates, CallbackInfo ci) {\n\t\tfor (var delegate : delegates) {\n\t\t\taccelerated = accelerated && delegate\n\t\t\t\t\t.getAccelerated\t()\n\t\t\t\t\t.isAccelerated\t();\n\t\t}\n\t}\n\n\t@Unique\n\t@Override\n\tpublic boolean isAccelerated() {\n\t\treturn accelerated;\n\t}\n\n\t@Unique\n\t@Override\n\tpublic <T>  void doRender(\n\t\t\tIAcceleratedRenderer<T>\trenderer,\n\t\t\tT\t\t\t\t\t\tcontext,\n\t\t\tMatrix4f\t\t\t\ttransform,\n\t\t\tMatrix3f\t\t\t\tnormal,\n\t\t\tint\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\t\tcolor\n\t) {\n\t\tfor (var delegate : delegates) {\n\t\t\tdelegate\n\t\t\t\t\t.getAccelerated\t()\n\t\t\t\t\t.doRender\t\t(\n\t\t\t\t\t\t\trenderer,\n\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\ttransform,\n\t\t\t\t\t\t\tnormal,\n\t\t\t\t\t\t\tlight,\n\t\t\t\t\t\t\toverlay,\n\t\t\t\t\t\t\tcolor\n\t\t\t\t\t);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/compatibility/MinecraftMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.mixins.compatibility;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.backends.DebugOutput;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.main.GameConfig;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@Mixin(Minecraft.class)\npublic class MinecraftMixin {\n\n    @Inject(\n            method  = \"<init>\",\n            at      = @At(\"TAIL\")\n    )\n    public void setDebugContext(GameConfig gameConfig, CallbackInfo ci) {\n        if (\t\tCoreFeature.isConfigLoaded\t\t\t()\n\t\t\t\t&&\tCoreFeature.isDebugContextEnabled\t()\n\t\t) {\n            DebugOutput.enable();\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/compatibility/ParticleEngineMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.mixins.compatibility;\n\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature;\nimport net.minecraft.client.Camera;\nimport net.minecraft.client.particle.ParticleEngine;\nimport net.minecraft.client.particle.ParticleRenderType;\nimport net.minecraft.client.renderer.LightTexture;\nimport net.minecraft.client.renderer.culling.Frustum;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\nimport java.util.function.Predicate;\n\n@Mixin(ParticleEngine.class)\npublic class ParticleEngineMixin {\n\n\t@Inject(\n\t\t\tmethod\t= \"render(Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/culling/Frustum;Ljava/util/function/Predicate;)V\",\n\t\t\tat\t\t= @At(\"HEAD\")\n\t)\n\tpublic void disableParticleAcceleration(\n\t\t\tLightTexture\t\t\t\t\tlightTexture,\n\t\t\tCamera\t\t\t\t\t\t\tcamera,\n\t\t\tfloat\t\t\t\t\t\t\tpartialTick,\n\t\t\tFrustum\t\t\t\t\t\t\tfrustum,\n\t\t\tPredicate<ParticleRenderType>\trenderTypePredicate,\n\t\t\tCallbackInfo\t\t\t\t\tci\n\t) {\n\t\tAcceleratedEntityRenderingFeature\t.useVanillaPipeline();\n\t\tAcceleratedItemRenderingFeature\t\t.useVanillaPipeline();\n\t\tAcceleratedTextRenderingFeature\t\t.useVanillaPipeline();\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"render(Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/culling/Frustum;Ljava/util/function/Predicate;)V\",\n\t\t\tat\t\t= @At(\"RETURN\")\n\t)\n\tpublic void resetParticleAcceleration(\n\t\t\tLightTexture\t\t\t\t\tlightTexture,\n\t\t\tCamera\t\t\t\t\t\t\tcamera,\n\t\t\tfloat\t\t\t\t\t\t\tpartialTick,\n\t\t\tFrustum\t\t\t\t\t\t\tfrustum,\n\t\t\tPredicate<ParticleRenderType>\trenderTypePredicate,\n\t\t\tCallbackInfo\t\t\t\t\tci\n\t) {\n\t\tAcceleratedEntityRenderingFeature\t.resetPipeline();\n\t\tAcceleratedItemRenderingFeature\t\t.resetPipeline();\n\t\tAcceleratedTextRenderingFeature\t\t.resetPipeline();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/compatibility/RenderTypeMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.mixins.compatibility;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport com.mojang.datafixers.util.Pair;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.resources.ResourceLocation;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Unique;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\n@Mixin(RenderType.class)\npublic class RenderTypeMixin {\n\n\t@Unique private static final Map<Pair<ResourceLocation, Integer>, RenderType> ENERGY_SWIRL\t= new ConcurrentHashMap<>();\n\t@Unique private static final Map<Pair<ResourceLocation, Integer>, RenderType> BREEZE_WIND\t= new ConcurrentHashMap<>();\n\n\t@WrapMethod(method = \"energySwirl\")\n\tprivate static RenderType cacheEnergySwirl(\n\t\t\tResourceLocation\t\tlocation,\n\t\t\tfloat\t\t\t\t\tu,\n\t\t\tfloat\t\t\t\t\tv,\n\t\t\tOperation<RenderType>\toriginal\n\t) {\n\t\treturn ENERGY_SWIRL.computeIfAbsent(Pair.of(location, CoreFeature.packDynamicUV(u, v)), pair -> original.call(\n\t\t\t\tlocation,\n\t\t\t\tCoreFeature.unpackDynamicU(pair.getSecond()),\n\t\t\t\tCoreFeature.unpackDynamicV(pair.getSecond())\n\t\t));\n\t}\n\n\t@WrapMethod(method = \"breezeWind\")\n\tprivate static RenderType cacheBreezeWind(\n\t\t\tResourceLocation\t\tlocation,\n\t\t\tfloat\t\t\t\t\tu,\n\t\t\tfloat\t\t\t\t\tv,\n\t\t\tOperation<RenderType>\toriginal\n\t) {\n\t\treturn BREEZE_WIND.computeIfAbsent(Pair.of(location, CoreFeature.packDynamicUV(u, v)), pair -> original.call(\n\t\t\t\tlocation,\n\t\t\t\tCoreFeature.unpackDynamicU(pair.getSecond()),\n\t\t\t\tCoreFeature.unpackDynamicV(pair.getSecond())\n\t\t));\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/compatibility/WindowMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.mixins.compatibility;\n\nimport com.mojang.blaze3d.platform.Window;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.Constant;\nimport org.spongepowered.asm.mixin.injection.ModifyConstant;\n\n@Mixin(Window.class)\npublic class WindowMixin {\n\n\t@ModifyConstant(\n\t\t\tmethod\t\t= \"<init>\",\n\t\t\tconstant\t= @Constant(\n\t\t\t\t\tintValue\t= 3,\n\t\t\t\t\tordinal\t\t= 0\n\t\t\t)\n\t)\n\tpublic int modifyGlMajorVersion(int value) {\n\t\treturn 4;\n\t}\n\n\t@ModifyConstant(\n\t\t\tmethod\t\t= \"<init>\",\n\t\t\tconstant\t= @Constant(\n\t\t\t\t\tintValue\t= 2,\n\t\t\t\t\tordinal\t\t= 0\n\t\t\t)\n\t)\n\tpublic int modifyGlMinorVersion(int value) {\n\t\treturn 6;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/ComputeShaderDefinition.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs;\n\nimport net.minecraft.resources.ResourceLocation;\n\npublic record ComputeShaderDefinition(ResourceLocation location, int barrierFlags) {\n\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/ComputeShaderProgramLoader.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.programs.ComputeProgram;\nimport com.github.argon4w.acceleratedrendering.core.backends.programs.ComputeShader;\nimport com.mojang.blaze3d.systems.RenderSystem;\nimport it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;\nimport net.minecraft.CrashReport;\nimport net.minecraft.ReportedException;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.packs.resources.ResourceManager;\nimport net.minecraft.server.packs.resources.SimplePreparableReloadListener;\nimport net.minecraft.util.profiling.ProfilerFiller;\nimport net.neoforged.fml.ModLoader;\nimport org.apache.commons.io.IOUtils;\n\nimport java.nio.charset.StandardCharsets;\nimport java.util.Map;\n\npublic class ComputeShaderProgramLoader extends SimplePreparableReloadListener<Map<ResourceLocation, ComputeShaderProgramLoader.ShaderSource>> {\n\n\tpublic\tstatic final\tComputeShaderProgramLoader\t\t\t\tINSTANCE\t\t= new ComputeShaderProgramLoader();\n\tprivate\tstatic final\tMap<ResourceLocation, ComputeProgram>\tCOMPUTE_SHADERS\t= new Object2ObjectOpenHashMap<>();\n\tprivate\tstatic\t\t\tboolean\t\t\t\t\t\t\t\t\tLOADED\t\t\t= false;\n\n\t@Override\n\tprotected Map<ResourceLocation, ShaderSource> prepare(ResourceManager resourceManager, ProfilerFiller profiler) {\n\t\ttry {\n\t\t\tvar shaderSources\t= new Object2ObjectOpenHashMap<ResourceLocation, ShaderSource>\t\t();\n\t\t\tvar shaderLocations\t= ModLoader.postEventWithReturn(new LoadComputeShaderEvent()).build\t();\n\n\t\t\tfor (ResourceLocation key : shaderLocations.keySet()) {\n\t\t\t\tvar definition\t\t\t= shaderLocations\t.get\t\t\t(key);\n\t\t\t\tvar resourceLocation\t= definition\t\t.location\t\t();\n\t\t\t\tvar barrierFlags\t\t= definition\t\t.barrierFlags\t();\n\n\t\t\t\tif (resourceLocation == null) {\n\t\t\t\t\tthrow new IllegalStateException(\"Found empty shader location on: \\\"\" + key + \"\\\"\");\n\t\t\t\t}\n\n\t\t\t\tvar resource = resourceManager.getResource(resourceLocation);\n\n\t\t\t\tif (resource.isEmpty()) {\n\t\t\t\t\tthrow new IllegalStateException(\"Cannot found compute shader: \\\"\" + resourceLocation + \"\\\"\");\n\t\t\t\t}\n\n\t\t\t\ttry (var stream = resource.get().open()) {\n\t\t\t\t\tshaderSources.put(key, new ShaderSource(IOUtils.toString(stream, StandardCharsets.UTF_8), barrierFlags));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn shaderSources;\n\t\t} catch (Exception e) {\n\t\t\tthrow new ReportedException(CrashReport.forThrowable(e, \"Exception while loading compute shader\"));\n\t\t}\n\t}\n\n\t@Override\n\tprotected void apply(\n\t\t\tMap<ResourceLocation, ShaderSource>\tshaderSources,\n\t\t\tResourceManager\t\t\t\t\t\tresourceManager,\n\t\t\tProfilerFiller\t\t\t\t\t\tprofiler\n\t) {\n\t\tRenderSystem.recordRenderCall(() -> {\n\t\t\ttry {\n\t\t\t\tfor (var key : shaderSources.keySet()) {\n\t\t\t\t\tvar source\t\t\t= shaderSources\t.get(key);\n\t\t\t\t\tvar shaderSource\t= source\t\t.source;\n\t\t\t\t\tvar barrierFlags\t= source\t\t.barrierFlags;\n\n\t\t\t\t\tvar program\t\t\t= new ComputeProgram(barrierFlags);\n\t\t\t\t\tvar computeShader\t= new ComputeShader\t();\n\n\t\t\t\t\tcomputeShader.setShaderSource\t(shaderSource);\n\t\t\t\t\tcomputeShader.compileShader\t\t();\n\n\t\t\t\t\tif (!computeShader.isCompiled()) {\n\t\t\t\t\t\tthrow new IllegalStateException(\"Shader \\\"\" + key + \"\\\" failed to compile because of the following errors: \" + computeShader.getInfoLog());\n\t\t\t\t\t}\n\n\t\t\t\t\tprogram.attachShader(computeShader);\n\t\t\t\t\tprogram.linkProgram\t();\n\n\t\t\t\t\tif (!program.isLinked()) {\n\t\t\t\t\t\tthrow new IllegalStateException(\"Program \\\"\" + key + \"\\\" failed to link because of the following errors: \" + program.getInfoLog());\n\t\t\t\t\t}\n\n\t\t\t\t\tcomputeShader\t.delete\t();\n\t\t\t\t\tCOMPUTE_SHADERS\t.put\t(key, program);\n\t\t\t\t}\n\t\t\t} catch (Exception e) {\n\t\t\t\tthrow new ReportedException(CrashReport.forThrowable(e, \"Exception while compiling/linking compute shader\"));\n\t\t\t} finally {\n\t\t\t\tLOADED = true;\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic static ComputeProgram getProgram(ResourceLocation resourceLocation) {\n\t\tvar program = COMPUTE_SHADERS.get(resourceLocation);\n\n\t\tif (program == null) {\n\t\t\tthrow new IllegalStateException(\"Get shader program \\\"\"+ resourceLocation + \"\\\" too early! Program is not loaded yet!\");\n\t\t}\n\n\t\treturn program;\n\t}\n\n\tpublic static void delete() {\n\t\tfor (var program : COMPUTE_SHADERS.values()) {\n\t\t\tprogram.delete();\n\t\t}\n\n\t\tLOADED\t= false;\n\t}\n\n\tpublic static boolean isProgramsLoaded() {\n\t\treturn LOADED;\n\t}\n\n\tpublic record ShaderSource(String source, int barrierFlags) {\n\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/ComputeShaderPrograms.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs;\n\nimport com.github.argon4w.acceleratedrendering.AcceleratedRenderingModEntry;\nimport com.github.argon4w.acceleratedrendering.core.backends.programs.BarrierFlags;\nimport com.github.argon4w.acceleratedrendering.core.utils.ResourceLocationUtils;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.api.distmarker.Dist;\nimport net.neoforged.bus.api.SubscribeEvent;\nimport net.neoforged.fml.common.EventBusSubscriber;\nimport net.neoforged.neoforge.client.event.RegisterClientReloadListenersEvent;\n\n@EventBusSubscriber(\n\t\tmodid\t= AcceleratedRenderingModEntry\t.MOD_ID,\n\t\tbus\t\t= EventBusSubscriber.Bus\t\t.MOD,\n\t\tvalue\t= Dist\t\t\t\t\t\t\t.CLIENT\n)\npublic class ComputeShaderPrograms {\n\n\tpublic static final ResourceLocation CORE_BLOCK_VERTEX_TRANSFORM_KEY\t\t\t\t= ResourceLocationUtils.create(\"core_block_vertex_transform\");\n\tpublic static final ResourceLocation CORE_ENTITY_VERTEX_TRANSFORM_KEY\t\t\t\t= ResourceLocationUtils.create(\"core_entity_vertex_transform\");\n\tpublic static final ResourceLocation CORE_POS_VERTEX_TRANSFORM_KEY\t\t\t\t\t= ResourceLocationUtils.create(\"core_pos_vertex_transform\");\n\tpublic static final ResourceLocation CORE_POS_COLOR_VERTEX_TRANSFORM_KEY\t\t\t= ResourceLocationUtils.create(\"core_pos_color_vertex_transform\");\n\tpublic static final ResourceLocation CORE_POS_TEX_VERTEX_TRANSFORM_KEY\t\t\t\t= ResourceLocationUtils.create(\"core_pos_tex_vertex_transform\");\n\tpublic static final ResourceLocation CORE_POS_TEX_COLOR_VERTEX_TRANSFORM_KEY\t\t= ResourceLocationUtils.create(\"core_pos_tex_color_vertex_transform\");\n\tpublic static final ResourceLocation CORE_POS_COLOR_TEX_LIGHT_VERTEX_TRANSFORM_KEY\t= ResourceLocationUtils.create(\"core_pos_color_tex_light_vertex_transform\");\n\tpublic static final ResourceLocation CORE_PASS_THROUGH_QUAD_CULLING_KEY\t\t\t\t= ResourceLocationUtils.create(\"core_pass_through_quad_culling\");\n\tpublic static final ResourceLocation CORE_PASS_THROUGH_TRIANGLE_CULLING_KEY\t\t\t= ResourceLocationUtils.create(\"core_pass_through_triangle_culling\");\n\tpublic static final ResourceLocation CORE_BLOCK_MESH_UPLOADING_KEY\t\t\t\t\t= ResourceLocationUtils.create(\"core_block_mesh_uploading_key\");\n\tpublic static final ResourceLocation CORE_ENTITY_MESH_UPLOADING_KEY\t\t\t\t\t= ResourceLocationUtils.create(\"core_entity_mesh_uploading\");\n\tpublic static final ResourceLocation CORE_POS_MESH_UPLOADING_KEY\t\t\t\t\t= ResourceLocationUtils.create(\"core_pos_mesh_uploading\");\n\tpublic static final ResourceLocation CORE_POS_COLOR_MESH_UPLOADING_KEY\t\t\t\t= ResourceLocationUtils.create(\"core_pos_color_mesh_uploading\");\n\tpublic static final ResourceLocation CORE_POS_TEX_MESH_UPLOADING_KEY\t\t\t\t= ResourceLocationUtils.create(\"core_pos_tex_mesh_uploading\");\n\tpublic static final ResourceLocation CORE_POS_TEX_COLOR_MESH_UPLOADING_KEY\t\t\t= ResourceLocationUtils.create(\"core_pos_tex_color_mesh_uploading\");\n\tpublic static final ResourceLocation CORE_POS_COLOR_TEX_LIGHT_MESH_UPLOADING_KEY\t= ResourceLocationUtils.create(\"core_pos_color_tex_light_mesh_uploading\");\n\n\t@SubscribeEvent\n\tpublic static void onLoadComputeShaders(LoadComputeShaderEvent event) {\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_BLOCK_VERTEX_TRANSFORM_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/transform/block_vertex_transform_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_ENTITY_VERTEX_TRANSFORM_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/transform/entity_vertex_transform_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_POS_VERTEX_TRANSFORM_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/transform/pos_vertex_transform_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_POS_COLOR_VERTEX_TRANSFORM_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/transform/pos_color_vertex_transform_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_POS_TEX_VERTEX_TRANSFORM_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/transform/pos_tex_vertex_transform_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_POS_TEX_COLOR_VERTEX_TRANSFORM_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/transform/pos_tex_color_vertex_transform_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_POS_COLOR_TEX_LIGHT_VERTEX_TRANSFORM_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/transform/pos_color_tex_light_vertex_transform_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_PASS_THROUGH_QUAD_CULLING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/culling/pass_through_quad_culling_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE,\n\t\t\t\tBarrierFlags\t\t\t.ATOMIC_COUNTER\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_PASS_THROUGH_TRIANGLE_CULLING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/culling/pass_through_triangle_culling_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE,\n\t\t\t\tBarrierFlags\t\t\t.ATOMIC_COUNTER\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_BLOCK_MESH_UPLOADING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/uploading/block_mesh_uploading_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_ENTITY_MESH_UPLOADING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/uploading/entity_mesh_uploading_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_POS_MESH_UPLOADING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/uploading/pos_mesh_uploading_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_POS_COLOR_MESH_UPLOADING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/uploading/pos_color_mesh_uploading_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_POS_TEX_MESH_UPLOADING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/uploading/pos_tex_mesh_uploading_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_POS_TEX_COLOR_MESH_UPLOADING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/uploading/pos_tex_color_mesh_uploading_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_POS_COLOR_TEX_LIGHT_MESH_UPLOADING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/uploading/pos_color_tex_light_mesh_uploading_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE\n\t\t);\n\t}\n\n\t@SubscribeEvent\n\tpublic static void onRegisterResourceReloadListeners(RegisterClientReloadListenersEvent event) {\n\t\tevent.registerReloadListener(ComputeShaderProgramLoader.INSTANCE);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/LoadComputeShaderEvent.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.programs.BarrierFlags;\nimport com.google.common.collect.ImmutableMap;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.bus.api.Event;\nimport net.neoforged.fml.event.IModBusEvent;\n\nimport java.util.Map;\n\npublic class LoadComputeShaderEvent extends Event implements IModBusEvent {\n\n\tprivate final ImmutableMap.Builder<ResourceLocation, ComputeShaderDefinition> shaderLocations;\n\n\tpublic LoadComputeShaderEvent() {\n\t\tthis.shaderLocations = ImmutableMap.builder();\n\t}\n\n\tpublic void loadComputeShader(\n\t\t\tResourceLocation\tkey,\n\t\t\tResourceLocation\tlocation,\n\t\t\tBarrierFlags...\t\tbarrierFlags\n\t) {\n\t\tshaderLocations.put(key, new ComputeShaderDefinition(location, BarrierFlags.getFlags(barrierFlags)));\n\t}\n\n\tpublic Map<ResourceLocation, ComputeShaderDefinition> build() {\n\t\treturn shaderLocations.build();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/culling/ICullingProgramDispatcher.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs.culling;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder;\n\npublic interface ICullingProgramDispatcher {\n\n\tint\t\tdispatch\t(AcceleratedBufferBuilder builder);\n\tboolean\tshouldCull\t();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/culling/ICullingProgramSelector.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs.culling;\n\nimport net.minecraft.client.renderer.RenderType;\n\npublic interface ICullingProgramSelector {\n\n\tICullingProgramDispatcher select(RenderType renderType);\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/culling/LoadCullingProgramSelectorEvent.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs.culling;\n\nimport com.mojang.blaze3d.vertex.VertexFormat;\nimport lombok.Getter;\nimport net.neoforged.bus.api.Event;\nimport net.neoforged.fml.event.IModBusEvent;\n\nimport java.util.function.UnaryOperator;\n\npublic class LoadCullingProgramSelectorEvent extends Event implements IModBusEvent {\n\n\tprivate final\tVertexFormat\t\t\tvertexFormat;\n\n\t@Getter private ICullingProgramSelector\tselector;\n\n\tpublic LoadCullingProgramSelectorEvent(VertexFormat vertexFormat) {\n\t\tthis.vertexFormat\t= vertexFormat;\n\t\tthis.selector\t\t= PassThroughCullingProgramSelector.INSTANCE;\n\t}\n\n\tpublic void loadFor(VertexFormat vertexFormat, UnaryOperator<ICullingProgramSelector> selector) {\n\t\tif (this.vertexFormat == vertexFormat) {\n\t\t\tthis.selector = selector.apply(this.selector);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/culling/PassThroughCullingProgramDispatcher.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs.culling;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.programs.ComputeProgram;\nimport com.github.argon4w.acceleratedrendering.core.backends.programs.Uniform;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder;\nimport com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderProgramLoader;\nimport com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderPrograms;\nimport com.mojang.blaze3d.vertex.VertexFormat;\nimport net.minecraft.resources.ResourceLocation;\n\npublic class PassThroughCullingProgramDispatcher implements ICullingProgramDispatcher {\n\n\tpublic\tstatic\tfinal\t\tPassThroughCullingProgramDispatcher\tQUAD\t\t\t\t= new PassThroughCullingProgramDispatcher(VertexFormat.Mode.QUADS,\t\tComputeShaderPrograms.CORE_PASS_THROUGH_QUAD_CULLING_KEY);\n\tpublic\tstatic\tfinal\t\tPassThroughCullingProgramDispatcher\tTRIANGLE\t\t\t= new PassThroughCullingProgramDispatcher(VertexFormat.Mode.TRIANGLES,\tComputeShaderPrograms.CORE_PASS_THROUGH_TRIANGLE_CULLING_KEY);\n\tprivate static\tfinal\t\tint\t\t\t\t\t\t\t\t\tGROUP_SIZE\t\t\t= 128;\n\tprivate static\tfinal\t\tint\t\t\t\t\t\t\t\t\tDISPATCH_COUNT_Y_Z\t= 1;\n\n\tprivate final VertexFormat.Mode\tmode;\n\tprivate final ComputeProgram\tprogram;\n\tprivate final Uniform\t\t\tpolygonCountUniform;\n\tprivate final Uniform\t\t\tvertexOffsetUniform;\n\n\tpublic PassThroughCullingProgramDispatcher(VertexFormat.Mode mode, ResourceLocation key) {\n\t\tthis.mode\t\t\t\t\t= mode;\n\t\tthis.program\t\t\t\t= ComputeShaderProgramLoader.getProgram(key);\n\t\tthis.polygonCountUniform\t= program\t\t\t\t\t.getUniform(\"polygonCount\");\n\t\tthis.vertexOffsetUniform\t= program\t\t\t\t\t.getUniform(\"vertexOffset\");\n\t}\n\n\t@Override\n\tpublic int dispatch(AcceleratedBufferBuilder builder) {\n\t\tvar vertexCount\t\t= builder\t\t\t.getTotalVertexCount();\n\t\tvar polygonCount\t= vertexCount / mode.primitiveLength;\n\n\t\tpolygonCountUniform.uploadUnsignedInt(polygonCount);\n\t\tvertexOffsetUniform.uploadUnsignedInt((int) (builder.getVertexBuffer().getOffset() / builder.getVertexSize()));\n\n\t\tprogram.useProgram\t();\n\t\tprogram.dispatch\t(\n\t\t\t\t(polygonCount + GROUP_SIZE - 1) / GROUP_SIZE,\n\t\t\t\tDISPATCH_COUNT_Y_Z,\n\t\t\t\tDISPATCH_COUNT_Y_Z\n\t\t);\n\n\t\treturn program.getBarrierFlags();\n\t}\n\n\t@Override\n\tpublic boolean shouldCull() {\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/culling/PassThroughCullingProgramSelector.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs.culling;\n\nimport net.minecraft.client.renderer.RenderType;\n\npublic class PassThroughCullingProgramSelector implements ICullingProgramSelector {\n\n\tpublic static final ICullingProgramSelector\tINSTANCE = new PassThroughCullingProgramSelector();\n\n\t@Override\n\tpublic ICullingProgramDispatcher select(RenderType renderType) {\n\t\treturn switch (renderType.mode) {\n\t\t\tcase QUADS\t\t-> PassThroughCullingProgramDispatcher.QUAD;\n\t\t\tcase TRIANGLES\t-> PassThroughCullingProgramDispatcher.TRIANGLE;\n\t\t\tdefault\t\t\t-> throw new IllegalArgumentException(\"Unsupported mode: \" + renderType.mode);\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/dispatchers/EmptyProgramDispatcher.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs.dispatchers;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder;\n\npublic class EmptyProgramDispatcher implements IPolygonProgramDispatcher {\n\n\tpublic static final EmptyProgramDispatcher INSTANCE = new EmptyProgramDispatcher();\n\n\t@Override\n\tpublic int dispatch(AcceleratedBufferBuilder builder) {\n\t\treturn 0;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/dispatchers/FixedPolygonProgramDispatcher.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs.dispatchers;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.programs.ComputeProgram;\nimport com.github.argon4w.acceleratedrendering.core.backends.programs.Uniform;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder;\nimport com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderProgramLoader;\nimport com.mojang.blaze3d.vertex.VertexFormat;\nimport net.minecraft.resources.ResourceLocation;\n\npublic class FixedPolygonProgramDispatcher implements IPolygonProgramDispatcher {\n\n\tprivate static\tfinal int\t\t\t\tGROUP_SIZE\t\t\t\t= 128;\n\tprivate static\tfinal int\t\t\t\tDISPATCH_COUNT_Y_Z\t\t= 1;\n\n\tprivate\t\t\tfinal VertexFormat.Mode\tmode;\n\tprivate\t\t\tfinal ComputeProgram\tprogram;\n\tprivate\t\t\tfinal Uniform\t\t\tpolygonCountUniform;\n\tprivate\t\t\tfinal Uniform\t\t\tvertexOffsetUniform;\n\n\tpublic FixedPolygonProgramDispatcher(VertexFormat.Mode mode, ResourceLocation key) {\n\t\tthis.mode\t\t\t\t\t= mode;\n\t\tthis.program\t\t\t\t= ComputeShaderProgramLoader.getProgram(key);\n\t\tthis.polygonCountUniform\t= this.program\t\t\t\t.getUniform(\"polygonCount\");\n\t\tthis.vertexOffsetUniform\t= this.program\t\t\t\t.getUniform(\"vertexOffset\");\n\t}\n\n\t@Override\n\tpublic int dispatch(AcceleratedBufferBuilder builder) {\n\t\tvar vertexCount\t\t= builder\t\t\t.getTotalVertexCount();\n\t\tvar polygonCount\t= vertexCount / mode.primitiveLength;\n\n\t\tpolygonCountUniform.uploadUnsignedInt(polygonCount);\n\t\tvertexOffsetUniform.uploadUnsignedInt((int) (builder.getVertexBuffer().getOffset() / builder.getVertexSize()));\n\n\t\tprogram.useProgram\t();\n\t\tprogram.dispatch\t(\n\t\t\t\t(polygonCount + GROUP_SIZE - 1) / GROUP_SIZE,\n\t\t\t\tDISPATCH_COUNT_Y_Z,\n\t\t\t\tDISPATCH_COUNT_Y_Z\n\t\t);\n\n\t\treturn program.getBarrierFlags();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/dispatchers/IPolygonProgramDispatcher.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs.dispatchers;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder;\n\npublic interface IPolygonProgramDispatcher {\n\n\tint dispatch(AcceleratedBufferBuilder builder);\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/dispatchers/MeshUploadingProgramDispatcher.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs.dispatchers;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.buffers.IServerBuffer;\nimport com.github.argon4w.acceleratedrendering.core.backends.programs.ComputeProgram;\nimport com.github.argon4w.acceleratedrendering.core.backends.programs.Uniform;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.AcceleratedRingBuffers;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.MeshUploaderPool;\nimport com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderProgramLoader;\nimport com.github.argon4w.acceleratedrendering.core.programs.overrides.IUploadingShaderProgramOverride;\nimport it.unimi.dsi.fastutil.objects.Reference2ObjectLinkedOpenHashMap;\nimport it.unimi.dsi.fastutil.objects.ReferenceArrayList;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.util.FastColor;\n\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.lwjgl.opengl.GL46.*;\n\npublic class MeshUploadingProgramDispatcher {\n\n\tprivate static\tfinal\tint\t\t\t\t\t\t\t\t\t\t\t\t\t\tGROUP_SIZE\t\t\t\t\t= 128;\n\tprivate static\tfinal\tint\t\t\t\t\t\t\t\t\t\t\t\t\t\tDISPATCH_COUNT_Y_Z\t\t\t= 1;\n\tpublic static\tfinal\tint\t\t\t\t\t\t\t\t\t\t\t\t\t\tSPARSE_MESH_BUFFER_INDEX\t= 5;\n\tpublic static\tfinal\tint\t\t\t\t\t\t\t\t\t\t\t\t\t\tMESH_BUFFER_INDEX\t\t\t= 7;\n\n\tprivate\t\t\tfinal\tMap<IServerBuffer, List<MeshUploaderPool.MeshUploader>>\tdenseUploaders;\n\tprivate\t\t\tfinal\tMap<IServerBuffer, List<MeshUploaderPool.MeshUploader>>\tsparseUploaders;\n\n\tprivate\t\t\t\t\tIUploadingShaderProgramOverride\t\t\t\t\t\t\tlastOverride;\n\tprivate\t\t\t\t\tint\t\t\t\t\t\t\t\t\t\t\t\t\t\tlastBarriers;\n\n\tpublic MeshUploadingProgramDispatcher() {\n\t\tthis.denseUploaders\t\t= new Reference2ObjectLinkedOpenHashMap<>();\n\t\tthis.sparseUploaders\t= new Reference2ObjectLinkedOpenHashMap<>();\n\t\tthis.lastOverride\t\t= null;\n\t\tthis.lastBarriers\t\t= GL_SHADER_STORAGE_BARRIER_BIT;\n\t}\n\n\tpublic void dispatch(Collection<AcceleratedBufferBuilder> builders, AcceleratedRingBuffers.Buffers buffer) {\n\t\tglMemoryBarrier(lastBarriers);\n\n\t\tlastOverride\t= null;\n\t\tvar transform\t= buffer\n\t\t\t\t.getBufferEnvironment\t\t\t\t()\n\t\t\t\t.selectTransformProgramDispatcher\t();\n\n\t\tfor (var builder : builders) {\n\t\t\tvar vertexBuffer\t= builder\t.getVertexBuffer\t();\n\t\t\tvar varyingBuffer\t= builder\t.getVaryingBuffer\t();\n\t\t\tvar meshVertexCount = builder\t.getMeshVertexCount\t();\n\n\t\t\tvertexBuffer\t\t\t\t\t.reserve\t\t\t(meshVertexCount * builder.getVertexSize\t());\n\t\t\tvaryingBuffer\t\t\t\t\t.reserve\t\t\t(meshVertexCount * builder.getVaryingSize\t());\n\t\t\tvertexBuffer\t\t\t\t\t.allocateOffset\t\t();\n\t\t\tvaryingBuffer\t\t\t\t\t.allocateOffset\t\t();\n\t\t}\n\n\t\tbuffer.prepare\t\t\t\t();\n\t\tbuffer.bindTransformBuffers\t();\n\n\t\tfor (var builder : builders) {\n\t\t\tvar offset\t\t\t= 0;\n\t\t\tvar sparseStart\t\t= 0;\n\n\t\t\tvar vertexBuffer\t= builder\t\t.getVertexBuffer\t();\n\t\t\tvar varyingBuffer\t= builder\t\t.getVaryingBuffer\t();\n\t\t\tvar vertexCount\t\t= builder\t\t.getVertexCount\t\t();\n\n\t\t\tvar vertexAddress\t= vertexBuffer\t.getCurrent\t\t\t();\n\t\t\tvar varyingAddress\t= varyingBuffer\t.getCurrent\t\t\t();\n\t\t\tvar vertexOffset\t= vertexBuffer\t.getOffset\t\t\t() / builder.getVertexSize\t();\n\t\t\tvar varyingOffset\t= varyingBuffer\t.getOffset\t\t\t() / builder.getVaryingSize\t();\n\n\t\t\tfor (var uploader : builder\n\t\t\t\t\t.getMeshUploaders\t()\n\t\t\t\t\t.values\t\t\t\t()\n\t\t\t) {\n\t\t\t\tvar serverMesh\t= uploader\t\t\t\t\t.getServerMesh\t();\n\t\t\t\tvar meshCount\t= uploader.getMeshInfos()\t.getMeshCount\t();\n\t\t\t\tvar meshDense\t= serverMesh\t\t\t\t.forceDense\t\t() || meshCount >= 128;\n\t\t\t\tvar meshBuffer\t= serverMesh\t\t\t\t.meshBuffer\t\t();\n\t\t\t\tvar dense\t\t= denseUploaders\t\t\t.get\t\t\t(meshBuffer);\n\t\t\t\tvar sparse\t\t= sparseUploaders\t\t\t.get\t\t\t(meshBuffer);\n\n\t\t\t\tif (dense == null) {\n\t\t\t\t\tdense\t= new ReferenceArrayList<>\t();\n\t\t\t\t\tsparse\t= new ReferenceArrayList<>\t();\n\t\t\t\t\tdenseUploaders\t.put\t\t\t\t(meshBuffer, dense);\n\t\t\t\t\tsparseUploaders\t.put\t\t\t\t(meshBuffer, sparse);\n\t\t\t\t}\n\n\t\t\t\t(meshDense\n\t\t\t\t\t\t? dense\n\t\t\t\t\t\t: sparse).add(uploader);\n\t\t\t}\n\n\t\t\tfor (\t\tvar meshBuffer\t: sparseUploaders.keySet()) {\n\t\t\t\tfor (\tvar uploader\t: sparseUploaders.get\t(meshBuffer)) {\n\t\t\t\t\tvar mesh\t\t= uploader\t.getServerMesh\t();\n\t\t\t\t\tvar meshInfos\t= uploader\t.getMeshInfos\t();\n\t\t\t\t\tvar meshCount\t= meshInfos\t.getMeshCount\t();\n\t\t\t\t\tvar meshSize\t= mesh\t\t.size\t\t\t();\n\n\t\t\t\t\tfor (var i = 0; i < meshCount; i ++) {\n\t\t\t\t\t\tbuilder.getColorOffset\t\t().at(offset)\t.putInt\t\t\t(vertexAddress, FastColor.ABGR32.fromArgb32\t\t(meshInfos.getColor(i)));\n\t\t\t\t\t\tbuilder.getUv1Offset\t\t().at(offset)\t.putInt\t\t\t(vertexAddress, meshInfos\t\t.getOverlay\t\t(i));\n\t\t\t\t\t\tbuilder.getUv2Offset\t\t().at(offset)\t.putInt\t\t\t(vertexAddress, meshInfos\t\t.getLight\t\t(i));\n\n\t\t\t\t\t\tbuilder.getVaryingSharing\t().at(offset)\t.putInt\t\t\t(varyingAddress, meshInfos\t\t.getSharing\t\t(i));\n\t\t\t\t\t\tbuilder.getVaryingMesh\t\t().at(offset)\t.putInt\t\t\t(varyingAddress, mesh\t\t\t.offset\t\t\t());\n\t\t\t\t\t\tbuilder.getVaryingShouldCull().at(offset)\t.putInt\t\t\t(varyingAddress, meshInfos\t\t.getShouldCull\t(i));\n\t\t\t\t\t\tbuilder.getTransformOverride()\t\t\t\t.uploadVarying\t(varyingAddress, offset);\n\n\t\t\t\t\t\tfor (var offsetValue = 0; offsetValue < meshSize; offsetValue ++) {\n\t\t\t\t\t\t\tbuilder\n\t\t\t\t\t\t\t\t\t.getVaryingOffset\t()\n\t\t\t\t\t\t\t\t\t.at\t\t\t\t\t(offset)\n\t\t\t\t\t\t\t\t\t.at\t\t\t\t\t(offsetValue)\n\t\t\t\t\t\t\t\t\t.putInt\t\t\t\t(varyingAddress, offsetValue);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\toffset += meshSize;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tvar count = offset - sparseStart;\n\n\t\t\t\tif (count != 0) {\n\t\t\t\t\tmeshBuffer.bindBase(GL_SHADER_STORAGE_BUFFER, SPARSE_MESH_BUFFER_INDEX);\n\n\t\t\t\t\tlastOverride =\tnull;\n\t\t\t\t\tlastBarriers |=\ttransform.dispatch(\n\t\t\t\t\t\t\tbuilder,\n\t\t\t\t\t\t\tvertexBuffer,\n\t\t\t\t\t\t\tvaryingBuffer,\n\t\t\t\t\t\t\tcount,\n\t\t\t\t\t\t\tsparseStart + vertexCount + vertexOffset,\n\t\t\t\t\t\t\tsparseStart + vertexCount + varyingOffset\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tsparseStart = offset;\n\t\t\t}\n\n\t\t\tfor (var meshBuffer : denseUploaders.keySet()) {\n\t\t\t\tmeshBuffer.bindBase(GL_SHADER_STORAGE_BUFFER, MESH_BUFFER_INDEX);\n\n\t\t\t\tfor (var uploader : denseUploaders.get(meshBuffer)) {\n\t\t\t\t\tvar currentOverride\t= builder\t\t\t\t\t.getUploadingOverride\t();\n\t\t\t\t\tvar meshCount\t\t= uploader.getMeshInfos()\t.getMeshCount\t\t\t();\n\t\t\t\t\tvar mesh\t\t\t= uploader\t\t\t\t\t.getServerMesh\t\t\t();\n\t\t\t\t\tvar meshSize\t\t= mesh\t\t\t\t\t\t.size\t\t\t\t\t();\n\t\t\t\t\tvar uploadSize\t\t= meshCount * meshSize;\n\n\t\t\t\t\tif (lastOverride == null) {\n\t\t\t\t\t\tlastOverride = currentOverride;\n\t\t\t\t\t\tlastOverride.useProgram\t\t();\n\t\t\t\t\t\tlastOverride.setupProgram\t();\n\t\t\t\t\t}\n\n\t\t\t\t\ttransform\t\t\t\t\t\t.resetOverride\t\t();\n\t\t\t\t\tuploader\t\t\t\t\t\t.upload\t\t\t\t();\n\t\t\t\t\tuploader\t\t\t\t\t\t.bindBuffers\t\t();\n\t\t\t\t\tlastBarriers |= currentOverride\t.dispatchUploading\t(\n\t\t\t\t\t\t\tuploadSize,\n\t\t\t\t\t\t\tmeshCount,\n\t\t\t\t\t\t\tmeshSize,\n\t\t\t\t\t\t\t(int) (offset + vertexCount + vertexOffset),\n\t\t\t\t\t\t\t(int) (offset + vertexCount + varyingOffset),\n\t\t\t\t\t\t\t(int) mesh.offset()\n\t\t\t\t\t);\n\n\t\t\t\t\toffset += uploadSize;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (var meshBuffer : denseUploaders.keySet()) {\n\t\t\t\tdenseUploaders\t.get(meshBuffer).clear();\n\t\t\t\tsparseUploaders\t.get(meshBuffer).clear();\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void resetOverride() {\n\t\tlastOverride = null;\n\t}\n\n\tpublic static class Default implements IUploadingShaderProgramOverride {\n\n\t\tprivate final long\t\t\t\tmeshInfoSize;\n\t\tprivate final ComputeProgram\tprogram;\n\t\tprivate final Uniform\t\t\tmeshCountUniform;\n\t\tprivate final Uniform\t\t\tmeshSizeUniform;\n\t\tprivate final Uniform\t\t\tvertexOffsetUniform;\n\t\tprivate final Uniform\t\t\tvaryingOffsetUniform;\n\t\tprivate final Uniform\t\t\tmeshOffsetUniform;\n\n\t\tpublic Default(ResourceLocation key, long meshInfoSize) {\n\t\t\tthis.meshInfoSize\t\t\t= meshInfoSize;\n\t\t\tthis.program\t\t\t\t= ComputeShaderProgramLoader.getProgram(key);\n\t\t\tthis.meshCountUniform\t\t= program\t\t\t\t\t.getUniform(\"meshCount\");\n\t\t\tthis.meshSizeUniform\t\t= program\t\t\t\t\t.getUniform(\"meshSize\");\n\t\t\tthis.vertexOffsetUniform\t= program\t\t\t\t\t.getUniform(\"vertexOffset\");\n\t\t\tthis.varyingOffsetUniform\t= program\t\t\t\t\t.getUniform(\"varyingOffset\");\n\t\t\tthis.meshOffsetUniform\t\t= program\t\t\t\t\t.getUniform(\"meshOffset\");\n\t\t}\n\n\t\t@Override\n\t\tpublic long getMeshInfoSize() {\n\t\t\treturn meshInfoSize;\n\t\t}\n\n\t\t@Override\n\t\tpublic void useProgram() {\n\t\t\tprogram.useProgram();\n\t\t}\n\n\t\t@Override\n\t\tpublic void setupProgram() {\n\t\t\tprogram.setup();\n\t\t}\n\n\t\t@Override\n\t\tpublic void uploadMeshInfo(long meshInfoAddress, int meshInfoIndex) {\n\n\t\t}\n\n\t\t@Override\n\t\tpublic int dispatchUploading(\n\t\t\t\tint uploadSize,\n\t\t\t\tint meshCount,\n\t\t\t\tint meshSize,\n\t\t\t\tint vertexOffset,\n\t\t\t\tint varyingOffset,\n\t\t\t\tint meshOffset\n\t\t) {\n\t\t\tmeshCountUniform\t.uploadUnsignedInt\t(meshCount);\n\t\t\tmeshSizeUniform\t\t.uploadUnsignedInt\t(meshSize);\n\t\t\tvertexOffsetUniform\t.uploadUnsignedInt\t(vertexOffset);\n\t\t\tvaryingOffsetUniform.uploadUnsignedInt\t(varyingOffset);\n\t\t\tmeshOffsetUniform\t.uploadUnsignedInt\t(meshOffset);\n\t\t\tprogram\t\t\t\t.dispatch\t\t\t(\n\t\t\t\t\t(uploadSize + GROUP_SIZE - 1) / GROUP_SIZE,\n\t\t\t\t\tDISPATCH_COUNT_Y_Z,\n\t\t\t\t\tDISPATCH_COUNT_Y_Z\n\t\t\t);\n\n\t\t\treturn program.getBarrierFlags();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/dispatchers/TransformProgramDispatcher.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs.dispatchers;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.programs.ComputeProgram;\nimport com.github.argon4w.acceleratedrendering.core.backends.programs.Uniform;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.StagingBufferPool;\nimport com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderProgramLoader;\nimport com.github.argon4w.acceleratedrendering.core.programs.overrides.ITransformShaderProgramOverride;\nimport net.minecraft.resources.ResourceLocation;\n\nimport java.util.Collection;\n\nimport static org.lwjgl.opengl.GL46.*;\n\npublic class TransformProgramDispatcher {\n\n\tpublic\tstatic\tfinal\tint\t\t\t\t\t\t\t\tVERTEX_BUFFER_IN_INDEX\t\t= 0;\n\tpublic\tstatic\tfinal\tint\t\t\t\t\t\t\t\tVARYING_BUFFER_IN_INDEX\t\t= 3;\n\tprivate static\tfinal\tint\t\t\t\t\t\t\t\tGROUP_SIZE\t\t\t\t\t= 128;\n\tprivate static\tfinal\tint\t\t\t\t\t\t\t\tDISPATCH_COUNT_Y_Z\t\t\t= 1;\n\n\tprivate\t\t\t\t\tITransformShaderProgramOverride\tlastOverride;\n\tprivate\t\t\t\t\tint\t\t\t\t\t\t\t\tlastBarriers;\n\n\tpublic TransformProgramDispatcher() {\n\t\tthis.lastOverride = null;\n\t\tthis.lastBarriers = GL_SHADER_STORAGE_BARRIER_BIT;\n\t}\n\n\tpublic void dispatch(Collection<AcceleratedBufferBuilder> builders) {\n\t\tglMemoryBarrier(lastBarriers);\n\n\t\tfor (var builder : builders) {\n\t\t\tvar currentOverride\t= builder\t\t\t.getTransformOverride\t();\n\t\t\tvar vertexCount\t\t= builder\t\t\t.getVertexCount\t\t\t();\n\t\t\tvar vertexBuffer\t= builder\t\t\t.getVertexBuffer\t\t();\n\t\t\tvar varyingBuffer\t= builder\t\t\t.getVaryingBuffer\t\t();\n\n\t\t\tif (lastOverride != currentOverride) {\n\t\t\t\tlastOverride = currentOverride;\n\t\t\t\tlastOverride.useProgram\t\t();\n\t\t\t\tlastOverride.setupProgram\t();\n\t\t\t}\n\n\t\t\tif (vertexCount != 0) {\n\t\t\t\tvertexBuffer\t\t\t\t\t.bindBase\t\t\t(GL_SHADER_STORAGE_BUFFER, VERTEX_BUFFER_IN_INDEX);\n\t\t\t\tvaryingBuffer\t\t\t\t\t.bindBase\t\t\t(GL_SHADER_STORAGE_BUFFER, VARYING_BUFFER_IN_INDEX);\n\t\t\t\tlastBarriers |= currentOverride\t.dispatchTransform\t(\n\t\t\t\t\t\tvertexCount,\n\t\t\t\t\t\t(int) (vertexBuffer\t.getOffset() / builder.getVertexSize\t()),\n\t\t\t\t\t\t(int) (varyingBuffer.getOffset() / builder.getVaryingSize\t())\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tresetOverride\t();\n\t\tglUseProgram\t(0);\n\t}\n\n\tpublic int dispatch(\n\t\t\tAcceleratedBufferBuilder\t\tbuilder,\n\t\t\tStagingBufferPool.StagingBuffer\tvertexBuffer,\n\t\t\tStagingBufferPool.StagingBuffer\tvaryingBuffer,\n\t\t\tlong\t\t\t\t\t\t\tvertexCount,\n\t\t\tlong\t\t\t\t\t\t\tvertexOffset,\n\t\t\tlong\t\t\t\t\t\t\tvaryingOffset\n\t) {\n\t\tvar currentOverride = builder.getTransformOverride();\n\n\t\tif (lastOverride != currentOverride) {\n\t\t\tlastOverride = currentOverride;\n\t\t\tlastOverride.useProgram\t\t();\n\t\t\tlastOverride.setupProgram\t();\n\t\t}\n\n\t\tvertexBuffer\t.bindBase(GL_SHADER_STORAGE_BUFFER, VERTEX_BUFFER_IN_INDEX);\n\t\tvaryingBuffer\t.bindBase(GL_SHADER_STORAGE_BUFFER, VARYING_BUFFER_IN_INDEX);\n\n\t\treturn currentOverride\t.dispatchTransform\t(\n\t\t\t\t(int) vertexCount,\n\t\t\t\t(int) vertexOffset,\n\t\t\t\t(int) varyingOffset\n\t\t);\n\t}\n\n\tpublic void resetOverride() {\n\t\tlastOverride = null;\n\t}\n\n\tpublic static class Default implements ITransformShaderProgramOverride {\n\n\t\tprivate final long\t\t\t\tvaryingSize;\n\t\tprivate final ComputeProgram\tprogram;\n\t\tprivate final Uniform\t\t\tvertexCountUniform;\n\t\tprivate final Uniform\t\t\tvertexOffsetUniform;\n\t\tprivate final Uniform\t\t\tvaryingOffsetUniform;\n\n\t\tpublic Default(ResourceLocation key, long varyingSize) {\n\t\t\tthis.varyingSize\t\t\t= varyingSize;\n\t\t\tthis.program\t\t\t\t= ComputeShaderProgramLoader.getProgram(key);\n\t\t\tthis.vertexCountUniform\t\t= program\t\t\t\t\t.getUniform(\"vertexCount\");\n\t\t\tthis.vertexOffsetUniform\t= program\t\t\t\t\t.getUniform(\"vertexOffset\");\n\t\t\tthis.varyingOffsetUniform\t= program\t\t\t\t\t.getUniform(\"varyingOffset\");\n\t\t}\n\n\t\t@Override\n\t\tpublic long getVaryingSize() {\n\t\t\treturn varyingSize;\n\t\t}\n\n\t\t@Override\n\t\tpublic void useProgram() {\n\t\t\tprogram.useProgram();\n\t\t}\n\n\t\t@Override\n\t\tpublic void setupProgram() {\n\t\t\tprogram.setup();\n\t\t}\n\n\t\t@Override\n\t\tpublic void uploadVarying(long varyingAddress, int offset) {\n\n\t\t}\n\n\t\t@Override\n\t\tpublic int dispatchTransform(\n\t\t\t\tint vertexCount,\n\t\t\t\tint vertexOffset,\n\t\t\t\tint varyingOffset\n\t\t) {\n\t\t\tvertexCountUniform\t\t.uploadUnsignedInt\t(vertexCount);\n\t\t\tvertexOffsetUniform\t\t.uploadUnsignedInt\t(vertexOffset);\n\t\t\tvaryingOffsetUniform\t.uploadUnsignedInt\t(varyingOffset);\n\t\t\tprogram\t\t\t\t\t.dispatch\t\t\t(\n\t\t\t\t\t(vertexCount + GROUP_SIZE - 1) / GROUP_SIZE,\n\t\t\t\t\tDISPATCH_COUNT_Y_Z,\n\t\t\t\t\tDISPATCH_COUNT_Y_Z\n\t\t\t);\n\n\t\t\treturn program.getBarrierFlags();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/overrides/IShaderProgramOverride.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs.overrides;\n\npublic interface IShaderProgramOverride {\n\n\tvoid useProgram\t\t();\n\tvoid setupProgram\t();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/overrides/IShaderProgramOverrides.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs.overrides;\n\nimport net.minecraft.client.renderer.RenderType;\n\nimport java.util.Map;\n\npublic interface IShaderProgramOverrides {\n\n\tMap<RenderType, ITransformShaderProgramOverride> getTransformOverrides();\n\tMap<RenderType, IUploadingShaderProgramOverride> getUploadingOverrides();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/overrides/ITransformShaderProgramOverride.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs.overrides;\n\npublic interface ITransformShaderProgramOverride extends IShaderProgramOverride {\n\n\tvoid\tuploadVarying\t\t(long\tvaryingAddress,\tint offset);\n\tint\t\tdispatchTransform\t(int\tvertexCount,\tint vertexOffset, int varyingOffset);\n\tlong\tgetVaryingSize\t\t();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/overrides/IUploadingShaderProgramOverride.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs.overrides;\n\npublic interface IUploadingShaderProgramOverride extends IShaderProgramOverride {\n\n\tvoid\tuploadMeshInfo\t\t(long\tmeshInfoAddress,\tint\tmeshInfoIndex);\n\tint\t\tdispatchUploading\t(int\tmeshCount,\t\t\tint\tmeshSize,\tint vertexOffset, int varyingOffset, int meshOffset, int uploadSize);\n\tlong\tgetMeshInfoSize\t\t();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/overrides/LoadShaderProgramOverridesEvent.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs.overrides;\n\nimport com.mojang.blaze3d.vertex.VertexFormat;\nimport it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;\nimport lombok.Getter;\nimport net.minecraft.client.renderer.RenderType;\nimport net.neoforged.bus.api.Event;\nimport net.neoforged.fml.event.IModBusEvent;\n\npublic class LoadShaderProgramOverridesEvent extends Event implements IModBusEvent {\n\n\tprivate final VertexFormat\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvertexFormat;\n\tprivate final Object2ObjectOpenHashMap<RenderType, ITransformShaderProgramOverride> transformOverrides;\n\tprivate final Object2ObjectOpenHashMap<RenderType, IUploadingShaderProgramOverride>\tuploadingOverrides;\n\n\tpublic LoadShaderProgramOverridesEvent(VertexFormat vertexFormat) {\n\t\tthis.vertexFormat\t\t= vertexFormat;\n\t\tthis.transformOverrides\t= new Object2ObjectOpenHashMap<>();\n\t\tthis.uploadingOverrides\t= new Object2ObjectOpenHashMap<>();\n\t}\n\n\tpublic void loadFor(\n\t\t\tVertexFormat\t\t\tvertexFormat,\n\t\t\tRenderType\t\t\t\trenderType,\n\t\t\tIShaderProgramOverride\toverride\n\t) {\n\t\tif (this.vertexFormat == vertexFormat) {\n\t\t\tswitch (override) {\n\t\t\t\tcase ITransformShaderProgramOverride transform\t-> transformOverrides.put\t\t\t\t\t(renderType, transform);\n\t\t\t\tcase IUploadingShaderProgramOverride uploading\t-> uploadingOverrides.put\t\t\t\t\t(renderType, uploading);\n\t\t\t\tdefault\t\t\t\t\t\t\t\t\t\t\t-> throw new UnsupportedOperationException\t(\"Unsupported override type: \" + override.getClass().getSimpleName());\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic IShaderProgramOverrides getOverrides(ITransformShaderProgramOverride defaultTransformOverride, IUploadingShaderProgramOverride defaultUploadingOverride) {\n\t\treturn new ProgramOverrides(\n\t\t\t\ttransformOverrides,\n\t\t\t\tuploadingOverrides,\n\t\t\t\tdefaultTransformOverride,\n\t\t\t\tdefaultUploadingOverride\n\t\t);\n\t}\n\n\t@Getter\n\tpublic static class ProgramOverrides implements IShaderProgramOverrides {\n\n\t\tprivate final Object2ObjectOpenHashMap<RenderType, ITransformShaderProgramOverride> transformOverrides;\n\t\tprivate final Object2ObjectOpenHashMap<RenderType, IUploadingShaderProgramOverride>\tuploadingOverrides;\n\n\t\tpublic ProgramOverrides(\n\t\t\t\tObject2ObjectOpenHashMap<RenderType, ITransformShaderProgramOverride>\ttransformOverrides,\n\t\t\t\tObject2ObjectOpenHashMap<RenderType, IUploadingShaderProgramOverride>\tuploadingOverrides,\n\t\t\t\tITransformShaderProgramOverride\t\t\t\t\t\t\t\t\t\t\tdefaultTransformOverride,\n\t\t\t\tIUploadingShaderProgramOverride\t\t\t\t\t\t\t\t\t\t\tdefaultUploadingOverride\n\t\t) {\n\t\t\tthis.transformOverrides = transformOverrides;\n\t\t\tthis.uploadingOverrides = uploadingOverrides;\n\n\t\t\tthis.transformOverrides.defaultReturnValue(defaultTransformOverride);\n\t\t\tthis.uploadingOverrides.defaultReturnValue(defaultUploadingOverride);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/overrides/OverrideProgramType.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs.overrides;\n\npublic enum OverrideProgramType {\n\n\tTRANSFORM,\n\tUPLOADING\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/processing/EmptyPolygonProcessor.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs.processing;\n\nimport com.github.argon4w.acceleratedrendering.core.programs.dispatchers.EmptyProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.programs.dispatchers.IPolygonProgramDispatcher;\nimport com.mojang.blaze3d.vertex.VertexFormat;\n\npublic class EmptyPolygonProcessor implements IPolygonProcessor {\n\n\tpublic static final EmptyPolygonProcessor INSTANCE = new EmptyPolygonProcessor();\n\n\t@Override\n\tpublic IPolygonProgramDispatcher select(VertexFormat.Mode mode) {\n\t\treturn EmptyProgramDispatcher.INSTANCE;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/processing/IPolygonProcessor.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs.processing;\n\nimport com.github.argon4w.acceleratedrendering.core.programs.dispatchers.IPolygonProgramDispatcher;\nimport com.mojang.blaze3d.vertex.VertexFormat;\n\npublic interface IPolygonProcessor {\n\n\tIPolygonProgramDispatcher select(VertexFormat.Mode mode);\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/programs/processing/LoadPolygonProcessorEvent.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.programs.processing;\n\nimport com.mojang.blaze3d.vertex.VertexFormat;\nimport lombok.Getter;\nimport net.neoforged.bus.api.Event;\nimport net.neoforged.fml.event.IModBusEvent;\n\nimport java.util.function.UnaryOperator;\n\npublic class LoadPolygonProcessorEvent extends Event implements IModBusEvent {\n\n\tprivate final\tVertexFormat\t\tvertexFormat;\n\n\t@Getter private IPolygonProcessor\tprocessor;\n\n\tpublic LoadPolygonProcessorEvent(VertexFormat vertexFormat) {\n\t\tthis.vertexFormat\t= vertexFormat;\n\t\tthis.processor\t\t= EmptyPolygonProcessor.INSTANCE;\n\t}\n\n\tpublic void loadFor(VertexFormat vertexFormat, UnaryOperator<IPolygonProcessor> selector) {\n\t\tif (this.vertexFormat == vertexFormat) {\n\t\t\tthis.processor = selector.apply(this.processor);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/utils/CullerUtils.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.utils;\n\nimport com.mojang.blaze3d.platform.NativeImage;\nimport net.minecraft.util.FastColor;\nimport net.minecraft.util.Mth;\nimport org.joml.Vector3f;\n\npublic class CullerUtils {\n\n\tpublic static boolean shouldCull(Vertex[] vertices, NativeImage texture) {\n\t\tif (texture == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (vertices.length == 4) {\n\t\t\tvar vertex0 = new Vector3f(vertices[0].getPosition());\n\t\t\tvar vector1 = new Vector3f(vertices[1].getPosition()).sub(vertex0);\n\t\t\tvar vector2 = new Vector3f(vertices[2].getPosition()).sub(vertex0);\n\t\t\tvar vector3 = new Vector3f(vertices[3].getPosition()).sub(vertex0);\n\n\t\t\tvar length1 = vector1.cross(vector2).length();\n\t\t\tvar length2 = vector1.cross(vector3).length();\n\n\t\t\tif (length1 == 0 && length2 == 0) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\tvar minU = 1.0f;\n\t\tvar minV = 1.0f;\n\t\tvar maxU = 0.0f;\n\t\tvar maxV = 0.0f;\n\n\t\tfor (var vertex : vertices) {\n\t\t\tvar uv\t= vertex.getUv();\n\t\t\tvar u\t= uv\t.x;\n\t\t\tvar v\t= uv\t.y;\n\n\t\t\tminU = Math.min(minU, u);\n\t\t\tminV = Math.min(minV, v);\n\t\t\tmaxU = Math.max(maxU, u);\n\t\t\tmaxV = Math.max(maxV, v);\n\t\t}\n\n\t\tvar width\t= texture.getWidth\t();\n\t\tvar height\t= texture.getHeight\t();\n\n\t\tvar minX\t= Mth.floor\t(minU * texture.getWidth\t());\n\t\tvar minY\t= Mth.floor\t(minV * texture.getHeight\t());\n\t\tvar maxX\t= Mth.ceil\t(maxU * texture.getWidth\t());\n\t\tvar maxY\t= Mth.ceil\t(maxV * texture.getHeight\t());\n\n\t\tfor (\t\tvar x = minX; x <= maxX; x ++) {\n\t\t\tfor (\tvar y = minY; y <= maxY; y ++) {\n\t\t\t\tvar clampedX = x % width;\n\t\t\t\tvar clampedY = y % height;\n\n\t\t\t\tclampedX = clampedX < 0 ? width\t\t+ clampedX : clampedX;\n\t\t\t\tclampedY = clampedY < 0 ? height\t+ clampedY : clampedY;\n\n\t\t\t\tif (FastColor.ABGR32.alpha(texture.getPixelRGBA(clampedX, clampedY)) != 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/utils/DirectionUtils.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.utils;\n\nimport net.minecraft.core.Direction;\n\npublic class DirectionUtils {\n\n\tpublic static final Direction[] FULL = new Direction[] {\n\t\t\tnull,\n\t\t\tDirection.DOWN,\n\t\t\tDirection.UP,\n\t\t\tDirection.NORTH,\n\t\t\tDirection.SOUTH,\n\t\t\tDirection.WEST,\n\t\t\tDirection.EAST\n\t};\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/utils/EmptyIterator.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.utils;\n\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\n\npublic class EmptyIterator<T> implements Iterator<T> {\n\n\tpublic static final EmptyIterator<?> INSTANCE = new EmptyIterator<>();\n\n\t@Override\n\tpublic boolean hasNext() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic T next() {\n\t\tthrow new NoSuchElementException();\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tpublic static <T> Iterator<T> of() {\n\t\treturn (Iterator<T>) INSTANCE;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/utils/FastColorUtils.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.utils;\n\npublic class FastColorUtils {\n\n\tpublic static int convert(int color) {\n\t\treturn\t\tcolor & 0xFF00FF00\n\t\t\t\t| (\tcolor & 0x00FF0000) >> 16\n\t\t\t\t| (\tcolor & 0x000000FF) << 16;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/utils/FuzzyMatrix4f.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.utils;\n\nimport org.joml.Matrix4f;\nimport org.joml.Matrix4fc;\n\npublic class FuzzyMatrix4f extends Matrix4f {\n\n\tpublic FuzzyMatrix4f(Matrix4f matrix) {\n\t\tsuper(matrix);\n\t}\n\n\tpublic FuzzyMatrix4f() {\n\t\tsuper();\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn 61;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object obj) {\n\t\treturn obj instanceof Matrix4fc matrix && equals(matrix, 1e-2f);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/utils/IntArrayHashStrategy.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.utils;\n\nimport it.unimi.dsi.fastutil.Hash;\n\nimport java.util.Arrays;\n\npublic class IntArrayHashStrategy implements Hash.Strategy<int[]> {\n\n\tpublic static final IntArrayHashStrategy INSTANCE = new IntArrayHashStrategy();\n\n\t@Override\n\tpublic int hashCode(int[] o) {\n\t\treturn Arrays.hashCode(o);\n\t}\n\n\t@Override\n\tpublic boolean equals(int[] a, int[] b) {\n\t\treturn Arrays.equals(a, b);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/utils/LoopResetPool.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.utils;\n\npublic abstract class LoopResetPool<T, C> extends SimpleResetPool<T, C> {\n\n\tpublic LoopResetPool(int size, C context) {\n\t\tsuper(size, context);\n\t}\n\n\t@Override\n\t@SuppressWarnings(\"unchecked\")\n\tpublic T get(boolean force) {\n\t\tfor (var i = 0; i < size; i++) {\n\t\t\tvar t = (T) pool[i];\n\n\t\t\tif (test(t)) {\n\t\t\t\tinit(t);\n\t\t\t\treturn t;\n\t\t\t}\n\t\t}\n\n\t\treturn fail(force);\n\t}\n}"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/utils/MemUtils.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.utils;\n\nimport net.minecraft.util.Mth;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.lwjgl.system.MemoryUtil;\n\npublic class MemUtils {\n\n\tpublic static void putNormal(long address, float value) {\n\t\tMemoryUtil.memPutByte(address, (byte) ((int) (Mth.clamp(value, -1.0f, 1.0f) * 127.0f) & 0xFF));\n\t}\n\n\tpublic static void putMatrix3f(long address, Matrix3f matrix) {\n\t\tMemoryUtil.memPutFloat(address + 0L * 4L,\tmatrix.m00());\n\t\tMemoryUtil.memPutFloat(address + 1L * 4L,\tmatrix.m01());\n\t\tMemoryUtil.memPutFloat(address + 2L * 4L,\tmatrix.m02());\n\n\t\tMemoryUtil.memPutFloat(address + 4L * 4L,\tmatrix.m10());\n\t\tMemoryUtil.memPutFloat(address + 5L * 4L,\tmatrix.m11());\n\t\tMemoryUtil.memPutFloat(address + 6L * 4L,\tmatrix.m12());\n\n\t\tMemoryUtil.memPutFloat(address + 8L * 4L,\tmatrix.m20());\n\t\tMemoryUtil.memPutFloat(address + 9L * 4L,\tmatrix.m21());\n\t\tMemoryUtil.memPutFloat(address + 10L * 4L,\tmatrix.m22());\n\t}\n\n\tpublic static void putMatrix4f(long address, Matrix4f matrix) {\n\t\tMemoryUtil.memPutFloat(address + 0L * 4L,\tmatrix.m00());\n\t\tMemoryUtil.memPutFloat(address + 1L * 4L,\tmatrix.m01());\n\t\tMemoryUtil.memPutFloat(address + 2L * 4L,\tmatrix.m02());\n\t\tMemoryUtil.memPutFloat(address + 3L * 4L,\tmatrix.m03());\n\n\t\tMemoryUtil.memPutFloat(address + 4L * 4L,\tmatrix.m10());\n\t\tMemoryUtil.memPutFloat(address + 5L * 4L,\tmatrix.m11());\n\t\tMemoryUtil.memPutFloat(address + 6L * 4L,\tmatrix.m12());\n\t\tMemoryUtil.memPutFloat(address + 7L * 4L,\tmatrix.m13());\n\n\t\tMemoryUtil.memPutFloat(address + 8L * 4L,\tmatrix.m20());\n\t\tMemoryUtil.memPutFloat(address + 9L * 4L,\tmatrix.m21());\n\t\tMemoryUtil.memPutFloat(address + 10L * 4L,\tmatrix.m22());\n\t\tMemoryUtil.memPutFloat(address + 11L * 4L,\tmatrix.m23());\n\n\t\tMemoryUtil.memPutFloat(address + 12L * 4L,\tmatrix.m30());\n\t\tMemoryUtil.memPutFloat(address + 13L * 4L,\tmatrix.m31());\n\t\tMemoryUtil.memPutFloat(address + 14L * 4L,\tmatrix.m32());\n\t\tMemoryUtil.memPutFloat(address + 15L * 4L,\tmatrix.m33());\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/utils/MutableSize.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.utils;\n\nimport lombok.Getter;\n\n@Getter\npublic class MutableSize {\n\n\tprotected boolean\tresized;\n\tprotected long\t\tsize;\n\n\tpublic MutableSize(long initialSize) {\n\t\tthis.resized\t= false;\n\t\tthis.size\t\t= initialSize;\n\t}\n\n\tpublic void expand(long bytes) {\n\t\tif (bytes <= 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tbeforeExpand();\n\t\tonExpand\t(bytes);\n\t\tdoExpand\t(size, bytes);\n\n\t\tresized\t=\ttrue;\n\t\tsize\t+=\tbytes;\n\n\t\tafterExpand();\n\t}\n\n\tpublic void onExpand(long bytes) {\n\n\t}\n\n\tpublic void doExpand(long size, long bytes) {\n\n\t}\n\n\tpublic void beforeExpand() {\n\n\t}\n\n\tpublic void afterExpand() {\n\n\t}\n\n\tpublic void resize(long atLeast) {\n\t\tresizeTo(Long.highestOneBit(atLeast) << 1);\n\t}\n\n\tpublic void resizeTo(long newBufferSize) {\n\t\texpand(newBufferSize - size);\n\t}\n\n\tpublic void resetResized() {\n\t\tresized = false;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/utils/PackedVector2i.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.utils;\n\npublic class PackedVector2i {\n\n\tpublic static int pack(float u, float v) {\n\t\treturn pack((int) u, (int) v);\n\t}\n\n\tpublic static int pack(int u, int v) {\n\t\treturn (u & 0xFFFF) | (v & 0xFFFF) << 16;\n\t}\n\n\tpublic static int unpackU(int packed) {\n\t\treturn packed & 0xFFFF;\n\t}\n\n\tpublic static int unpackV(int packed) {\n\t\treturn packed >>> 16 & 0xFFFF;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/utils/PoseStackExtension.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.utils;\n\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\npublic class PoseStackExtension {\n\n\tpublic static void setPose(\n\t\t\tPoseStack\tin,\n\t\t\tMatrix4f\ttransform,\n\t\t\tMatrix3f\tnormal\n\t) {\n\t\tvar last = in.last();\n\n\t\tlast.pose\t().set(transform);\n\t\tlast.normal\t().set(normal);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/utils/RegistryFilter.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.utils;\n\nimport it.unimi.dsi.fastutil.objects.ReferenceArrayList;\nimport it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;\nimport it.unimi.dsi.fastutil.objects.ReferenceSets;\nimport net.minecraft.core.Registry;\n\nimport java.util.List;\nimport java.util.Set;\nimport java.util.regex.Pattern;\n\npublic class RegistryFilter {\n\n\tpublic static <T> Set<T> filterValues(Registry<T> registry, List<? extends String> values) {\n\t\tif (values.isEmpty()) {\n\t\t\treturn ReferenceSets.emptySet();\n\t\t}\n\n\t\tvar patterns = new ReferenceArrayList\t<Pattern>\t();\n\t\tvar filtered = new ReferenceOpenHashSet\t<T>\t\t\t();\n\n\t\tfor (var pattern : values) {\n\t\t\tpatterns.add(Pattern.compile(pattern));\n\t\t}\n\n\t\tfor\t\t(var key\t\t: registry.keySet()) {\n\t\t\tfor\t(var pattern\t: patterns) {\n\t\t\t\tif (pattern\n\t\t\t\t\t\t.matcher(key.toString())\n\t\t\t\t\t\t.matches()\n\t\t\t\t) {\n\t\t\t\t\tfiltered.add(registry.get(key));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn filtered;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/utils/RenderTypeUtils.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.utils;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType;\nimport it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;\nimport net.minecraft.client.renderer.RenderStateShard;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.resources.ResourceLocation;\nimport org.lwjgl.opengl.GL11;\n\nimport java.util.Map;\n\npublic class RenderTypeUtils {\n\n\tpublic static final Map<RenderType, RenderType> WITH_DEPTH_CACHE = new Object2ObjectOpenHashMap<>();\n\n\tpublic static ResourceLocation getTextureLocation(RenderType renderType) {\n\t\tif (renderType == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (!(renderType instanceof RenderType.CompositeRenderType composite)) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn composite\n\t\t\t\t.state\n\t\t\t\t.textureState\n\t\t\t\t.cutoutTexture()\n\t\t\t\t.orElse(null);\n\t}\n\n\tpublic static boolean isCulled(RenderType renderType) {\n\t\tif (renderType == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (!(renderType instanceof RenderType.CompositeRenderType composite)) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn composite\n\t\t\t\t.state\n\t\t\t\t.cullState\n\t\t\t\t.enabled;\n\t}\n\n\tpublic static boolean isDynamic(RenderType renderType) {\n\t\tif (renderType == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (!(renderType instanceof RenderType.CompositeRenderType composite)) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn composite\n\t\t\t\t.state\n\t\t\t\t.texturingState instanceof RenderStateShard.OffsetTexturingStateShard;\n\t}\n\n\tpublic static boolean hasDepth(RenderType renderType) {\n\t\tif (renderType == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (!(renderType instanceof RenderType.CompositeRenderType composite)) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn composite\n\t\t\t\t.state\n\t\t\t\t.depthTestState != RenderStateShard.NO_DEPTH_TEST;\n\t}\n\n\tpublic static RenderType withDepth(RenderType renderType) {\n\t\tif (renderType == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (hasDepth(renderType)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (!(renderType instanceof RenderType.CompositeRenderType composite)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar result = WITH_DEPTH_CACHE.get(renderType);\n\n\t\tif (result != null) {\n\t\t\treturn result;\n\t\t}\n\n\t\tvar state = composite.state;\n\n\t\tresult = RenderType.create(\n\t\t\t\trenderType.name,\n\t\t\t\trenderType.format,\n\t\t\t\trenderType.mode,\n\t\t\t\trenderType.bufferSize,\n\t\t\t\trenderType.affectsCrumbling,\n\t\t\t\trenderType.sortOnUpload,\n\t\t\t\tRenderType.CompositeState\n\t\t\t\t\t\t.builder\t\t\t\t()\n\t\t\t\t\t\t.setDepthTestState\t\t(RenderStateShard\t.LEQUAL_DEPTH_TEST)\n\t\t\t\t\t\t.setWriteMaskState\t\t(state\t\t\t\t.writeMaskState.writeColor ? RenderStateShard.COLOR_DEPTH_WRITE : RenderStateShard.DEPTH_WRITE)\n\t\t\t\t\t\t.setTextureState\t\t(state\t\t\t\t.textureState)\n\t\t\t\t\t\t.setShaderState\t\t\t(state\t\t\t\t.shaderState)\n\t\t\t\t\t\t.setTransparencyState\t(state\t\t\t\t.transparencyState)\n\t\t\t\t\t\t.setCullState\t\t\t(state\t\t\t\t.cullState)\n\t\t\t\t\t\t.setLightmapState\t\t(state\t\t\t\t.lightmapState)\n\t\t\t\t\t\t.setOverlayState\t\t(state\t\t\t\t.overlayState)\n\t\t\t\t\t\t.setLayeringState\t\t(state\t\t\t\t.layeringState)\n\t\t\t\t\t\t.setOutputState\t\t\t(state\t\t\t\t.outputState)\n\t\t\t\t\t\t.setTexturingState\t\t(state\t\t\t\t.texturingState)\n\t\t\t\t\t\t.setLineState\t\t\t(state\t\t\t\t.lineState)\n\t\t\t\t\t\t.setColorLogicState\t\t(state\t\t\t\t.colorLogicState)\n\t\t\t\t\t\t.createCompositeState\t(state\t\t\t\t.outlineProperty)\n\t\t);\n\n\t\treturn result;\n\t}\n\n\tpublic static LayerDrawType getDrawType(RenderType renderType) {\n\t\treturn renderType.sortOnUpload ? LayerDrawType.TRANSLUCENT : LayerDrawType.OPAQUE;\n\t}\n\n\tpublic static boolean isTranslucent(RenderType renderType) {\n\t\treturn renderType.sortOnUpload;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/utils/ResourceLocationUtils.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.utils;\n\nimport com.github.argon4w.acceleratedrendering.AcceleratedRenderingModEntry;\nimport net.minecraft.resources.ResourceLocation;\n\npublic class ResourceLocationUtils {\n\n\tpublic static ResourceLocation create(String path) {\n\t\treturn ResourceLocation.fromNamespaceAndPath(AcceleratedRenderingModEntry.MOD_ID, path);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/utils/SimpleCachedArray.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.utils;\n\nimport java.util.function.IntFunction;\n\npublic class SimpleCachedArray<T extends SimpleCachedArray.Element> extends SimpleResetPool<T, IntFunction<T>> {\n\n\tpublic SimpleCachedArray(int size, IntFunction<T> initializer) {\n\t\tsuper(size, initializer);\n\t}\n\n\t@Override\n\tprotected T create(IntFunction<T> context, int i) {\n\t\treturn context.apply(i);\n\t}\n\n\t@Override\n\tprotected void reset(T t) {\n\t\tt.reset();\n\t}\n\n\t@Override\n\tprotected void delete(T t) {\n\t\tt.delete();\n\t}\n\n\t@Override\n\tpublic T fail() {\n\t\texpand();\n\t\treturn get();\n\t}\n\n\tpublic interface Element {\n\n\t\tvoid reset\t();\n\t\tvoid delete\t();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/utils/SimpleResetPool.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.utils;\n\nimport lombok.Getter;\n\nimport java.util.Arrays;\n\npublic abstract class SimpleResetPool<T, C> {\n\n\t@Getter protected\tfinal\tC\t\t\tcontext;\n\n\t@Getter protected\t\t\tObject[]\tpool;\n\t@Getter protected\t\t\tint\t\t\tcursor;\n\tprotected \t\t\t\t\tint\t\t\tsize;\n\n\tpublic SimpleResetPool(int size, C context) {\n\t\tthis.size\t\t= size;\n\t\tthis.pool\t\t= new Object[size];\n\t\tthis.context\t= context;\n\n\t\tthis.cursor\t\t= 0;\n\n\t\tfor (var i = 0; i < this.size; i++) {\n\t\t\tthis.pool[i] = create(this.context, i);\n\t\t}\n\t}\n\n\tprotected abstract T\tcreate\t(C context, int i);\n\tprotected abstract void\treset\t(T t);\n\tprotected abstract void\tdelete\t(T t);\n\n\t@SuppressWarnings(\"unchecked\")\n\tpublic T get(boolean force) {\n\t\tif (cursor < size) {\n\t\t\tvar t = (T) pool[cursor ++];\n\n\t\t\tif (test(t)) {\n\t\t\t\tinit(t);\n\t\t\t\treturn t;\n\t\t\t}\n\t\t}\n\n\t\treturn fail(force);\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tpublic void reset() {\n\t\tfor (var i = 0; i < cursor; i++) {\n\t\t\treset((T) pool[i]);\n\t\t}\n\n\t\tcursor = 0;\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tpublic void delete() {\n\t\tfor (var i = 0; i < size; i++) {\n\t\t\tdelete((T) pool[i]);\n\t\t}\n\t}\n\n\tprotected void expand() {\n\t\tvar old\t= size;\n\n\t\tsize\t= old * 2;\n\t\tpool\t= Arrays.copyOf(pool, size);\n\n\t\tfor (var i = old; i < size; i ++) {\n\t\t\tpool[i] = create(context, i);\n\t\t}\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tpublic T at(int index) {\n\t\treturn (T) pool[index];\n\t}\n\n\tpublic T get() {\n\t\treturn get(false);\n\t}\n\n\tpublic void init(T t) {\n\n\t}\n\n\tprotected T fail(boolean force) {\n\t\treturn fail();\n\t}\n\n\tpublic T fail() {\n\t\treturn null;\n\t}\n\n\tprotected boolean test(T t) {\n\t\treturn true;\n\t}\n}"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/utils/SimpleTextureTarget.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.utils;\n\nimport com.mojang.blaze3d.pipeline.TextureTarget;\nimport net.minecraft.client.Minecraft;\n\npublic class SimpleTextureTarget extends TextureTarget {\n\n\tpublic SimpleTextureTarget(boolean useDepth) {\n\t\tsuper(\n\t\t\t\tMinecraft.getInstance().getWindow().getWidth\t(),\n\t\t\t\tMinecraft.getInstance().getWindow().getHeight\t(),\n\t\t\t\tuseDepth,\n\t\t\t\tMinecraft.ON_OSX\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/utils/TextureUtils.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.utils;\n\nimport com.github.argon4w.acceleratedrendering.AcceleratedRenderingModEntry;\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.mojang.blaze3d.platform.NativeImage;\nimport it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.packs.resources.ResourceManager;\nimport net.minecraft.server.packs.resources.ResourceManagerReloadListener;\nimport net.neoforged.api.distmarker.Dist;\nimport net.neoforged.bus.api.SubscribeEvent;\nimport net.neoforged.fml.common.EventBusSubscriber;\nimport net.neoforged.neoforge.client.event.RegisterClientReloadListenersEvent;\nimport org.lwjgl.system.MemoryStack;\n\nimport static org.lwjgl.opengl.GL46.*;\n\n@EventBusSubscriber(\n\t\tmodid\t= AcceleratedRenderingModEntry\t.MOD_ID,\n\t \tbus\t\t= EventBusSubscriber.Bus\t\t.MOD,\n\t\tvalue\t= Dist\t\t\t\t\t\t\t.CLIENT\n)\npublic class TextureUtils implements ResourceManagerReloadListener {\n\n\tprivate\tstatic final TextureUtils\t\t\t\t\t\t\t\t\t\t\t\t\tINSTANCE\t= new TextureUtils\t\t\t\t\t\t();\n\tprivate\tstatic final Object2ObjectLinkedOpenHashMap<ResourceLocation, NativeImage>\tIMAGE_CACHE\t= new Object2ObjectLinkedOpenHashMap<>\t();\n\n\t@Override\n\tpublic void onResourceManagerReload(ResourceManager resourceManager) {\n\t\tIMAGE_CACHE.clear();\n\t}\n\n\t@SubscribeEvent\n\tpublic static void onRegisterClientReloadListener(RegisterClientReloadListenersEvent event) {\n\t\tevent.registerReloadListener(INSTANCE);\n\t}\n\n\tpublic static NativeImage downloadTexture(RenderType renderType, int mipmapLevel) {\n\t\tvar textureLocation = RenderTypeUtils.getTextureLocation(renderType);\n\n\t\tif (textureLocation == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar image = IMAGE_CACHE.getAndMoveToFirst(textureLocation);\n\n\t\tif (image != null) {\n\t\t\treturn image;\n\t\t}\n\n\t\tMinecraft\n\t\t\t\t.getInstance\t\t()\n\t\t\t\t.getTextureManager\t()\n\t\t\t\t.getTexture\t\t\t(textureLocation)\n\t\t\t\t.bind\t\t\t\t();\n\n\t\ttry (var stack = MemoryStack.stackPush()) {\n\t\t\tvar widthBuffer\t\t= stack.callocInt(1);\n\t\t\tvar heightBuffer\t= stack.callocInt(1);\n\n\t\t\tglGetTexLevelParameteriv(\n\t\t\t\t\tGL_TEXTURE_2D,\n\t\t\t\t\tmipmapLevel,\n\t\t\t\t\tGL_TEXTURE_WIDTH,\n\t\t\t\t\twidthBuffer\n\t\t\t);\n\n\t\t\tglGetTexLevelParameteriv(\n\t\t\t\t\tGL_TEXTURE_2D,\n\t\t\t\t\tmipmapLevel,\n\t\t\t\t\tGL_TEXTURE_HEIGHT,\n\t\t\t\t\theightBuffer\n\t\t\t);\n\n\t\t\tvar width\t= widthBuffer\t.get(0);\n\t\t\tvar height\t= heightBuffer\t.get(0);\n\n\t\t\tif (width == 0 || height == 0) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tvar nativeImage = new NativeImage(\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\tfalse\n\t\t\t);\n\n\t\t\tnativeImage\t.downloadTexture\t(mipmapLevel,\t\tfalse);\n\t\t\tIMAGE_CACHE\t.putAndMoveToFirst\t(textureLocation,\tnativeImage);\n\n\t\t\tif (IMAGE_CACHE.size() > CoreFeature.getCachedImageSize()) {\n\t\t\t\tIMAGE_CACHE\n\t\t\t\t\t\t.removeLast\t()\n\t\t\t\t\t\t.close\t\t();\n\t\t\t}\n\n\t\t\treturn nativeImage;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/core/utils/Vertex.java",
    "content": "package com.github.argon4w.acceleratedrendering.core.utils;\n\nimport lombok.EqualsAndHashCode;\nimport lombok.Getter;\nimport net.minecraft.util.FastColor;\nimport net.minecraft.util.Mth;\nimport org.joml.Vector2f;\nimport org.joml.Vector2i;\nimport org.joml.Vector3f;\nimport org.joml.Vector4i;\n\n@Getter\n@EqualsAndHashCode\npublic class Vertex {\n\n\tpublic static final int NORMAL_X_OFFSET = 0;\n\tpublic static final int NORMAL_Y_OFFSET = 8;\n\tpublic static final int NORMAL_Z_OFFSET = 16;\n\n\tprivate final Vector3f position;\n\tprivate final Vector2f uv;\n\tprivate final Vector4i color;\n\tprivate final Vector2i light;\n\tprivate final Vector3f normal;\n\n\tpublic Vertex() {\n\t\tthis.position\t= new Vector3f();\n\t\tthis.uv\t\t\t= new Vector2f();\n\t\tthis.color\t\t= new Vector4i();\n\t\tthis.light\t\t= new Vector2i();\n\t\tthis.normal\t\t= new Vector3f();\n\t}\n\n\tpublic Vertex(Vertex vertex) {\n\t\tthis.position\t= new Vector3f(vertex.getPosition\t());\n\t\tthis.uv\t\t\t= new Vector2f(vertex.getUv\t\t\t());\n\t\tthis.color\t\t= new Vector4i(vertex.getColor\t\t());\n\t\tthis.light\t\t= new Vector2i(vertex.getLight\t\t());\n\t\tthis.normal\t\t= new Vector3f(vertex.getNormal\t\t());\n\t}\n\n\tpublic int getPackedLight() {\n\t\treturn light.x | light.y << 16;\n\t}\n\n\tpublic int getPackedColor() {\n\t\treturn FastColor.ARGB32.color(\n\t\t\t\tcolor.w,\n\t\t\t\tcolor.x,\n\t\t\t\tcolor.y,\n\t\t\t\tcolor.z\n\t\t);\n\t}\n\n\tpublic int getPackedNormal() {\n\t\treturn\t\t((byte) ((int) (Mth.clamp(normal.x, -1.0f, 1.0f) * 127.0f) & 0xFF) << NORMAL_X_OFFSET)\n\t\t\t\t|\t((byte) ((int) (Mth.clamp(normal.y, -1.0f, 1.0f) * 127.0f) & 0xFF) << NORMAL_Y_OFFSET)\n\t\t\t\t|\t((byte) ((int) (Mth.clamp(normal.z, -1.0f, 1.0f) * 127.0f) & 0xFF) << NORMAL_Z_OFFSET);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/culling/OrientationCullingFeature.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.culling;\n\nimport com.github.argon4w.acceleratedrendering.configs.FeatureConfig;\nimport com.github.argon4w.acceleratedrendering.configs.FeatureStatus;\n\nimport java.util.ArrayDeque;\nimport java.util.Deque;\n\npublic class OrientationCullingFeature {\n\n\tprivate static final Deque<FeatureStatus> CULLING_CONTROLLER_STACK = new ArrayDeque<>();\n\n\tpublic static boolean isEnabled() {\n\t\treturn FeatureConfig.CONFIG.orientationCullingFeatureStatus.get() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean shouldIgnoreCullState() {\n\t\treturn FeatureConfig.CONFIG.orientationCullingIgnoreCullState.get() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean shouldCull() {\n\t\treturn getCullingSetting() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static void disableCulling() {\n\t\tCULLING_CONTROLLER_STACK.push(FeatureStatus.DISABLED);\n\t}\n\n\tpublic static void forceEnableCulling() {\n\t\tCULLING_CONTROLLER_STACK.push(FeatureStatus.ENABLED);\n\t}\n\n\tpublic static void forceSetCulling(FeatureStatus status) {\n\t\tCULLING_CONTROLLER_STACK.push(status);\n\t}\n\n\tpublic static void resetCullingSetting() {\n\t\tCULLING_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static FeatureStatus getCullingSetting() {\n\t\treturn CULLING_CONTROLLER_STACK.isEmpty() ? getDefaultCullingSetting() : CULLING_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static FeatureStatus getDefaultCullingSetting() {\n\t\treturn FeatureConfig.CONFIG.orientationCullingDefaultCulling.get();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/culling/OrientationCullingProgramDispatcher.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.culling;\n\nimport com.github.argon4w.acceleratedrendering.core.backends.programs.ComputeProgram;\nimport com.github.argon4w.acceleratedrendering.core.backends.programs.Uniform;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder;\nimport com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderProgramLoader;\nimport com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramDispatcher;\nimport com.mojang.blaze3d.systems.RenderSystem;\nimport com.mojang.blaze3d.vertex.VertexFormat;\nimport net.minecraft.resources.ResourceLocation;\n\npublic class OrientationCullingProgramDispatcher implements ICullingProgramDispatcher {\n\n\tprivate static  final int\t\t\t\tGROUP_SIZE \t\t\t= 128;\n\tprivate static\tfinal int\t\t\t\tDISPATCH_COUNT_Y_Z\t= 1;\n\n\tprivate\t\t\tfinal VertexFormat.Mode\tmode;\n\tprivate\t\t\tfinal ComputeProgram\tprogram;\n\tprivate\t\t\tfinal Uniform\t\t\tviewMatrixUniform;\n\tprivate\t\t\tfinal Uniform\t\t\tprojectMatrixUniform;\n\tprivate\t\t\tfinal Uniform\t\t\tpolygonCountUniform;\n\tprivate\t\t\tfinal Uniform\t\t\tvertexOffsetUniform;\n\tprivate\t\t\tfinal Uniform\t\t\tvaryingOffsetUniform;\n\n\tpublic OrientationCullingProgramDispatcher(VertexFormat.Mode mode, ResourceLocation key) {\n\t\tthis.mode\t\t\t\t\t= mode;\n\t\tthis.program\t\t\t\t= ComputeShaderProgramLoader.getProgram(key);\n\t\tthis.viewMatrixUniform\t\t= this.program\t\t\t\t.getUniform(\"viewMatrix\");\n\t\tthis.projectMatrixUniform\t= this.program\t\t\t\t.getUniform(\"projectMatrix\");\n\t\tthis.polygonCountUniform\t= this.program\t\t\t\t.getUniform(\"polygonCount\");\n\t\tthis.vertexOffsetUniform\t= this.program\t\t\t\t.getUniform(\"vertexOffset\");\n\t\tthis.varyingOffsetUniform\t= this.program\t\t\t\t.getUniform(\"varyingOffset\");\n\t}\n\n\t@Override\n\tpublic int dispatch(AcceleratedBufferBuilder builder) {\n\t\tvar vertexCount\t\t= builder\t\t\t.getTotalVertexCount();\n\t\tvar polygonCount\t= vertexCount / mode.primitiveLength;\n\n\t\tviewMatrixUniform\t.uploadMatrix4f\t\t(RenderSystem\t.getModelViewMatrix\t());\n\t\tprojectMatrixUniform.uploadMatrix4f\t\t(RenderSystem\t.getProjectionMatrix());\n\t\tpolygonCountUniform\t.uploadUnsignedInt\t(polygonCount);\n\t\tvertexOffsetUniform\t.uploadUnsignedInt\t((int) (builder\t.getVertexBuffer\t().getOffset() / builder.getVertexSize\t()));\n\t\tvaryingOffsetUniform.uploadUnsignedInt\t((int) (builder\t.getVaryingBuffer\t().getOffset() / builder.getVaryingSize\t()));\n\n\t\tprogram.useProgram\t();\n\t\tprogram.dispatch\t(\n\t\t\t\t(polygonCount + GROUP_SIZE - 1) / GROUP_SIZE,\n\t\t\t\tDISPATCH_COUNT_Y_Z,\n\t\t\t\tDISPATCH_COUNT_Y_Z\n\t\t);\n\n\t\treturn program.getBarrierFlags();\n\t}\n\n\t@Override\n\tpublic boolean shouldCull() {\n\t\treturn OrientationCullingFeature.shouldCull();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/culling/OrientationCullingProgramSelector.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.culling;\n\nimport com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramDispatcher;\nimport com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramSelector;\nimport com.github.argon4w.acceleratedrendering.core.utils.RenderTypeUtils;\nimport com.mojang.blaze3d.vertex.VertexFormat;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.resources.ResourceLocation;\n\npublic class OrientationCullingProgramSelector implements ICullingProgramSelector {\n\n\tprivate final ICullingProgramSelector\tparent;\n\tprivate final ICullingProgramDispatcher\tquadDispatcher;\n\tprivate final ICullingProgramDispatcher\ttriangleDispatcher;\n\n\tpublic OrientationCullingProgramSelector(\n\t\t\tICullingProgramSelector\tparent,\n\t\t\tResourceLocation\t\tquadProgramKey,\n\t\t\tResourceLocation\t\ttriangleProgramKey\n\t) {\n\t\tthis.parent\t\t\t\t= parent;\n\t\tthis.quadDispatcher\t\t= new OrientationCullingProgramDispatcher(VertexFormat.Mode.QUADS,\t\tquadProgramKey);\n\t\tthis.triangleDispatcher\t= new OrientationCullingProgramDispatcher(VertexFormat.Mode.TRIANGLES,\ttriangleProgramKey);\n\t}\n\n\t@Override\n\tpublic ICullingProgramDispatcher select(RenderType renderType) {\n\t\tif (\t\t\tOrientationCullingFeature\t.isEnabled\t\t\t\t()\n\t\t\t\t&&\t(\tOrientationCullingFeature\t.shouldIgnoreCullState\t() || RenderTypeUtils.isCulled(renderType))\n\t\t) {\n\t\t\treturn switch (renderType.mode) {\n\t\t\t\tcase QUADS\t\t-> quadDispatcher;\n\t\t\t\tcase TRIANGLES\t-> triangleDispatcher;\n\t\t\t\tdefault\t\t\t-> parent.select(renderType);\n\t\t\t};\n\t\t}\n\n\t\treturn parent.select(renderType);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/culling/OrientationCullingPrograms.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.culling;\n\nimport com.github.argon4w.acceleratedrendering.AcceleratedRenderingModEntry;\nimport com.github.argon4w.acceleratedrendering.core.backends.programs.BarrierFlags;\nimport com.github.argon4w.acceleratedrendering.core.programs.LoadComputeShaderEvent;\nimport com.github.argon4w.acceleratedrendering.core.programs.culling.LoadCullingProgramSelectorEvent;\nimport com.github.argon4w.acceleratedrendering.core.utils.ResourceLocationUtils;\nimport com.mojang.blaze3d.vertex.DefaultVertexFormat;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.api.distmarker.Dist;\nimport net.neoforged.bus.api.EventPriority;\nimport net.neoforged.bus.api.SubscribeEvent;\nimport net.neoforged.fml.common.EventBusSubscriber;\n\n@EventBusSubscriber(\n\t\tmodid\t= AcceleratedRenderingModEntry\t.MOD_ID,\n\t\tbus\t\t= EventBusSubscriber.Bus\t\t.MOD,\n\t\tvalue\t= Dist\t\t\t\t\t\t\t.CLIENT\n)\npublic class OrientationCullingPrograms {\n\n\tpublic static final ResourceLocation CORE_ENTITY_QUAD_CULLING_KEY\t\t\t\t= ResourceLocationUtils.create(\"core_entity_quad_culling\");\n\tpublic static final ResourceLocation CORE_ENTITY_TRIANGLE_CULLING_KEY\t\t\t= ResourceLocationUtils.create(\"core_entity_triangle_culling\");\n\tpublic static final ResourceLocation CORE_BLOCK_QUAD_CULLING_KEY\t\t\t\t= ResourceLocationUtils.create(\"core_block_quad_culling\");\n\tpublic static final ResourceLocation CORE_BLOCK_TRIANGLE_CULLING_KEY\t\t\t= ResourceLocationUtils.create(\"core_block_triangle_culling\");\n\tpublic static final ResourceLocation CORE_POS_TEX_COLOR_QUAD_CULLING_KEY\t\t= ResourceLocationUtils.create(\"core_pos_tex_color_quad_culling\");\n\tpublic static final ResourceLocation CORE_POS_TEX_COLOR_TRIANGLE_CULLING_KEY\t= ResourceLocationUtils.create(\"core_pos_tex_color_triangle_culling\");\n\tpublic static final ResourceLocation CORE_POS_TEX_QUAD_CULLING_KEY\t\t\t\t= ResourceLocationUtils.create(\"core_pos_tex_quad_culling\");\n\tpublic static final ResourceLocation CORE_POS_TEX_TRIANGLE_CULLING_KEY\t\t\t= ResourceLocationUtils.create(\"core_pos_tex_triangle_culling\");\n\n\t@SubscribeEvent\n\tpublic static void onLoadComputeShaders(LoadComputeShaderEvent event) {\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_ENTITY_QUAD_CULLING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/culling/entity_quad_culling_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE,\n\t\t\t\tBarrierFlags\t\t\t.ATOMIC_COUNTER\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_ENTITY_TRIANGLE_CULLING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/culling/entity_triangle_culling_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE,\n\t\t\t\tBarrierFlags\t\t\t.ATOMIC_COUNTER\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_BLOCK_QUAD_CULLING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/culling/block_quad_culling_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE,\n\t\t\t\tBarrierFlags\t\t\t.ATOMIC_COUNTER\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_BLOCK_TRIANGLE_CULLING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/culling/block_triangle_culling_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE,\n\t\t\t\tBarrierFlags\t\t\t.ATOMIC_COUNTER\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_POS_TEX_COLOR_QUAD_CULLING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/culling/pos_tex_color_quad_culling_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE,\n\t\t\t\tBarrierFlags\t\t\t.ATOMIC_COUNTER\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_POS_TEX_COLOR_TRIANGLE_CULLING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/culling/pos_tex_color_triangle_culling_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE,\n\t\t\t\tBarrierFlags\t\t\t.ATOMIC_COUNTER\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_POS_TEX_QUAD_CULLING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/culling/pos_tex_quad_culling_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE,\n\t\t\t\tBarrierFlags\t\t\t.ATOMIC_COUNTER\n\t\t);\n\n\t\tevent.loadComputeShader(\n\t\t\t\tCORE_POS_TEX_TRIANGLE_CULLING_KEY,\n\t\t\t\tResourceLocationUtils\t.create(\"shaders/core/culling/pos_tex_triangle_culling_shader.compute\"),\n\t\t\t\tBarrierFlags\t\t\t.SHADER_STORAGE,\n\t\t\t\tBarrierFlags\t\t\t.ATOMIC_COUNTER\n\t\t);\n\t}\n\n\t@SubscribeEvent(priority = EventPriority.HIGH)\n\tpublic static void onLoadCullingPrograms(LoadCullingProgramSelectorEvent event) {\n\t\tevent.loadFor(DefaultVertexFormat.NEW_ENTITY, parent -> new OrientationCullingProgramSelector(\n\t\t\t\tparent,\n\t\t\t\tCORE_ENTITY_QUAD_CULLING_KEY,\n\t\t\t\tCORE_ENTITY_TRIANGLE_CULLING_KEY\n\t\t));\n\n\t\tevent.loadFor(DefaultVertexFormat.BLOCK, parent -> new OrientationCullingProgramSelector(\n\t\t\t\tparent,\n\t\t\t\tCORE_BLOCK_QUAD_CULLING_KEY,\n\t\t\t\tCORE_BLOCK_TRIANGLE_CULLING_KEY\n\t\t));\n\n\t\tevent.loadFor(DefaultVertexFormat.POSITION_TEX_COLOR, parent -> new OrientationCullingProgramSelector(\n\t\t\t\tparent,\n\t\t\t\tCORE_POS_TEX_COLOR_QUAD_CULLING_KEY,\n\t\t\t\tCORE_POS_TEX_COLOR_TRIANGLE_CULLING_KEY\n\t\t));\n\n\t\tevent.loadFor(DefaultVertexFormat.POSITION_TEX, parent -> new OrientationCullingProgramSelector(\n\t\t\t\tparent,\n\t\t\t\tCORE_POS_TEX_QUAD_CULLING_KEY,\n\t\t\t\tCORE_POS_TEX_TRIANGLE_CULLING_KEY\n\t\t));\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/emf/IEMFModelVariant.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.emf;\n\npublic interface IEMFModelVariant {\n\n\tvoid setCurrentVariant(int variant);\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/emf/mixins/EMFModelPartMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.emf.mixins;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IBufferGraph;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.github.argon4w.acceleratedrendering.core.meshes.IMesh;\nimport com.github.argon4w.acceleratedrendering.core.meshes.collectors.CulledMeshCollector;\nimport com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData;\nimport com.github.argon4w.acceleratedrendering.features.emf.IEMFModelVariant;\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.modelparts.mixins.ModelPartMixin;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport it.unimi.dsi.fastutil.ints.Int2ReferenceMap;\nimport it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;\nimport it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.model.geom.ModelPart;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Unique;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\nimport traben.entity_model_features.models.parts.EMFModelPart;\n\nimport java.util.Map;\n\n@ExtensionMethod(VertexConsumerExtension.class)\n@Mixin\t\t\t(EMFModelPart\t\t\t.class)\npublic class EMFModelPartMixin extends ModelPartMixin implements IEMFModelVariant {\n\n\t@Unique private final\tInt2ReferenceMap<Map<IBufferGraph,\tIMesh>>\temfMeshes\t= new Int2ReferenceOpenHashMap<>();\n\t@Unique private final\tInt2ReferenceMap<Map<MeshData,\t\tIMesh>>\temfMerges\t= new Int2ReferenceOpenHashMap<>();\n\t@Unique private\t\t\tint\t\t\t\t\t\t\t\t\t\t\temfVariant\t= Integer.MIN_VALUE;\n\n\n\t@Inject(\n\t\t\tmethod\t\t= \"renderLikeVanilla\",\n\t\t\tat\t\t\t= @At(\"HEAD\"),\n\t\t\tcancellable\t= true\n\t)\n\tpublic void renderLikeVanillaFast(\n\t\t\tPoseStack\t\tposeStack,\n\t\t\tVertexConsumer\tbuffer,\n\t\t\tint\t\t\t\tpackedLight,\n\t\t\tint\t\t\t\tpackedOverlay,\n\t\t\tint\t\t\t\tcolor,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tvar extension = buffer.getAccelerated();\n\n\t\tif (\t\t\tAcceleratedEntityRenderingFeature\t.isEnabled\t\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedEntityRenderingFeature\t.shouldUseAcceleratedPipeline\t()\n\t\t\t\t&&\t(\tCoreFeature\t\t\t\t\t\t\t.isRenderingLevel\t\t\t\t()\n\t\t\t\t||\t(\tCoreFeature\t\t\t\t\t\t\t.isRenderingGui\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedEntityRenderingFeature\t.shouldAccelerateInGui\t\t\t()))\n\t\t\t\t&&\t\textension\t\t\t\t\t\t\t.isAccelerated\t\t\t\t\t()\n\t\t) {\n\t\t\tci.cancel();\n\n\t\t\trenderFast(\n\t\t\t\t\t(ModelPart) (Object) this,\n\t\t\t\t\tposeStack,\n\t\t\t\t\textension,\n\t\t\t\t\tpackedLight,\n\t\t\t\t\tpackedOverlay,\n\t\t\t\t\tcolor\n\t\t\t);\n\t\t}\n\t}\n\n\t@Inject(\n\t\t\tmethod\t\t= \"compile\",\n\t\t\tat\t\t\t= @At(\"HEAD\"),\n\t\t\tcancellable\t= true\n\t)\n\tpublic void compileFast(\n\t\t\tPoseStack.Pose\tpPose,\n\t\t\tVertexConsumer\tpBuffer,\n\t\t\tint\t\t\t\tpPackedLight,\n\t\t\tint\t\t\t\tpPackedOverlay,\n\t\t\tint\t\t\t\tpColor,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tvar extension = pBuffer.getAccelerated();\n\n\t\tif (\t\t\tAcceleratedEntityRenderingFeature\t.isEnabled\t\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedEntityRenderingFeature\t.shouldUseAcceleratedPipeline\t()\n\t\t\t\t&&\t(\tCoreFeature\t\t\t\t\t\t\t.isRenderingLevel\t\t\t\t()\n\t\t\t\t||\t(\tCoreFeature\t\t\t\t\t\t\t.isRenderingGui\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedEntityRenderingFeature\t.shouldAccelerateInGui\t\t\t()))\n\t\t\t\t&&\t\textension\t\t\t\t\t\t\t.isAccelerated\t\t\t\t\t()\n\t\t) {\n\t\t\tci\t\t\t.cancel\t\t();\n\t\t\textension\t.doRender\t(\n\t\t\t\t\tthis,\n\t\t\t\t\tnull,\n\t\t\t\t\tpPose.pose\t(),\n\t\t\t\t\tpPose.normal(),\n\t\t\t\t\tpPackedLight,\n\t\t\t\t\tpPackedOverlay,\n\t\t\t\t\tpColor\n\t\t\t);\n\t\t}\n\t}\n\n\t@Unique\n\t@Override\n\tpublic void render(\n\t\t\tVertexConsumer\tvertexConsumer,\n\t\t\tVoid\t\t\tcontext,\n\t\t\tMatrix4f\t\ttransform,\n\t\t\tMatrix3f\t\tnormal,\n\t\t\tint\t\t\t\tlight,\n\t\t\tint\t\t\t\toverlay,\n\t\t\tint\t\t\t\tcolor\n\t) {\n\t\tvar meshes = emfMeshes.get(emfVariant);\n\t\tvar merges = emfMerges.get(emfVariant);\n\n\t\tif (\t\tmeshes == null\n\t\t\t\t||\tmerges == null\n\t\t) {\n\t\t\tmeshes = new Object2ObjectOpenHashMap<>();\n\t\t\tmerges = new Object2ObjectOpenHashMap<>();\n\n\t\t\temfMeshes.put(emfVariant, meshes);\n\t\t\temfMerges.put(emfVariant, merges);\n\t\t}\n\n\t\tvar extension\t= vertexConsumer.getAccelerated\t();\n\t\tvar mesh\t\t= meshes\t\t.get\t\t\t(extension);\n\n\t\textension.beginTransform(transform, normal);\n\n\t\tif (mesh != null) {\n\t\t\tmesh.write(\n\t\t\t\t\textension,\n\t\t\t\t\tcolor,\n\t\t\t\t\tlight,\n\t\t\t\t\toverlay\n\t\t\t);\n\n\t\t\textension.endTransform();\n\t\t\treturn;\n\t\t}\n\n\t\tvar culledMeshCollector\t= new CulledMeshCollector\t(extension);\n\t\tvar meshBuilder\t\t\t= extension.decorate\t\t(culledMeshCollector);\n\n\t\tfor (var cube : cubes) {\n\t\t\tfor (var polygon : cube.polygons) {\n\t\t\t\tvar polygonNormal = polygon.normal;\n\n\t\t\t\tfor (var vertex : polygon.vertices) {\n\t\t\t\t\tvar vertexPosition = vertex.pos;\n\n\t\t\t\t\tmeshBuilder.addVertex(\n\t\t\t\t\t\t\tvertexPosition.x / 16.0f,\n\t\t\t\t\t\t\tvertexPosition.y / 16.0f,\n\t\t\t\t\t\t\tvertexPosition.z / 16.0f,\n\t\t\t\t\t\t\t-1,\n\t\t\t\t\t\t\tvertex.u,\n\t\t\t\t\t\t\tvertex.v,\n\t\t\t\t\t\t\toverlay,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\tpolygonNormal.x,\n\t\t\t\t\t\t\tpolygonNormal.y,\n\t\t\t\t\t\t\tpolygonNormal.z\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tculledMeshCollector.flush();\n\n\t\tvar data\t= culledMeshCollector\t.getData\t();\n\t\tvar buffer\t= culledMeshCollector\t.getBuffer\t();\n\t\tmesh\t\t= merges\t\t\t\t.get\t\t(data);\n\n\t\tif (mesh != null) {\n\t\t\tbuffer.discard\t();\n\t\t\tbuffer.close\t();\n\t\t} else {\n\t\t\tmesh = AcceleratedEntityRenderingFeature\n\t\t\t\t\t.getMeshType()\n\t\t\t\t\t.getBuilder\t()\n\t\t\t\t\t.build\t\t(culledMeshCollector);\n\t\t}\n\n\t\tmeshes\t.put\t(extension, mesh);\n\t\tmerges\t.put\t(data,\t\tmesh);\n\t\tmesh\t.write\t(\n\t\t\t\textension,\n\t\t\t\tcolor,\n\t\t\t\tlight,\n\t\t\t\toverlay\n\t\t);\n\n\t\textension.endTransform();\n\t}\n\n\t@Unique\n\t@Override\n\tpublic void setCurrentVariant(int variant) {\n\t\temfVariant = variant;\n\t}\n\n\t@Unique\n\t@SuppressWarnings(\"unchecked\")\n\tprivate static void renderFast(\n\t\t\tModelPart\t\t\t\t\tmodelPart,\n\t\t\tPoseStack\t\t\t\t\tposeStack,\n\t\t\tIAcceleratedVertexConsumer\textension,\n\t\t\tint\t\t\t\t\t\t\tpackedLight,\n\t\t\tint\t\t\t\t\t\t\tpackedOverlay,\n\t\t\tint\t\t\t\t\t\t\tpackedColor\n\t) {\n\t\tif (!modelPart.visible) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (\t\tmodelPart.cubes\t\t.isEmpty()\n\t\t\t\t&&\tmodelPart.children\t.isEmpty()\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tposeStack.pushPose();\n\n\t\tmodelPart.translateAndRotate(poseStack);\n\n\t\tif (!modelPart.skipDraw) {\n\t\t\textension.doRender(\n\t\t\t\t\t(IAcceleratedRenderer<Void>) (Object) modelPart,\n\t\t\t\t\tnull,\n\t\t\t\t\tposeStack.last().pose(),\n\t\t\t\t\tposeStack.last().normal(),\n\t\t\t\t\tpackedLight,\n\t\t\t\t\tpackedOverlay,\n\t\t\t\t\tpackedColor\n\t\t\t);\n\t\t}\n\n\t\tfor(var child : modelPart.children.values()) {\n\t\t\trenderFast(\n\t\t\t\t\tchild,\n\t\t\t\t\tposeStack,\n\t\t\t\t\textension,\n\t\t\t\t\tpackedLight,\n\t\t\t\t\tpackedOverlay,\n\t\t\t\t\tpackedColor\n\t\t\t);\n\t\t}\n\n\t\tposeStack.popPose();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/emf/mixins/EMFModelPartWithStateMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.emf.mixins;\n\nimport com.github.argon4w.acceleratedrendering.features.emf.IEMFModelVariant;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\nimport traben.entity_model_features.models.parts.EMFModelPartWithState;\n\n@Mixin(EMFModelPartWithState.class)\npublic class EMFModelPartWithStateMixin {\n\n\t@Shadow public int currentModelVariant;\n\n\t@Inject(\n\t\t\tmethod\t= \"resetState\",\n\t\t\tat\t\t= @At(\"RETURN\")\n\t)\n\tpublic void resetEmfVariant(CallbackInfo ci) {\n\t\t((IEMFModelVariant) this).setCurrentVariant(currentModelVariant);\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"setVariantStateTo\",\n\t\t\tat\t\t= @At(\"RETURN\")\n\t)\n\tpublic void setEmfVariant(int newVariant, CallbackInfo ci) {\n\t\t((IEMFModelVariant) this).setCurrentVariant(newVariant);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/entities/AcceleratedEntityRenderingFeature.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.entities;\n\nimport com.github.argon4w.acceleratedrendering.configs.FeatureConfig;\nimport com.github.argon4w.acceleratedrendering.configs.FeatureStatus;\nimport com.github.argon4w.acceleratedrendering.configs.PipelineSetting;\nimport com.github.argon4w.acceleratedrendering.core.meshes.MeshType;\n\nimport java.util.ArrayDeque;\nimport java.util.Deque;\n\npublic class AcceleratedEntityRenderingFeature {\n\n\tprivate static final Deque<PipelineSetting>\tPIPELINE_CONTROLLER_STACK\t\t\t= new ArrayDeque<>();\n\tprivate static final Deque<FeatureStatus>\tGUI_ACCELERATION_CONTROLLER_STACK\t= new ArrayDeque<>();\n\n\tpublic static boolean isEnabled() {\n\t\treturn FeatureConfig.CONFIG.acceleratedEntityRenderingFeatureStatus.get() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean shouldUseAcceleratedPipeline() {\n\t\treturn getPipelineSetting() == PipelineSetting.ACCELERATED;\n\t}\n\n\tpublic static boolean shouldAccelerateInGui() {\n\t\treturn getGuiAccelerationSetting() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static MeshType getMeshType() {\n\t\treturn FeatureConfig.CONFIG.acceleratedEntityRenderingMeshType.get();\n\t}\n\n\tpublic static void useVanillaPipeline() {\n\t\tPIPELINE_CONTROLLER_STACK.push(PipelineSetting.VANILLA);\n\t}\n\n\tpublic static void dontAccelerateInGui() {\n\t\tGUI_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.DISABLED);\n\t}\n\n\tpublic static void forceUseAcceleratedPipeline() {\n\t\tPIPELINE_CONTROLLER_STACK.push(PipelineSetting.ACCELERATED);\n\t}\n\n\tpublic static void forceAccelerateInGui() {\n\t\tGUI_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.ENABLED);\n\t}\n\n\tpublic static void forceSetPipeline(PipelineSetting pipeline) {\n\t\tPIPELINE_CONTROLLER_STACK.push(pipeline);\n\t}\n\n\tpublic static void forceSetGuiAcceleration(FeatureStatus status) {\n\t\tGUI_ACCELERATION_CONTROLLER_STACK.push(status);\n\t}\n\n\tpublic static void resetPipeline() {\n\t\tPIPELINE_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static void resetGuiAcceleration() {\n\t\tGUI_ACCELERATION_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static PipelineSetting getPipelineSetting() {\n\t\treturn PIPELINE_CONTROLLER_STACK.isEmpty() ? getDefaultPipelineSetting() : PIPELINE_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static FeatureStatus getGuiAccelerationSetting() {\n\t\treturn GUI_ACCELERATION_CONTROLLER_STACK.isEmpty() ? getDefaultGuiAccelerationSetting() : GUI_ACCELERATION_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static PipelineSetting getDefaultPipelineSetting() {\n\t\treturn FeatureConfig.CONFIG.acceleratedEntityRenderingDefaultPipeline.get();\n\t}\n\n\tpublic static FeatureStatus getDefaultGuiAccelerationSetting() {\n\t\treturn FeatureConfig.CONFIG.acceleratedEntityRenderingGuiAcceleration.get();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/entities/AcceleratedEntityShadowRenderer.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.entities;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.LightTexture;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.util.FastColor;\nimport net.minecraft.world.level.LevelReader;\nimport net.minecraft.world.level.block.RenderShape;\nimport net.minecraft.world.level.chunk.ChunkAccess;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.joml.Vector2f;\nimport org.joml.Vector3f;\n\n@ExtensionMethod(VertexConsumerExtension.class)\npublic class AcceleratedEntityShadowRenderer implements IAcceleratedRenderer<AcceleratedEntityShadowRenderer.Context> {\n\n\t@Override\n\tpublic void render(\n\t\t\tVertexConsumer\tvertexConsumer,\n\t\t\tContext\t\t\tcontext,\n\t\t\tMatrix4f\t\ttransform,\n\t\t\tMatrix3f\t\tnormal,\n\t\t\tint\t\t\t\tlight,\n\t\t\tint\t\t\t\toverlay,\n\t\t\tint\t\t\t\tcolor\n\t) {\n\t\tvar extension\t= vertexConsumer\t.getAccelerated\t();\n\t\tvar levelReader\t= context\t\t\t.levelReader\t();\n\t\tvar chunkAccess\t= context\t\t\t.chunkAccess\t();\n\t\tvar blockPos\t= context\t\t\t.blockPos\t\t();\n\t\tvar center\t\t= context\t\t\t.center\t\t\t();\n\t\tvar size\t\t= context\t\t\t.size\t\t\t();\n\t\tvar weight\t\t= context\t\t\t.weight\t\t\t();\n\n\t\tvar belowPos\t= context.blockPos().below\t\t\t();\n\t\tvar blockState\t= chunkAccess\t\t.getBlockState\t(belowPos);\n\n\t\tif (blockState.getRenderShape() == RenderShape.INVISIBLE) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar levelBrightness = levelReader.getMaxLocalRawBrightness(blockPos);\n\n\t\tif (levelBrightness <= 3) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!blockState.isCollisionShapeFullBlock(chunkAccess, belowPos)) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar voxelShape = blockState.getShape(chunkAccess, belowPos);\n\n\t\tif (voxelShape.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar dimensionBrightness\t= LightTexture.getBrightness(levelReader.dimensionType(), levelBrightness);\n\t\tvar shadowTransparency\t= weight * 0.5f * dimensionBrightness * 255.0f;\n\n\t\tif (shadowTransparency < 0.0f) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (shadowTransparency > 255.0f) {\n\t\t\tshadowTransparency = 255.0f;\n\t\t}\n\n\t\tvar shadowColor\t= FastColor.ARGB32\t.color\t((int) shadowTransparency, color);\n\t\tvar bounds\t\t= voxelShape\t\t.bounds\t();\n\n\t\tvar minX = blockPos.getX() + (float) bounds.minX;\n\t\tvar maxX = blockPos.getX() + (float) bounds.maxX;\n\t\tvar minY = blockPos.getY() + (float) bounds.minY;\n\t\tvar minZ = blockPos.getZ() + (float) bounds.minZ;\n\t\tvar maxZ = blockPos.getZ() + (float) bounds.maxZ;\n\n\t\tvar minPosX = minX - center.x;\n\t\tvar maxPosX = maxX - center.x;\n\t\tvar minPosY = minY - center.y;\n\t\tvar minPosZ = minZ - center.z;\n\t\tvar maxPosZ = maxZ - center.z;\n\n\t\tvar u0 = -minPosX / 2.0f / size + 0.5f;\n\t\tvar u1 = -maxPosX / 2.0f / size + 0.5f;\n\t\tvar v0 = -minPosZ / 2.0f / size + 0.5f;\n\t\tvar v1 = -maxPosZ / 2.0f / size + 0.5f;\n\n\t\textension.beginTransform(transform, normal);\n\n\t\tvar positions = new Vector3f[] {\n\t\t\t\tnew Vector3f(minPosX, minPosY, minPosZ),\n\t\t\t\tnew Vector3f(minPosX, minPosY, maxPosZ),\n\t\t\t\tnew Vector3f(maxPosX, minPosY, maxPosZ),\n\t\t\t\tnew Vector3f(maxPosX, minPosY, minPosZ),\n\t\t};\n\n\t\tvar texCoords = new Vector2f[] {\n\t\t\t\tnew Vector2f(u0, v0),\n\t\t\t\tnew Vector2f(u0, v1),\n\t\t\t\tnew Vector2f(u1, v1),\n\t\t\t\tnew Vector2f(u1, v0),\n\t\t};\n\n\t\tfor (var i = 0; i < 4; i ++) {\n\t\t\tvar position = positions[i];\n\t\t\tvar texCoord = texCoords[i];\n\n\t\t\tvertexConsumer.addVertex(\n\t\t\t\t\tposition.x,\n\t\t\t\t\tposition.y,\n\t\t\t\t\tposition.z,\n\t\t\t\t\tshadowColor,\n\t\t\t\t\ttexCoord.x,\n\t\t\t\t\ttexCoord.y,\n\t\t\t\t\toverlay,\n\t\t\t\t\tlight,\n\t\t\t\t\t0.0f,\n\t\t\t\t\t1.0f,\n\t\t\t\t\t0.0f\n\t\t\t);\n\t\t}\n\n\t\textension.endTransform();\n\t}\n\n\tpublic record Context(\n\t\t\tLevelReader\tlevelReader,\n\t\t\tChunkAccess\tchunkAccess,\n\t\t\tBlockPos\tblockPos,\n\t\t\tVector3f\tcenter,\n\t\t\tfloat\t\tsize,\n\t\t\tfloat\t\tweight\n\t) {\n\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/entities/mixins/EntityRenderDispatcherMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.entities.mixins;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityShadowRenderer;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.LightTexture;\nimport net.minecraft.client.renderer.entity.EntityRenderDispatcher;\nimport net.minecraft.client.renderer.texture.OverlayTexture;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.world.level.LevelReader;\nimport net.minecraft.world.level.chunk.ChunkAccess;\nimport org.joml.Matrix3f;\nimport org.joml.Vector3f;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Unique;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@ExtensionMethod(VertexConsumerExtension.class)\n@Mixin\t\t\t(\n\t\tvalue\t\t= EntityRenderDispatcher.class,\n\t\tpriority\t= 999\n)\npublic class EntityRenderDispatcherMixin {\n\n\t@Unique private static final Matrix3f\t\t\t\t\t\t\tSHADOW_NORMAL_MATRIX\t= new Matrix3f().identity\t\t\t\t();\n\t@Unique private static final AcceleratedEntityShadowRenderer\tSHADOW_RENDERER\t\t\t= new AcceleratedEntityShadowRenderer\t();\n\n\t@Inject(\n\t\t\tmethod\t\t= \"renderBlockShadow\",\n\t\t\tat\t\t\t= @At(\"HEAD\"),\n\t\t\tcancellable\t= true\n\t)\n\tprivate static void fastBlockShadow(\n\t\t\tPoseStack.Pose\tpPose,\n\t\t\tVertexConsumer\tpVertexConsumer,\n\t\t\tChunkAccess\t\tpChunk,\n\t\t\tLevelReader\t\tpLevel,\n\t\t\tBlockPos\t\tpPos,\n\t\t\tdouble\t\t\tpX,\n\t\t\tdouble\t\t\tpY,\n\t\t\tdouble\t\t\tpZ,\n\t\t\tfloat\t\t\tpSize,\n\t\t\tfloat\t\t\tpWeight,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tvar extension = pVertexConsumer.getAccelerated();\n\n\t\tif (\t\tCoreFeature\t\t\t\t\t\t\t.isRenderingLevel\t\t\t\t()\n\t\t\t\t&&\tAcceleratedEntityRenderingFeature\t.isEnabled\t\t\t\t\t\t()\n\t\t\t\t&&\tAcceleratedEntityRenderingFeature\t.shouldUseAcceleratedPipeline\t()\n\t\t\t\t&&\textension\t\t\t\t\t\t\t.isAccelerated\t\t\t\t\t()\n\t\t) {\n\t\t\tci\t\t\t.cancel\t\t();\n\t\t\textension\t.doRender\t(\n\t\t\t\t\tSHADOW_RENDERER,\n\t\t\t\t\tnew AcceleratedEntityShadowRenderer.Context(\n\t\t\t\t\t\t\tpLevel,\n\t\t\t\t\t\t\tpChunk,\n\t\t\t\t\t\t\tpPos,\n\t\t\t\t\t\t\tnew Vector3f(\n\t\t\t\t\t\t\t\t\t(float) pX,\n\t\t\t\t\t\t\t\t\t(float) pY,\n\t\t\t\t\t\t\t\t\t(float) pZ\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tpSize,\n\t\t\t\t\t\t\tpWeight\n\t\t\t\t\t),\n\t\t\t\t\tpPose.pose(),\n\t\t\t\t\tSHADOW_NORMAL_MATRIX,\n\t\t\t\t\tLightTexture\t.FULL_BRIGHT,\n\t\t\t\t\tOverlayTexture\t.NO_OVERLAY,\n\t\t\t\t\t-1\n\t\t\t);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/entities/mixins/InventoryScreenMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.entities.mixins;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreBuffers;\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.CoreStates;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.BufferSourceExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType;\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport com.mojang.blaze3d.platform.Lighting;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.gui.screens.inventory.InventoryScreen;\nimport net.minecraft.client.renderer.entity.EntityRenderDispatcher;\nimport net.minecraft.world.entity.LivingEntity;\nimport org.spongepowered.asm.mixin.Mixin;\n\n@ExtensionMethod(BufferSourceExtension\t.class)\n@Mixin\t\t\t(InventoryScreen\t\t.class)\npublic class InventoryScreenMixin {\n\n\t@WrapMethod(method = \"lambda$renderEntityInInventory$1\")\n\tprivate static void renderEntityInInventoryFast(\n\t\t\tEntityRenderDispatcher\tentityRenderDispatcher,\n\t\t\tLivingEntity\t\t\tentity,\n\t\t\tGuiGraphics\t\t\t\tguiGraphics,\n\t\t\tOperation<Void>\t\t\toperation\n\t) {\n\t\tif (\t\t!guiGraphics.bufferSource().getAcceleratable()\t.isBufferSourceAcceleratable\t()\n\t\t\t\t||\t!AcceleratedEntityRenderingFeature\t\t\t\t.isEnabled\t\t\t\t\t\t()\n\t\t\t\t||\t!AcceleratedEntityRenderingFeature\t\t\t\t.shouldUseAcceleratedPipeline\t()\n\t\t\t\t||\t!AcceleratedEntityRenderingFeature\t\t\t\t.shouldAccelerateInGui\t\t\t()\n\t\t\t\t||\t!CoreFeature\t\t\t\t\t\t\t\t\t.isLoaded\t\t\t\t\t\t()\n\t\t) {\n\t\t\toperation.call(\n\t\t\t\t\tentityRenderDispatcher,\n\t\t\t\t\tentity,\n\t\t\t\t\tguiGraphics\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (CoreFeature.isGuiBatching()) {\n\t\t\tCoreFeature.forceSetDefaultLayer\t\t\t\t(2);\n\t\t\tCoreFeature.forceSetDefaultLayerBeforeFunction\t(Lighting::setupForEntityInInventory);\n\t\t\tCoreFeature.forceSetDefaultLayerAfterFunction\t(Lighting::setupFor3DItems);\n\t\t}\n\n\t\tCoreFeature.setRenderingGui();\n\n\t\toperation.call(\n\t\t\t\tentityRenderDispatcher,\n\t\t\t\tentity,\n\t\t\t\tguiGraphics\n\t\t);\n\n\t\tCoreFeature.resetRenderingGui();\n\n\t\tif (CoreFeature.isGuiBatching()) {\n\t\t\tCoreFeature.resetDefaultLayer\t\t\t\t();\n\t\t\tCoreFeature.resetDefaultLayerBeforeFunction\t();\n\t\t\tCoreFeature.resetDefaultLayerAfterFunction\t();\n\t\t} else {\n\t\t\tCoreStates\t\t\t\t\t\t.recordBuffers\t();\n\t\t\tCoreBuffers.ENTITY\t\t\t\t.prepareBuffers\t();\n\t\t\tCoreBuffers.BLOCK\t\t\t\t.prepareBuffers\t();\n\t\t\tCoreBuffers.POS\t\t\t\t\t.prepareBuffers\t();\n\t\t\tCoreBuffers.POS_COLOR\t\t\t.prepareBuffers\t();\n\t\t\tCoreBuffers.POS_TEX\t\t\t\t.prepareBuffers\t();\n\t\t\tCoreBuffers.POS_TEX_COLOR\t\t.prepareBuffers\t();\n\t\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.prepareBuffers\t();\n\t\t\tCoreStates\t\t\t\t\t\t.restoreBuffers\t();\n\n\t\t\tCoreBuffers.ENTITY\t\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\t\tCoreBuffers.BLOCK\t\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\t\tCoreBuffers.POS\t\t\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\t\tCoreBuffers.POS_COLOR\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\t\tCoreBuffers.POS_TEX\t\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\t\tCoreBuffers.POS_TEX_COLOR\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.drawBuffers\t(LayerDrawType.ALL);\n\n\t\t\tCoreBuffers.ENTITY\t\t\t\t.clearBuffers\t();\n\t\t\tCoreBuffers.BLOCK\t\t\t\t.clearBuffers\t();\n\t\t\tCoreBuffers.POS\t\t\t\t\t.clearBuffers\t();\n\t\t\tCoreBuffers.POS_COLOR\t\t\t.clearBuffers\t();\n\t\t\tCoreBuffers.POS_TEX\t\t\t\t.clearBuffers\t();\n\t\t\tCoreBuffers.POS_TEX_COLOR\t\t.clearBuffers\t();\n\t\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.clearBuffers\t();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/filter/FilterFeature.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.filter;\n\nimport com.github.argon4w.acceleratedrendering.configs.FeatureConfig;\nimport com.github.argon4w.acceleratedrendering.configs.FeatureStatus;\nimport com.github.argon4w.acceleratedrendering.core.utils.RegistryFilter;\nimport it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.world.entity.Entity;\nimport net.minecraft.world.entity.EntityType;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.minecraft.world.inventory.MenuType;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.entity.BlockEntityType;\nimport net.neoforged.neoforge.client.event.RenderLevelStageEvent;\n\nimport java.util.ArrayDeque;\nimport java.util.Deque;\nimport java.util.Set;\n\npublic class FilterFeature {\n\n\tprivate static final Deque\t<FeatureStatus>\t\t\tMENU_FILTER_CONTROLLER_STACK\t\t\t= new ArrayDeque<>();\n\tprivate\tstatic final Deque\t<FeatureStatus>\t\t\tENTITIES_FILTER_CONTROLLER_STACK\t\t= new ArrayDeque<>();\n\tprivate\tstatic final Deque\t<FeatureStatus>\t\t\tBLOCK_ENTITIES_FILTER_CONTROLLER_STACK\t= new ArrayDeque<>();\n\tprivate\tstatic final Deque\t<FeatureStatus>\t\t\tITEM_FILTER_CONTROLLER_STACK\t\t\t= new ArrayDeque<>();\n\tprivate static final Deque\t<FeatureStatus>\t\t\tSTAGE_FILTER_CONTROLLER_STACK\t\t\t= new ArrayDeque<>();\n\n\tprivate static final Set\t<MenuType<?>>\t\t\tMENU_FILTER_VALUES;\n\tprivate\tstatic final Set\t<EntityType<?>>\t\t\tENTITY_FILTER_VALUES;\n\tprivate\tstatic final Set\t<BlockEntityType<?>>\tBLOCK_ENTITY_FILTER_VALUES;\n\tprivate static final Set\t<Item>\t\t\t\t\tITEM_FILTER_VALUES;\n\tprivate static final Set\t<String>\t\t\t\tSTAGE_FILTER_VALUES;\n\n\tstatic {\n\t\tMENU_FILTER_VALUES\t\t\t= RegistryFilter.filterValues\t(BuiltInRegistries.MENU,\t\t\t\tFeatureConfig.CONFIG.filterMenuFilterValues\t\t\t.get());\n\t\tENTITY_FILTER_VALUES\t\t= RegistryFilter.filterValues\t(BuiltInRegistries.ENTITY_TYPE,\t\t\tFeatureConfig.CONFIG.filterEntityFilterValues\t\t.get());\n\t\tBLOCK_ENTITY_FILTER_VALUES\t= RegistryFilter.filterValues\t(BuiltInRegistries.BLOCK_ENTITY_TYPE,\tFeatureConfig.CONFIG.filterBlockEntityFilterValues\t.get());\n\t\tITEM_FILTER_VALUES\t\t\t= RegistryFilter.filterValues\t(BuiltInRegistries.ITEM,\t\t\t\tFeatureConfig.CONFIG.filterItemFilterValues\t\t\t.get());\n\t\tSTAGE_FILTER_VALUES\t\t\t= new ReferenceOpenHashSet<>\t(\t\t\t\t\t\t\t\t\t\tFeatureConfig.CONFIG.filterStageFilterValues\t\t.get());\n\t}\n\n\tpublic static boolean isEnabled() {\n\t\treturn FeatureConfig.CONFIG.filterFeatureStatus.get() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean testMenu(AbstractContainerMenu menu) {\n\t\treturn menu.menuType == null || getMenuFilterType().test(MENU_FILTER_VALUES, menu.menuType);\n\t}\n\n\tpublic static boolean testEntity(Entity entity) {\n\t\treturn getEntityFilterType().test(ENTITY_FILTER_VALUES, entity.getType());\n\t}\n\n\tpublic static boolean testBlockEntity(BlockEntity entity) {\n\t\treturn getBlockEntityFilterType().test(BLOCK_ENTITY_FILTER_VALUES, entity.getType());\n\t}\n\n\tpublic static boolean testItem(ItemStack itemStack) {\n\t\treturn getItemFilterType().test(ITEM_FILTER_VALUES, itemStack.getItem());\n\t}\n\n\tpublic static boolean testStage(RenderLevelStageEvent.Stage stage) {\n\t\treturn getStageFilterType().test(STAGE_FILTER_VALUES, stage.toString());\n\t}\n\n\tpublic static boolean shouldFilterMenus() {\n\t\treturn getMenuFilterSetting() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean shouldFilterEntities() {\n\t\treturn getEntityFilterSetting() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean shouldFilterBlockEntities() {\n\t\treturn getBlockEntityFilterSetting() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean shouldFilterItems() {\n\t\treturn getItemFilterSetting() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean shouldFilterStage() {\n\t\treturn getStageFilterSetting() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static FilterType getMenuFilterType() {\n\t\treturn FeatureConfig.CONFIG.filterMenuFilterType.get();\n\t}\n\n\tpublic static FilterType getEntityFilterType() {\n\t\treturn FeatureConfig.CONFIG.filterEntityFilterType.get();\n\t}\n\n\tpublic static FilterType getBlockEntityFilterType() {\n\t\treturn FeatureConfig.CONFIG.filterBlockEntityFilterType.get();\n\t}\n\n\tpublic static FilterType getItemFilterType() {\n\t\treturn FeatureConfig.CONFIG.filterItemFilterType.get();\n\t}\n\n\tpublic static FilterType getStageFilterType() {\n\t\treturn FeatureConfig.CONFIG.filterStageFilterType.get();\n\t}\n\n\tpublic static void disableMenuFilter() {\n\t\tMENU_FILTER_CONTROLLER_STACK.push(FeatureStatus.DISABLED);\n\t}\n\n\tpublic static void disableEntityFilter() {\n\t\tENTITIES_FILTER_CONTROLLER_STACK.push(FeatureStatus.DISABLED);\n\t}\n\n\tpublic static void disableBlockEntityFilter() {\n\t\tBLOCK_ENTITIES_FILTER_CONTROLLER_STACK.push(FeatureStatus.DISABLED);\n\t}\n\n\tpublic static void disableItemFilter() {\n\t\tITEM_FILTER_CONTROLLER_STACK.push(FeatureStatus.DISABLED);\n\t}\n\n\tpublic static void disableStageFilter() {\n\t\tSTAGE_FILTER_CONTROLLER_STACK.push(FeatureStatus.DISABLED);\n\t}\n\n\tpublic static void forceEnableMenuFilter() {\n\t\tMENU_FILTER_CONTROLLER_STACK.push(FeatureStatus.ENABLED);\n\t}\n\n\tpublic static void forceEnableEntityFilter() {\n\t\tENTITIES_FILTER_CONTROLLER_STACK.push(FeatureStatus.ENABLED);\n\t}\n\n\tpublic static void forceEnableBlockEntityFilter() {\n\t\tBLOCK_ENTITIES_FILTER_CONTROLLER_STACK.push(FeatureStatus.ENABLED);\n\t}\n\n\tpublic static void forceEnableItemFilter() {\n\t\tITEM_FILTER_CONTROLLER_STACK.push(FeatureStatus.ENABLED);\n\t}\n\n\tpublic static void forceEnableStageFilter() {\n\t\tSTAGE_FILTER_CONTROLLER_STACK.push(FeatureStatus.ENABLED);\n\t}\n\n\tpublic static void forceSetMenuFilter(FeatureStatus status) {\n\t\tMENU_FILTER_CONTROLLER_STACK.push(status);\n\t}\n\n\tpublic static void forceSetEntityFilter(FeatureStatus status) {\n\t\tENTITIES_FILTER_CONTROLLER_STACK.push(status);\n\t}\n\n\tpublic static void forceSetBlockEntityFilter(FeatureStatus status) {\n\t\tBLOCK_ENTITIES_FILTER_CONTROLLER_STACK.push(status);\n\t}\n\n\tpublic static void forceSetItemFilter(FeatureStatus status) {\n\t\tITEM_FILTER_CONTROLLER_STACK.push(status);\n\t}\n\n\tpublic static void forceSetStageFilter(FeatureStatus status) {\n\t\tSTAGE_FILTER_CONTROLLER_STACK.push(status);\n\t}\n\n\tpublic static void resetMenuFilter() {\n\t\tMENU_FILTER_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static void resetEntityFilter() {\n\t\tENTITIES_FILTER_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static void resetBlockEntityFilter() {\n\t\tBLOCK_ENTITIES_FILTER_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static void resetItemFilter() {\n\t\tITEM_FILTER_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static void resetStageFilter() {\n\t\tSTAGE_FILTER_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static FeatureStatus getMenuFilterSetting() {\n\t\treturn MENU_FILTER_CONTROLLER_STACK.isEmpty() ? getDefaultMenuFilterSetting() : MENU_FILTER_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static FeatureStatus getEntityFilterSetting() {\n\t\treturn ENTITIES_FILTER_CONTROLLER_STACK.isEmpty() ? getDefaultEntityFilterSetting() : ENTITIES_FILTER_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static FeatureStatus getBlockEntityFilterSetting() {\n\t\treturn BLOCK_ENTITIES_FILTER_CONTROLLER_STACK.isEmpty() ? getDefaultBlockEntityFilterSetting() : BLOCK_ENTITIES_FILTER_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static FeatureStatus getItemFilterSetting() {\n\t\treturn ITEM_FILTER_CONTROLLER_STACK.isEmpty() ? getDefaultItemFilterSetting() : ITEM_FILTER_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static FeatureStatus getStageFilterSetting() {\n\t\treturn STAGE_FILTER_CONTROLLER_STACK.isEmpty() ? getDefaultStageFilterSetting() : STAGE_FILTER_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static FeatureStatus getDefaultMenuFilterSetting() {\n\t\treturn FeatureConfig.CONFIG.filterMenuFilter.get();\n\t}\n\n\tpublic static FeatureStatus getDefaultEntityFilterSetting() {\n\t\treturn FeatureConfig.CONFIG.filterEntityFilter.get();\n\t}\n\n\tpublic static FeatureStatus getDefaultBlockEntityFilterSetting() {\n\t\treturn FeatureConfig.CONFIG.filterBlockEntityFilter.get();\n\t}\n\n\tpublic static FeatureStatus getDefaultItemFilterSetting() {\n\t\treturn FeatureConfig.CONFIG.filterItemFilter.get();\n\t}\n\n\tpublic static FeatureStatus getDefaultStageFilterSetting() {\n\t\treturn FeatureConfig.CONFIG.filterStageFilter.get();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/filter/FilterType.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.filter;\n\nimport java.util.Set;\n\npublic enum FilterType {\n\n\tBLACKLIST,\n\tWHITELIST;\n\n\tpublic <T> boolean test(Set<T> values, T value) {\n\t\treturn switch (this) {\n\t\t\tcase WHITELIST -> \tvalues.contains(value);\n\t\t\tcase BLACKLIST -> !\tvalues.contains(value);\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/filter/mixins/AbstractContainerScreenMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.filter.mixins;\n\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.filter.FilterFeature;\nimport com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature;\nimport com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\n\n@Mixin(value = AbstractContainerScreen.class)\npublic class AbstractContainerScreenMixin {\n\n\t@Shadow @Final protected AbstractContainerMenu menu;\n\n\t@WrapMethod(method = \"render\")\n\tpublic void startBatching(\n\t\t\tGuiGraphics\t\tguiGraphics,\n\t\t\tint\t\t\t\tmouseX,\n\t\t\tint\t\t\t\tmouseY,\n\t\t\tfloat\t\t\tpartialTick,\n\t\t\tOperation<Void>\toriginal\n\t) {\n\t\tvar pass =\t!\tFilterFeature.isEnabled\t\t\t()\n\t\t\t\t||\t!\tFilterFeature.shouldFilterMenus\t()\n\t\t\t\t||\t\tFilterFeature.testMenu\t\t\t(menu);\n\n\t\tif (!pass) {\n\t\t\tAcceleratedEntityRenderingFeature\t.useVanillaPipeline();\n\t\t\tAcceleratedItemRenderingFeature\t\t.useVanillaPipeline();\n\t\t\tAcceleratedTextRenderingFeature\t\t.useVanillaPipeline();\n\t\t}\n\n\t\toriginal.call(\n\t\t\t\tguiGraphics,\n\t\t\t\tmouseX,\n\t\t\t\tmouseY,\n\t\t\t\tpartialTick\n\t\t);\n\n\t\tif (!pass) {\n\t\t\tAcceleratedEntityRenderingFeature\t.resetPipeline();\n\t\t\tAcceleratedItemRenderingFeature\t\t.resetPipeline();\n\t\t\tAcceleratedTextRenderingFeature\t\t.resetPipeline();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/filter/mixins/BlockEntityRenderDispatcherMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.filter.mixins;\n\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.filter.FilterFeature;\nimport com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;\nimport net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.At;\n\n@Mixin(BlockEntityRenderDispatcher.class)\npublic class BlockEntityRenderDispatcherMixin {\n\n\t@WrapOperation(\n\t\t\tmethod\t= \"tryRender\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Ljava/lang/Runnable;run()V\"\n\t\t\t)\n\t)\n\tprivate static void filterBlockEntity(\n\t\t\tRunnable\t\tinstance,\n\t\t\tOperation<Void>\toriginal,\n\t\t\tBlockEntity\t\tblockEntity\n\t) {\n\t\tvar pass =\t!\tFilterFeature.isEnabled\t\t\t\t\t()\n\t\t\t\t||\t!\tFilterFeature.shouldFilterBlockEntities\t()\n\t\t\t\t||\t\tFilterFeature.testBlockEntity\t\t\t(blockEntity);\n\n\t\tif (!pass) {\n\t\t\tAcceleratedEntityRenderingFeature\t.useVanillaPipeline();\n\t\t\tAcceleratedItemRenderingFeature\t\t.useVanillaPipeline();\n\t\t\tAcceleratedTextRenderingFeature\t\t.useVanillaPipeline();\n\t\t}\n\n\t\toriginal.call(instance);\n\n\t\tif (!pass) {\n\t\t\tAcceleratedEntityRenderingFeature\t.resetPipeline();\n\t\t\tAcceleratedItemRenderingFeature\t\t.resetPipeline();\n\t\t\tAcceleratedTextRenderingFeature\t\t.resetPipeline();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/filter/mixins/ClientHooksMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.filter.mixins;\n\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.filter.FilterFeature;\nimport com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;\nimport net.neoforged.bus.api.Event;\nimport net.neoforged.bus.api.IEventBus;\nimport net.neoforged.neoforge.client.ClientHooks;\nimport net.neoforged.neoforge.client.event.RenderLevelStageEvent;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.At;\n\n@Mixin(ClientHooks.class)\npublic class ClientHooksMixin {\n\n\t@WrapOperation(\n\t\t\tmethod\t= \"dispatchRenderStage(Lnet/neoforged/neoforge/client/event/RenderLevelStageEvent$Stage;Lnet/minecraft/client/renderer/LevelRenderer;Lcom/mojang/blaze3d/vertex/PoseStack;Lorg/joml/Matrix4f;Lorg/joml/Matrix4f;ILnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/culling/Frustum;)V\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/neoforged/bus/api/IEventBus;post(Lnet/neoforged/bus/api/Event;)Lnet/neoforged/bus/api/Event;\"\n\t\t\t)\n\t)\n\tprivate static Event startRenderLevelStage(\n\t\t\tIEventBus\t\t\t\t\tinstance,\n\t\t\tEvent\t\t\t\t\t\tevent,\n\t\t\tOperation<Event>\t\t\toriginal,\n\t\t\tRenderLevelStageEvent.Stage\tstage\n\t) {\n\t\tvar pass =\t!\tFilterFeature.isEnabled\t\t\t()\n\t\t\t\t||\t!\tFilterFeature.shouldFilterStage\t()\n\t\t\t\t||\t\tFilterFeature.testStage\t\t\t(stage);\n\n\t\tif (!pass) {\n\t\t\tAcceleratedEntityRenderingFeature\t.useVanillaPipeline();\n\t\t\tAcceleratedItemRenderingFeature\t\t.useVanillaPipeline();\n\t\t\tAcceleratedTextRenderingFeature\t\t.useVanillaPipeline();\n\t\t}\n\n\t\tvar result = original.call(instance, event);\n\n\t\tif (!pass) {\n\t\t\tAcceleratedEntityRenderingFeature\t.resetPipeline();\n\t\t\tAcceleratedItemRenderingFeature\t\t.resetPipeline();\n\t\t\tAcceleratedTextRenderingFeature\t\t.resetPipeline();\n\t\t}\n\n\t\treturn result;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/filter/mixins/ItemRendererMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.filter.mixins;\n\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.filter.FilterFeature;\nimport com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport net.minecraft.client.renderer.entity.ItemRenderer;\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.world.item.ItemStack;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.At;\n\n@Mixin(\n\t\tvalue\t\t= ItemRenderer.class,\n\t\tpriority\t= 1001\n)\npublic class ItemRendererMixin {\n\n\t@WrapOperation(\n\t\t\tmethod\t= \"render\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/minecraft/client/renderer/entity/ItemRenderer;renderModelLists(Lnet/minecraft/client/resources/model/BakedModel;Lnet/minecraft/world/item/ItemStack;IILcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;)V\"\n\t\t\t)\n\t)\n\tpublic void filterItem(\n\t\t\tItemRenderer\tinstance,\n\t\t\tBakedModel\t\tbakedModel,\n\t\t\tItemStack\t\tmodel,\n\t\t\tint\t\t\t\tstack,\n\t\t\tint\t\t\t\tcombinedLight,\n\t\t\tPoseStack\t\tcombinedOverlay,\n\t\t\tVertexConsumer\tposeStack,\n\t\t\tOperation<Void>\toriginal\n\t) {\n\t\tvar pass =\t!\tFilterFeature.isEnabled\t\t\t()\n\t\t\t\t||\t!\tFilterFeature.shouldFilterItems\t()\n\t\t\t\t||\t\tFilterFeature.testItem\t\t\t(model);\n\n\t\tif (!pass) {\n\t\t\tAcceleratedEntityRenderingFeature\t.useVanillaPipeline();\n\t\t\tAcceleratedItemRenderingFeature\t\t.useVanillaPipeline();\n\t\t\tAcceleratedTextRenderingFeature\t\t.useVanillaPipeline();\n\t\t}\n\n\t\toriginal.call(\n\t\t\t\tinstance,\n\t\t\t\tbakedModel,\n\t\t\t\tmodel,\n\t\t\t\tstack,\n\t\t\t\tcombinedLight,\n\t\t\t\tcombinedOverlay,\n\t\t\t\tposeStack\n\t\t);\n\n\t\tif (!pass) {\n\t\t\tAcceleratedEntityRenderingFeature\t.resetPipeline();\n\t\t\tAcceleratedItemRenderingFeature\t\t.resetPipeline();\n\t\t\tAcceleratedTextRenderingFeature\t\t.resetPipeline();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/filter/mixins/LevelRendererMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.filter.mixins;\n\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.filter.FilterFeature;\nimport com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport net.minecraft.client.renderer.LevelRenderer;\nimport net.minecraft.client.renderer.MultiBufferSource;\nimport net.minecraft.world.entity.Entity;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.At;\n\n@Mixin(LevelRenderer.class)\npublic class LevelRendererMixin {\n\n\t@WrapOperation(\n\t\t\tmethod\t= \"renderLevel\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/minecraft/client/renderer/LevelRenderer;renderEntity(Lnet/minecraft/world/entity/Entity;DDDFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;)V\"\n\t\t\t)\n\t)\n\tpublic void filterEntity(\n\t\t\tLevelRenderer\t\tinstance,\n\t\t\tEntity\t\t\t\tentity,\n\t\t\tdouble\t\t\t\tcamX,\n\t\t\tdouble\t\t\t\tcamY,\n\t\t\tdouble\t\t\t\tcamZ,\n\t\t\tfloat\t\t\t\tpartialTick,\n\t\t\tPoseStack\t\t\tposeStack,\n\t\t\tMultiBufferSource\tbufferSource,\n\t\t\tOperation<Void>\t\toriginal\n\t) {\n\t\tvar pass =\t!\tFilterFeature.isEnabled\t\t\t\t()\n\t\t\t\t||\t!\tFilterFeature.shouldFilterEntities\t()\n\t\t\t\t||\t\tFilterFeature.testEntity\t\t\t(entity);\n\n\t\tif (!pass) {\n\t\t\tAcceleratedEntityRenderingFeature\t.useVanillaPipeline();\n\t\t\tAcceleratedItemRenderingFeature\t\t.useVanillaPipeline();\n\t\t\tAcceleratedTextRenderingFeature\t\t.useVanillaPipeline();\n\t\t}\n\n\t\toriginal.call(\n\t\t\t\tinstance,\n\t\t\t\tentity,\n\t\t\t\tcamX,\n\t\t\t\tcamY,\n\t\t\t\tcamZ,\n\t\t\t\tpartialTick,\n\t\t\t\tposeStack,\n\t\t\t\tbufferSource\n\t\t);\n\n\t\tif (!pass) {\n\t\t\tAcceleratedEntityRenderingFeature\t.resetPipeline();\n\t\t\tAcceleratedItemRenderingFeature\t\t.resetPipeline();\n\t\t\tAcceleratedTextRenderingFeature\t\t.resetPipeline();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/ftb/mixins/BaseScreenMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.ftb.mixins;\n\nimport com.github.argon4w.acceleratedrendering.features.items.gui.GuiBatchingController;\nimport dev.ftb.mods.ftblibrary.ui.BaseScreen;\nimport dev.ftb.mods.ftblibrary.ui.Theme;\nimport net.minecraft.client.gui.GuiGraphics;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Pseudo;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@Pseudo\n@Mixin(BaseScreen.class)\npublic class BaseScreenMixin {\n\n\t@Inject(\n\t\t\tmethod\t= \"draw\",\n\t\t\tat\t\t= {\n\t\t\t\t\t@At(\n\t\t\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\t\t\ttarget\t= \"Ldev/ftb/mods/ftblibrary/ui/Panel;draw(Lnet/minecraft/client/gui/GuiGraphics;Ldev/ftb/mods/ftblibrary/ui/Theme;IIII)V\",\n\t\t\t\t\t\t\tshift\t= At.Shift.BEFORE\n\t\t\t\t\t),\n\t\t\t\t\t@At(\n\t\t\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\t\t\ttarget\t= \"Ldev/ftb/mods/ftblibrary/ui/ModalPanel;draw(Lnet/minecraft/client/gui/GuiGraphics;Ldev/ftb/mods/ftblibrary/ui/Theme;IIII)V\",\n\t\t\t\t\t\t\tshift\t= At.Shift.BEFORE\n\t\t\t\t\t)\n\t\t\t}\n\t)\n\tpublic void startBatching(\n\t\t\tGuiGraphics\t\tgraphics,\n\t\t\tTheme\t\t\ttheme,\n\t\t\tint\t\t\t\tx,\n\t\t\tint\t\t\t\ty,\n\t\t\tint\t\t\t\tw,\n\t\t\tint\t\t\t\th,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tGuiBatchingController.INSTANCE.startBatching(graphics);\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"draw\",\n\t\t\tat\t\t= {\n\t\t\t\t\t@At(\n\t\t\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\t\t\ttarget\t= \"Ldev/ftb/mods/ftblibrary/ui/Panel;draw(Lnet/minecraft/client/gui/GuiGraphics;Ldev/ftb/mods/ftblibrary/ui/Theme;IIII)V\",\n\t\t\t\t\t\t\tshift\t= At.Shift.AFTER\n\t\t\t\t\t),\n\t\t\t\t\t@At(\n\t\t\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\t\t\ttarget\t= \"Ldev/ftb/mods/ftblibrary/ui/ModalPanel;draw(Lnet/minecraft/client/gui/GuiGraphics;Ldev/ftb/mods/ftblibrary/ui/Theme;IIII)V\",\n\t\t\t\t\t\t\tshift\t= At.Shift.AFTER\n\t\t\t\t\t)\n\t\t\t}\n\t)\n\tpublic void stopBatching(\n\t\t\tGuiGraphics\t\tgraphics,\n\t\t\tTheme\t\t\ttheme,\n\t\t\tint\t\t\t\tx,\n\t\t\tint\t\t\t\ty,\n\t\t\tint\t\t\t\tw,\n\t\t\tint\t\t\t\th,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tGuiBatchingController.INSTANCE.flushBatching(graphics);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/geckolib/mixins/GeoBoneMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.geckolib.mixins;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IBufferGraph;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.github.argon4w.acceleratedrendering.core.meshes.IMesh;\nimport com.github.argon4w.acceleratedrendering.core.meshes.collectors.CulledMeshCollector;\nimport com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData;\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;\nimport lombok.experimental.ExtensionMethod;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.joml.Vector3f;\nimport org.joml.Vector4f;\nimport org.spongepowered.asm.mixin.*;\nimport software.bernie.geckolib.cache.object.GeoBone;\nimport software.bernie.geckolib.cache.object.GeoCube;\nimport software.bernie.geckolib.util.RenderUtil;\n\nimport java.util.List;\nimport java.util.Map;\n\n@Pseudo\n@ExtensionMethod(VertexConsumerExtension.class)\n@Mixin\t\t\t(GeoBone\t\t\t\t.class)\npublic class GeoBoneMixin implements IAcceleratedRenderer<Void> {\n\n\t@Shadow @Final private\tList<GeoCube>\t\t\t\tcubes;\n\n\t@Unique private\tfinal\tMap<IBufferGraph,\tIMesh>\tmeshes = new Object2ObjectOpenHashMap<>();\n\t@Unique private final\tMap<MeshData,\t\tIMesh>\tmerges = new Object2ObjectOpenHashMap<>();\n\n\t@Override\n\tpublic void render(\n\t\t\tVertexConsumer vertexConsumer,\n\t\t\tVoid\t\t\tcontext,\n\t\t\tMatrix4f\t\ttransform,\n\t\t\tMatrix3f\t\tnormal,\n\t\t\tint\t\t\t\tlight,\n\t\t\tint\t\t\t\toverlay,\n\t\t\tint\t\t\t\tcolor\n\t) {\n\t\tvar extension\t= vertexConsumer.getAccelerated\t();\n\t\tvar mesh\t\t= meshes\t\t.get\t\t\t(extension);\n\n\t\textension.beginTransform(transform, normal);\n\n\t\tif (mesh != null) {\n\t\t\tmesh.write(\n\t\t\t\t\textension,\n\t\t\t\t\tcolor,\n\t\t\t\t\tlight,\n\t\t\t\t\toverlay\n\t\t\t);\n\n\t\t\textension.endTransform();\n\t\t\treturn;\n\t\t}\n\n\t\tvar culledMeshCollector\t= new CulledMeshCollector\t(extension);\n\t\tvar meshBuilder\t\t\t= extension.decorate\t\t(culledMeshCollector);\n\n\t\tfor (GeoCube cube : cubes) {\n\t\t\tvar poseStack = new PoseStack();\n\n\t\t\tRenderUtil.translateToPivotPoint\t\t(poseStack, cube);\n\t\t\tRenderUtil.rotateMatrixAroundCube\t\t(poseStack, cube);\n\t\t\tRenderUtil.translateAwayFromPivotPoint\t(poseStack, cube);\n\n\t\t\tvar pose\t\t\t= poseStack\t.last\t();\n\t\t\tvar cubeTransform\t= pose\t\t.pose\t();\n\t\t\tvar cubeNormal\t\t= pose\t\t.normal\t();\n\n\t\t\tfor (var quad : cube.quads()) {\n\t\t\t\tif (quad != null) {\n\t\t\t\t\tvar polygonNormal = cubeNormal.transform(new Vector3f(quad.normal()));\n\n\t\t\t\t\tfor (var vertex : quad.vertices()) {\n\t\t\t\t\t\tvar vertexPosition = cubeTransform.transform(new Vector4f(vertex.position(), 1.0f));\n\n\t\t\t\t\t\tmeshBuilder.addVertex(\n\t\t\t\t\t\t\t\tvertexPosition.x,\n\t\t\t\t\t\t\t\tvertexPosition.y,\n\t\t\t\t\t\t\t\tvertexPosition.z,\n\t\t\t\t\t\t\t\t-1,\n\t\t\t\t\t\t\t\tvertex.texU(),\n\t\t\t\t\t\t\t\tvertex.texV(),\n\t\t\t\t\t\t\t\toverlay,\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tpolygonNormal.x,\n\t\t\t\t\t\t\t\tpolygonNormal.y,\n\t\t\t\t\t\t\t\tpolygonNormal.z\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tculledMeshCollector.flush();\n\n\t\tvar data\t= culledMeshCollector\t.getData\t();\n\t\tvar buffer\t= culledMeshCollector\t.getBuffer\t();\n\t\tmesh\t\t= merges\t\t\t\t.get\t\t(data);\n\n\t\tif (mesh != null) {\n\t\t\tbuffer.discard\t();\n\t\t\tbuffer.close\t();\n\t\t} else {\n\t\t\tmesh = AcceleratedEntityRenderingFeature\n\t\t\t\t\t.getMeshType()\n\t\t\t\t\t.getBuilder\t()\n\t\t\t\t\t.build\t\t(culledMeshCollector);\n\t\t}\n\n\t\tmeshes\t.put\t(extension, mesh);\n\t\tmerges\t.put\t(data,\t\tmesh);\n\t\tmesh\t.write\t(\n\t\t\t\textension,\n\t\t\t\tcolor,\n\t\t\t\tlight,\n\t\t\t\toverlay\n\t\t);\n\n\t\textension.endTransform();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/geckolib/mixins/GeoRendererMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.geckolib.mixins;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.experimental.ExtensionMethod;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Pseudo;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\nimport software.bernie.geckolib.cache.object.GeoBone;\nimport software.bernie.geckolib.renderer.GeoRenderer;\n\n@Pseudo\n@ExtensionMethod(VertexConsumerExtension.class)\n@Mixin\t\t\t(GeoRenderer\t\t\t.class)\npublic interface GeoRendererMixin {\n\n\t@SuppressWarnings\t(\"unchecked\")\n\t@Inject\t\t\t\t(\n\t\t\tmethod\t\t= \"renderCubesOfBone\",\n\t\t\tcancellable\t= true,\n\t\t\tat\t\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lsoftware/bernie/geckolib/cache/object/GeoBone;getCubes()Ljava/util/List;\",\n\t\t\t\t\tshift\t= At.Shift.BEFORE\n\t\t\t)\n\t)\n\tdefault void renderCubesOfBoneFast(\n\t\t\tPoseStack\t\tposeStack,\n\t\t\tGeoBone\t\t\tbone,\n\t\t\tVertexConsumer\tbuffer,\n\t\t\tint\t\t\t\tpackedLight,\n\t\t\tint\t\t\t\tpackedOverlay,\n\t\t\tint\t\t\t\tcolour,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tvar extension = buffer.getAccelerated();\n\n\t\tif (\t\t\tAcceleratedEntityRenderingFeature\t.isEnabled\t\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedEntityRenderingFeature\t.shouldUseAcceleratedPipeline\t()\n\t\t\t\t&&\t(\tCoreFeature\t\t\t\t\t\t\t.isRenderingLevel\t\t\t\t()\n\t\t\t\t||\t(\tCoreFeature\t\t\t\t\t\t\t.isRenderingGui\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedEntityRenderingFeature\t.shouldAccelerateInGui\t\t\t()))\n\t\t\t\t&&\t\textension\t\t\t\t\t\t\t.isAccelerated\t\t\t\t\t()\n\t\t) {\n\t\t\tvar pose = poseStack.last();\n\n\t\t\tci\t\t\t.cancel\t\t();\n\t\t\textension\t.doRender\t(\n\t\t\t\t\t(IAcceleratedRenderer<Void>) bone,\n\t\t\t\t\tnull,\n\t\t\t\t\tpose.pose\t(),\n\t\t\t\t\tpose.normal\t(),\n\t\t\t\t\tpackedLight,\n\t\t\t\t\tpackedOverlay,\n\t\t\t\t\tcolour\n\t\t\t);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/AcceleratedItemRenderingFeature.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items;\n\nimport com.github.argon4w.acceleratedrendering.configs.FeatureConfig;\nimport com.github.argon4w.acceleratedrendering.configs.FeatureStatus;\nimport com.github.argon4w.acceleratedrendering.configs.PipelineSetting;\nimport com.github.argon4w.acceleratedrendering.core.meshes.MeshType;\n\nimport java.util.ArrayDeque;\nimport java.util.Deque;\n\npublic class AcceleratedItemRenderingFeature {\n\n\tprivate\tstatic final Deque<PipelineSetting>\tPIPELINE_CONTROLLER_STACK\t\t\t= new ArrayDeque<>();\n\tprivate\tstatic final Deque<FeatureStatus>\tBAKE_QUAD_MESH_CONTROLLER_STACK\t\t= new ArrayDeque<>();\n\tprivate\tstatic final Deque<FeatureStatus>\tHAND_ACCELERATION_CONTROLLER_STACK\t= new ArrayDeque<>();\n\tprivate\tstatic final Deque<FeatureStatus>\tGUI_ACCELERATION_CONTROLLER_STACK\t= new ArrayDeque<>();\n\n\tpublic static boolean isEnabled() {\n\t\treturn FeatureConfig.CONFIG.acceleratedItemRenderingFeatureStatus.get() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean shouldUseAcceleratedPipeline() {\n\t\treturn getPipelineSetting() == PipelineSetting.ACCELERATED;\n\t}\n\n\tpublic static boolean shouldBakeMeshForQuad() {\n\t\treturn getBakeQuadMeshSetting() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean shouldAccelerateInHand() {\n\t\treturn getHandAccelerationSetting() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean shouldAccelerateInGui() {\n\t\treturn getGUIAccelerationSetting() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean shouldUseGuiItemBatching() {\n\t\treturn FeatureConfig.CONFIG.acceleratedItemRenderingGuiItemBatching.get() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean shouldMergeGuiItemBatches() {\n\t\treturn FeatureConfig.CONFIG.acceleratedItemRenderingMergeGuiItemBatches.get() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static MeshType getMeshType() {\n\t\treturn FeatureConfig.CONFIG.acceleratedItemRenderingMeshType.get();\n\t}\n\n\tpublic static void useVanillaPipeline() {\n\t\tPIPELINE_CONTROLLER_STACK.push(PipelineSetting.VANILLA);\n\t}\n\n\tpublic static void dontBakeMeshForQuad() {\n\t\tBAKE_QUAD_MESH_CONTROLLER_STACK.push(FeatureStatus.DISABLED);\n\t}\n\n\tpublic static void dontAccelerateInHand() {\n\t\tHAND_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.DISABLED);\n\t}\n\n\tpublic static void dontAccelerateInGui() {\n\t\tGUI_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.DISABLED);\n\t}\n\n\tpublic static void forceUseAcceleratedPipeline() {\n\t\tPIPELINE_CONTROLLER_STACK.push(PipelineSetting.ACCELERATED);\n\t}\n\n\tpublic static void forceBakeMeshForQuad() {\n\t\tBAKE_QUAD_MESH_CONTROLLER_STACK.push(FeatureStatus.ENABLED);\n\t}\n\n\tpublic static void forceAccelerateInHand() {\n\t\tHAND_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.ENABLED);\n\t}\n\n\tpublic static void forceAccelerateInGui() {\n\t\tGUI_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.ENABLED);\n\t}\n\n\tpublic static void forceSetPipeline(PipelineSetting pipeline) {\n\t\tPIPELINE_CONTROLLER_STACK.push(pipeline);\n\t}\n\n\tpublic static void forceSetBakeQuadForMesh(FeatureStatus status) {\n\t\tBAKE_QUAD_MESH_CONTROLLER_STACK.push(status);\n\t}\n\n\tpublic static void forceSetHandAcceleration(FeatureStatus status) {\n\t\tHAND_ACCELERATION_CONTROLLER_STACK.push(status);\n\t}\n\n\tpublic static void forceSetGUIAcceleration(FeatureStatus status) {\n\t\tGUI_ACCELERATION_CONTROLLER_STACK.push(status);\n\t}\n\n\tpublic static void resetPipeline() {\n\t\tPIPELINE_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static void resetBakeQuadForMesh() {\n\t\tBAKE_QUAD_MESH_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static void resetHandAcceleration() {\n\t\tHAND_ACCELERATION_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static void resetGuiAcceleration() {\n\t\tGUI_ACCELERATION_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static PipelineSetting getPipelineSetting() {\n\t\treturn PIPELINE_CONTROLLER_STACK.isEmpty() ? getDefaultPipelineSetting() : PIPELINE_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static FeatureStatus getBakeQuadMeshSetting() {\n\t\treturn BAKE_QUAD_MESH_CONTROLLER_STACK.isEmpty() ? getDefaultBakeQuadMeshSetting() : BAKE_QUAD_MESH_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static FeatureStatus getHandAccelerationSetting() {\n\t\treturn HAND_ACCELERATION_CONTROLLER_STACK.isEmpty() ? getDefaultHandAccelerationSetting() : HAND_ACCELERATION_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static FeatureStatus getGUIAccelerationSetting() {\n\t\treturn GUI_ACCELERATION_CONTROLLER_STACK.isEmpty() ? getDefaultGUIAccelerationSetting() : GUI_ACCELERATION_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static PipelineSetting getDefaultPipelineSetting() {\n\t\treturn FeatureConfig.CONFIG.acceleratedItemRenderingDefaultPipeline.get();\n\t}\n\n\tpublic static FeatureStatus getDefaultBakeQuadMeshSetting() {\n\t\treturn FeatureConfig.CONFIG.acceleratedItemRenderingBakeMeshForQuads.get();\n\t}\n\n\tpublic static FeatureStatus getDefaultHandAccelerationSetting() {\n\t\treturn FeatureConfig.CONFIG.acceleratedItemRenderingHandAcceleration.get();\n\t}\n\n\tpublic static FeatureStatus getDefaultGUIAccelerationSetting() {\n\t\treturn FeatureConfig.CONFIG.acceleratedItemRenderingGuiAcceleration.get();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/AcceleratedQuadsRenderer.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.github.argon4w.acceleratedrendering.features.items.contexts.AcceleratedQuadsRenderContext;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.experimental.ExtensionMethod;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\n@ExtensionMethod({\n\t\tVertexConsumerExtension\t.class,\n\t\tBakedModelExtension\t\t.class\n})\npublic class AcceleratedQuadsRenderer implements IAcceleratedRenderer<AcceleratedQuadsRenderContext> {\n\n\tpublic static final AcceleratedQuadsRenderer INSTANCE = new AcceleratedQuadsRenderer();\n\n\t@Override\n\tpublic void render(\n\t\t\tVertexConsumer\t\t\t\t\tvertexConsumer,\n\t\t\tAcceleratedQuadsRenderContext\tcontext,\n\t\t\tMatrix4f\t\t\t\t\t\ttransform,\n\t\t\tMatrix3f\t\t\t\t\t\tnormal,\n\t\t\tint\t\t\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\t\t\t\tcolor\n\t) {\n\t\tvar extension\t= vertexConsumer.getAccelerated\t();\n\t\tvar quads\t\t= context\t\t.quads\t\t\t();\n\t\tvar colors\t\t= context\t\t.colors\t\t\t();\n\n\t\textension.beginTransform(transform, normal);\n\n\t\tfor (var quad : quads) {\n\t\t\tquad\n\t\t\t\t\t.getAccelerated\t()\n\t\t\t\t\t.renderFast\t\t(\n\t\t\t\t\t\t\ttransform,\n\t\t\t\t\t\t\tnormal,\n\t\t\t\t\t\t\textension,\n\t\t\t\t\t\t\tlight,\n\t\t\t\t\t\t\toverlay,\n\t\t\t\t\t\t\tcolors.getColor(quad.getTintIndex())\n\t\t\t\t\t);\n\t\t}\n\n\t\textension.endTransform();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/BakedModelExtension.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items;\n\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.minecraft.client.resources.model.BakedModel;\n\npublic class BakedModelExtension {\n\n\tpublic static IAcceleratedBakedModel getAccelerated(BakedModel in) {\n\t\treturn (IAcceleratedBakedModel) in;\n\t}\n\n\tpublic static IAcceleratedBakedQuad getAccelerated(BakedQuad in) {\n\t\treturn (IAcceleratedBakedQuad) in;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/IAcceleratedBakedModel.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.util.RandomSource;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.data.ModelData;\n\npublic interface IAcceleratedBakedModel {\n\n\tvoid\trenderItemFast\t\t(ItemStack\titemStack,\tRandomSource\trandom, PoseStack.Pose pose, IAcceleratedVertexConsumer extension, int light, int overlay);\n\tvoid\trenderBlockFast\t\t(BlockState\tblockState, RandomSource\trandom, PoseStack.Pose pose, IAcceleratedVertexConsumer extension, int light, int overlay, int color, ModelData data, RenderType renderType);\n\tint\t\tgetCustomColor \t\t(int\t\tlayer,\t\tint\t\t\t\tcolor);\n\tboolean\tisAccelerated\t\t();\n\tboolean\tisAcceleratedInHand\t();\n\tboolean isAcceleratedInGui\t();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/IAcceleratedBakedQuad.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\npublic interface IAcceleratedBakedQuad {\n\n\tvoid\trenderFast\t\t(Matrix4f\ttransform, Matrix3f normal, IAcceleratedVertexConsumer extension, int combinedLight, int combinedOverlay, int color);\n\tint\t\tgetCustomColor\t(int\t\tcolor);\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/colors/BlockLayerColors.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.colors;\n\nimport com.github.argon4w.acceleratedrendering.features.items.mixins.accessors.BlockColorsAccessor;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.color.block.BlockColor;\nimport net.minecraft.world.level.block.state.BlockState;\n\npublic class BlockLayerColors implements ILayerColors {\n\n\tprivate final BlockState blockState;\n\tprivate final BlockColor blockColor;\n\n\tpublic BlockLayerColors(BlockState blockState) {\n\t\tthis.blockState = blockState;\n\t\tthis.blockColor = ((BlockColorsAccessor) Minecraft.getInstance().getBlockColors()).getBlockColors().getOrDefault(this.blockState.getBlock(), EmptyBlockColor.INSTANCE);\n\t}\n\n\t@Override\n\tpublic int getColor(int layer) {\n\t\treturn layer == -1 ? -1 : blockColor.getColor(\n\t\t\t\tblockState,\n\t\t\t\tnull,\n\t\t\t\tnull,\n\t\t\t\tlayer\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/colors/EmptyBlockColor.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.colors;\n\nimport net.minecraft.client.color.block.BlockColor;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.world.level.BlockAndTintGetter;\nimport net.minecraft.world.level.block.state.BlockState;\n\npublic class EmptyBlockColor implements BlockColor {\n\n\tpublic static final BlockColor INSTANCE = new EmptyBlockColor();\n\n\t@Override\n\tpublic int getColor(\n\t\t\tBlockState\t\t\tstate,\n\t\t\tBlockAndTintGetter\tlevel,\n\t\t\tBlockPos\t\t\tpos,\n\t\t\tint\t\t\t\t\ttintIndex\n\t) {\n\t\treturn -1;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/colors/EmptyItemColor.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.colors;\n\nimport net.minecraft.client.color.item.ItemColor;\nimport net.minecraft.world.item.ItemStack;\n\npublic class EmptyItemColor implements ItemColor {\n\n\tpublic static final ItemColor INSTANCE = new EmptyItemColor();\n\n\t@Override\n\tpublic int getColor(ItemStack pStack, int pTintIndex) {\n\t\treturn -1;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/colors/FixedColors.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.colors;\n\npublic record FixedColors(int color) implements ILayerColors {\n\n\t@Override\n\tpublic int getColor(int layer) {\n\t\treturn color;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/colors/ILayerColors.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.colors;\n\npublic interface ILayerColors {\n\n\tint getColor(int layer);\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/colors/ItemLayerColors.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.colors;\n\nimport com.github.argon4w.acceleratedrendering.features.items.mixins.accessors.ItemColorsAccessor;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.color.item.ItemColor;\nimport net.minecraft.world.item.ItemStack;\n\npublic class ItemLayerColors implements ILayerColors {\n\n\tprivate final ItemStack itemStack;\n\tprivate final ItemColor itemColor;\n\n\tpublic ItemLayerColors(ItemStack itemStack) {\n\t\tthis.itemStack = itemStack;\n\t\tthis.itemColor = ((ItemColorsAccessor) Minecraft.getInstance().getItemColors()).getItemColors().getOrDefault(this.itemStack.getItem(), EmptyItemColor.INSTANCE);\n\t}\n\n\t@Override\n\tpublic int getColor(int layer) {\n\t\treturn layer == -1 ? -1 : itemColor.getColor(itemStack, layer);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/contexts/AcceleratedModelRenderContext.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.contexts;\n\nimport com.github.argon4w.acceleratedrendering.features.items.colors.ILayerColors;\nimport net.minecraft.util.RandomSource;\n\npublic record AcceleratedModelRenderContext(RandomSource randomSource, ILayerColors layerColors) {\n\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/contexts/AcceleratedQuadsRenderContext.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.contexts;\n\nimport com.github.argon4w.acceleratedrendering.features.items.colors.ILayerColors;\nimport net.minecraft.client.renderer.block.model.BakedQuad;\n\nimport java.util.List;\n\npublic record AcceleratedQuadsRenderContext(List<BakedQuad> quads, ILayerColors colors) {\n\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/contexts/DecorationRenderContext.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.contexts;\n\nimport net.minecraft.world.item.ItemStack;\n\npublic record DecorationRenderContext(\n\t\tItemStack\titemStack,\n\t\tString\t\tcountString,\n\t\tint\t\t\tslotX,\n\t\tint\t\t\tslotY\n) {\n\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/GuiBatchingController.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.gui;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreBuffers;\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.CoreStates;\nimport com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.BufferSourceExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType;\nimport com.github.argon4w.acceleratedrendering.core.utils.PoseStackExtension;\nimport com.github.argon4w.acceleratedrendering.core.utils.RenderTypeUtils;\nimport com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.items.gui.contexts.*;\nimport com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string.IStringDrawContext;\nimport com.github.argon4w.acceleratedrendering.features.items.gui.renderer.AcceleratedBlitRenderer;\nimport com.github.argon4w.acceleratedrendering.features.items.gui.renderer.AcceleratedFillRenderer;\nimport com.github.argon4w.acceleratedrendering.features.items.gui.renderer.AcceleratedGradientRenderer;\nimport com.mojang.blaze3d.platform.Lighting;\nimport it.unimi.dsi.fastutil.floats.Float2ReferenceAVLTreeMap;\nimport it.unimi.dsi.fastutil.floats.Float2ReferenceSortedMap;\nimport it.unimi.dsi.fastutil.objects.ReferenceArrayList;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.Font;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemDisplayContext;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.client.ItemDecoratorHandler;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\nimport java.util.List;\n\n\n@ExtensionMethod({\n\t\tVertexConsumerExtension\t.class,\n\t\tBufferSourceExtension\t.class,\n\t\tPoseStackExtension\t\t.class,\n})\npublic class GuiBatchingController {\n\n\tpublic static\tfinal\tGuiBatchingController\t\t\t\t\t\t\t\tINSTANCE = new GuiBatchingController();\n\n\tprivate\t\t\tfinal\tIBindingState\t\t\t\t\t\t\t\t\t\tscissorDraw;\n\tprivate\t\t\tfinal\tIBindingState\t\t\t\t\t\t\t\t\t\tscissorFlush;\n\tprivate\t\t\tfinal\tList<BlitDrawContext>\t\t\t\t\t\t\t\tblitDrawContexts;\n\tprivate\t\t\tfinal\tList<IStringDrawContext>\t\t\t\t\t\t\tstringDrawContexts;\n\tprivate\t\t\tfinal\tList<DecoratorDrawContext>\t\t\t\t\t\t\tdecoratorDrawContexts;\n\tprivate\t\t\tfinal\tList<FillDrawContext>\t\t\t\t\t\t\t\tfillDrawContexts;\n\tprivate\t\t\tfinal\tList<HighlightDrawContext>\t\t\t\t\t\t\thighlightDrawContexts;\n\tprivate\t\t\tfinal\tList<GradientDrawContext>\t\t\t\t\t\t\tgradientDrawContexts;\n\tprivate\t\t\tfinal\tList<ItemRenderContext>\t\t\t\t\t\t\t\tflatItemDrawContexts;\n\tprivate\t\t\tfinal\tList<ItemRenderContext>\t\t\t\t\t\t\t\tblockItemDrawContexts;\n\tprivate\t\t\tfinal\tFloat2ReferenceSortedMap<List<IGuiElementContext>>\tdepthLayers;\n\n\tprivate GuiBatchingController() {\n\t\tthis.scissorDraw\t\t\t= CoreFeature.createScissorState\t();\n\t\tthis.scissorFlush\t\t\t= CoreFeature.createScissorState\t();\n\t\tthis.blitDrawContexts\t\t= new ReferenceArrayList\t\t<>\t();\n\t\tthis.stringDrawContexts\t\t= new ReferenceArrayList\t\t<>\t();\n\t\tthis.decoratorDrawContexts\t= new ReferenceArrayList\t\t<>\t();\n\t\tthis.fillDrawContexts\t\t= new ReferenceArrayList\t\t<>\t();\n\t\tthis.highlightDrawContexts\t= new ReferenceArrayList\t\t<>\t();\n\t\tthis.gradientDrawContexts\t= new ReferenceArrayList\t\t<>\t();\n\t\tthis.flatItemDrawContexts\t= new ReferenceArrayList\t\t<>\t();\n\t\tthis.blockItemDrawContexts\t= new ReferenceArrayList\t\t<>\t();\n\t\tthis.depthLayers\t\t\t= new Float2ReferenceAVLTreeMap\t<>\t();\n\t}\n\n\tpublic void startBatching(GuiGraphics graphics) {\n\t\tif (\t\tgraphics.bufferSource().getAcceleratable()\t.isBufferSourceAcceleratable\t()\n\t\t\t\t&&\tAcceleratedItemRenderingFeature\t\t\t\t.isEnabled\t\t\t\t\t\t()\n\t\t\t\t&&\tAcceleratedItemRenderingFeature\t\t\t\t.shouldUseAcceleratedPipeline\t()\n\t\t\t\t&&\tAcceleratedItemRenderingFeature\t\t\t\t.shouldAccelerateInGui\t\t\t()\n\t\t\t\t&&\tAcceleratedItemRenderingFeature\t\t\t\t.shouldUseGuiItemBatching\t\t()\n\t\t\t\t&&\tCoreFeature\t\t\t\t\t\t\t\t\t.isLoaded\t\t\t\t\t\t()\n\t\t) {\n\t\t\tCoreFeature.setGuiBatching\t();\n\t\t\tscissorDraw.record\t\t\t(graphics);\n\t\t}\n\t}\n\n\t@SuppressWarnings(\"UnstableApiUsage\")\n\tpublic void flushBatching(GuiGraphics graphics) {\n\t\tif (CoreFeature.isGuiBatching()) {\n\t\t\tvar itemRenderer\t= Minecraft.getInstance()\t.getItemRenderer();\n\t\t\tvar bufferSource\t= graphics\t\t\t\t\t.bufferSource\t();\n\t\t\tvar poseStack\t\t= graphics\t\t\t\t\t.pose\t\t\t();\n\n\t\t\tCoreFeature.resetGuiBatching();\n\t\t\tCoreFeature.setRenderingGui\t();\n\n\t\t\tfor (float layer : depthLayers.keySet()) {\n\t\t\t\tvar nextLayer\t= depthLayers.tailMap\t(layer);\n\t\t\t\tvar elements\t= depthLayers.get\t\t(layer);\n\t\t\t\tvar depth\t\t= 0.0f;\n\t\t\t\tvar step\t\t= 0.1f;\n\n\t\t\t\tif (!nextLayer.isEmpty()) {\n\t\t\t\t\tstep = 1.0f / nextLayer.firstEntry().getValue().size();\n\t\t\t\t}\n\n\t\t\t\tfor (var element : elements) {\n\t\t\t\t\telement.transform().translateLocal(\n\t\t\t\t\t\t\t0.0f,\n\t\t\t\t\t\t\t0.0f,\n\t\t\t\t\t\t\tdepth\n\t\t\t\t\t);\n\n\t\t\t\t\tdepth += step;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (float layer : depthLayers.keySet()) {\n\t\t\t\tvar elements = depthLayers.get(layer);\n\n\t\t\t\tif (elements.isEmpty()) {\n\t\t\t\t\tdepthLayers.remove(layer);\n\t\t\t\t} else {\n\t\t\t\t\telements.clear();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (var context : blitDrawContexts) {\n\t\t\t\tvar extension = graphics.bufferSource().getBuffer(GuiRenderTypes.blit(context.atlasLocation())).getAccelerated();\n\n\t\t\t\tif (extension.isAccelerated()) {\n\t\t\t\t\textension.doRender(\n\t\t\t\t\t\t\tAcceleratedBlitRenderer.INSTANCE,\n\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\tcontext.transform\t(),\n\t\t\t\t\t\t\tcontext.normal\t\t(),\n\t\t\t\t\t\t\tcontext.blitLight\t(),\n\t\t\t\t\t\t\tcontext.blitOverlay\t(),\n\t\t\t\t\t\t\tcontext.blitColor\t()\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (var context : fillDrawContexts) {\n\t\t\t\tvar extension = graphics.bufferSource().getBuffer(context.renderType()).getAccelerated();\n\n\t\t\t\tif (extension.isAccelerated()) {\n\t\t\t\t\textension.doRender(\n\t\t\t\t\t\t\tAcceleratedFillRenderer.INSTANCE,\n\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\tcontext.transform\t(),\n\t\t\t\t\t\t\tcontext.normal\t\t(),\n\t\t\t\t\t\t\tcontext.light\t\t(),\n\t\t\t\t\t\t\tcontext.overlay\t\t(),\n\t\t\t\t\t\t\tcontext.color\t\t()\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (var context : gradientDrawContexts) {\n\t\t\t\tvar extension = graphics.bufferSource().getBuffer(context.renderType()).getAccelerated();\n\n\t\t\t\tif (extension.isAccelerated()) {\n\t\t\t\t\textension.doRender(\n\t\t\t\t\t\t\tAcceleratedGradientRenderer.INSTANCE,\n\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\tcontext.transform\t(),\n\t\t\t\t\t\t\tcontext.normal\t\t(),\n\t\t\t\t\t\t\tcontext.light\t\t(),\n\t\t\t\t\t\t\tcontext.overlay\t\t(),\n\t\t\t\t\t\t\t-1\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (var context : stringDrawContexts) {\n\t\t\t\tcontext.drawString(graphics.bufferSource());\n\t\t\t}\n\n\t\t\tscissorFlush.record\t(graphics);\n\t\t\tscissorDraw\t.restore();\n\n\t\t\tCoreFeature.forceSetDefaultLayer\t\t\t\t(1);\n\t\t\tCoreFeature.forceSetDefaultLayerBeforeFunction\t(Lighting::setupForFlatItems);\n\t\t\tCoreFeature.forceSetDefaultLayerAfterFunction\t(Lighting::setupFor3DItems);\n\n\t\t\tfor (var context : flatItemDrawContexts) {\n\t\t\t\tposeStack.pushPose\t();\n\t\t\t\tposeStack.setPose\t(context.transform(), context.normal());\n\n\t\t\t\titemRenderer.render(\n\t\t\t\t\t\tcontext.itemStack\t\t(),\n\t\t\t\t\t\tcontext.displayContext\t(),\n\t\t\t\t\t\tcontext.leftHand\t\t(),\n\t\t\t\t\t\tposeStack,\n\t\t\t\t\t\tbufferSource,\n\t\t\t\t\t\tcontext.combinedLight\t(),\n\t\t\t\t\t\tcontext.combinedOverlay\t(),\n\t\t\t\t\t\tcontext.bakedModel\t\t()\n\t\t\t\t);\n\n\t\t\t\tposeStack.popPose();\n\t\t\t}\n\n\t\t\tCoreFeature.resetDefaultLayer\t\t\t\t();\n\t\t\tCoreFeature.resetDefaultLayerBeforeFunction\t();\n\t\t\tCoreFeature.resetDefaultLayerAfterFunction\t();\n\n\t\t\tfor (var context : blockItemDrawContexts) {\n\t\t\t\tposeStack.pushPose\t();\n\t\t\t\tposeStack.setPose\t(context.transform(), context.normal());\n\n\t\t\t\titemRenderer.render(\n\t\t\t\t\t\tcontext.itemStack\t\t(),\n\t\t\t\t\t\tcontext.displayContext\t(),\n\t\t\t\t\t\tcontext.leftHand\t\t(),\n\t\t\t\t\t\tposeStack,\n\t\t\t\t\t\tbufferSource,\n\t\t\t\t\t\tcontext.combinedLight\t(),\n\t\t\t\t\t\tcontext.combinedOverlay\t(),\n\t\t\t\t\t\tcontext.bakedModel\t\t()\n\t\t\t\t);\n\n\t\t\t\tposeStack.popPose();\n\t\t\t}\n\n\t\t\tCoreFeature.resetRenderingGui\t();\n\t\t\tflushBatching\t\t\t\t\t();\n\n\t\t\tfor (var context : decoratorDrawContexts) {\n\t\t\t\tposeStack.pushPose\t();\n\t\t\t\tposeStack.setPose\t(context.transform(), context.normal());\n\n\t\t\t\tcontext.handler().render(\n\t\t\t\t\t\tgraphics,\n\t\t\t\t\t\tcontext.font\t(),\n\t\t\t\t\t\tcontext.stack\t(),\n\t\t\t\t\t\tcontext.xOffset\t(),\n\t\t\t\t\t\tcontext.yOffset\t()\n\t\t\t\t);\n\n\t\t\t\tgraphics.pose().popPose();\n\t\t\t}\n\n\t\t\tfor (var context : highlightDrawContexts) {\n\t\t\t\tposeStack.pushPose\t();\n\t\t\t\tposeStack.last\t\t().pose\t\t().set(context.transform());\n\t\t\t\tposeStack.last\t\t().normal\t().set(context.normal\t());\n\n\t\t\t\tAbstractContainerScreen.renderSlotHighlight(\n\t\t\t\t\t\tgraphics,\n\t\t\t\t\t\tcontext.highlightX\t(),\n\t\t\t\t\t\tcontext.highlightY\t(),\n\t\t\t\t\t\tcontext.blitOffset\t(),\n\t\t\t\t\t\tcontext.color\t\t()\n\t\t\t\t);\n\n\t\t\t\tgraphics.pose().popPose();\n\t\t\t}\n\n\t\t\tblitDrawContexts\t\t.clear\t();\n\t\t\tstringDrawContexts\t\t.clear\t();\n\t\t\tdecoratorDrawContexts\t.clear\t();\n\t\t\tfillDrawContexts\t\t.clear\t();\n\t\t\thighlightDrawContexts\t.clear\t();\n\t\t\tgradientDrawContexts\t.clear\t();\n\t\t\tflatItemDrawContexts\t.clear\t();\n\t\t\tblockItemDrawContexts\t.clear\t();\n\t\t\tscissorFlush\t\t\t.restore();\n\t\t}\n\t}\n\n\tpublic void flushBatching() {\n\t\tCoreStates\t\t\t\t\t\t.recordBuffers\t();\n\t\tCoreBuffers.ENTITY\t\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.BLOCK\t\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS\t\t\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS_COLOR\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS_TEX\t\t\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS_TEX_COLOR\t\t.prepareBuffers\t();\n\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.prepareBuffers\t();\n\t\tCoreStates\t\t\t\t\t\t.restoreBuffers\t();\n\n\t\tCoreBuffers.ENTITY\t\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tCoreBuffers.BLOCK\t\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS\t\t\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS_COLOR\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS_TEX\t\t\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS_TEX_COLOR\t\t.drawBuffers\t(LayerDrawType.ALL);\n\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.drawBuffers\t(LayerDrawType.ALL);\n\n\t\tCoreBuffers.ENTITY\t\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.BLOCK\t\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS\t\t\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS_COLOR\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS_TEX\t\t\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS_TEX_COLOR\t\t.clearBuffers\t();\n\t\tCoreBuffers.POS_COLOR_TEX_LIGHT\t.clearBuffers\t();\n\t}\n\n\tpublic void submitBlit(\n\t\t\tMatrix4f\t\t\ttransform,\n\t\t\tMatrix3f\t\t\tnormal,\n\t\t\tResourceLocation\tatlasLocation,\n\t\t\tint\t\t\t\t\tminX,\n\t\t\tint\t\t\t\t\tmaxX,\n\t\t\tint\t\t\t\t\tminY,\n\t\t\tint\t\t\t\t\tmaxY,\n\t\t\tint\t\t\t\t\tblitOffset,\n\t\t\tint\t\t\t\t\tblitColor,\n\t\t\tfloat\t\t\t\tminU,\n\t\t\tfloat\t\t\t\tmaxU,\n\t\t\tfloat\t\t\t\tminV,\n\t\t\tfloat\t\t\t\tmaxV\n\t) {\n\t\tvar layer = getLayer(getGlobalDepth(\n\t\t\t\ttransform.m22(),\n\t\t\t\ttransform.m32(),\n\t\t\t\tblitOffset\n\t\t));\n\n\t\tvar context = new BlitDrawContext(\n\t\t\t\tnew Matrix4f(transform),\n\t\t\t\tnew Matrix3f(normal),\n\t\t\t\tatlasLocation,\n\t\t\t\tminX,\n\t\t\t\tmaxX,\n\t\t\t\tminY,\n\t\t\t\tmaxY,\n\t\t\t\tblitOffset,\n\t\t\t\tblitColor,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tminU,\n\t\t\t\tmaxU,\n\t\t\t\tminV,\n\t\t\t\tmaxV\n\t\t);\n\n\t\tblitDrawContexts.add(context);\n\t\tlayer\t\t\t.add(context);\n\t}\n\n\tpublic void submitItem(\n\t\t\tMatrix4f\t\t\ttransform,\n\t\t\tMatrix3f\t\t\tnormal,\n\t\t\tItemStack\t\t\titemStack,\n\t\t\tItemDisplayContext\tdisplayContext,\n\t\t\tboolean\t\t\t\tleftHand,\n\t\t\tint\t\t\t\t\tcombinedLight,\n\t\t\tint\t\t\t\t\tcombinedOverlay,\n\t\t\tBakedModel\t\t\tbakedModel,\n\t\t\tboolean\t\t\t\tblockLight\n\t) {\n\t\tvar layer = getLayer(getGlobalDepth(\n\t\t\t\ttransform.m22(),\n\t\t\t\ttransform.m32(),\n\t\t\t\t0.0f\n\t\t));\n\n\t\tvar context = new ItemRenderContext(\n\t\t\t\tnew Matrix4f(transform),\n\t\t\t\tnew Matrix3f(normal),\n\t\t\t\titemStack,\n\t\t\t\tdisplayContext,\n\t\t\t\tleftHand,\n\t\t\t\tcombinedLight,\n\t\t\t\tcombinedOverlay,\n\t\t\t\tbakedModel\n\t\t);\n\n\t\tvar contexts = blockLight ? blockItemDrawContexts : flatItemDrawContexts;\n\n\t\tcontexts.add(context);\n\t\tlayer\t.add(context);\n\t}\n\n\tpublic void submitFill(\n\t\t\tMatrix4f\ttransform,\n\t\t\tMatrix3f\tnormal,\n\t\t\tRenderType\trenderType,\n\t\t\tint\t\t\tminX,\n\t\t\tint\t\t\tminY,\n\t\t\tint\t\t\tmaxX,\n\t\t\tint\t\t\tmaxY,\n\t\t\tint\t\t\tblitOffset,\n\t\t\tint\t\t\tcolor\n\t) {\n\t\tif (RenderTypeUtils.hasDepth(renderType)) {\n\t\t\tvar layer = getLayer(getGlobalDepth(\n\t\t\t\t\ttransform.m22(),\n\t\t\t\t\ttransform.m32(),\n\t\t\t\t\tblitOffset\n\t\t\t));\n\n\t\t\tvar context = new FillDrawContext(\n\t\t\t\t\tnew Matrix4f(transform),\n\t\t\t\t\tnew Matrix3f(normal),\n\t\t\t\t\trenderType,\n\t\t\t\t\tminX,\n\t\t\t\t\tminY,\n\t\t\t\t\tmaxX,\n\t\t\t\t\tmaxY,\n\t\t\t\t\tblitOffset,\n\t\t\t\t\tcolor,\n\t\t\t\t\t0,\n\t\t\t\t\t0\n\t\t\t);\n\n\t\t\tfillDrawContexts.add(context);\n\t\t\tlayer\t\t\t.add(context);\n\t\t} else {\n\t\t\tvar depth = depthLayers.lastFloatKey();\n\t\t\tvar layer = depthLayers.get\t\t\t(depth);\n\n\t\t\tvar context = new FillDrawContext(\n\t\t\t\t\tnew Matrix4f\t\t\t\t(transform).translate(0.0f, 0.0f, depth),\n\t\t\t\t\tnew Matrix3f\t\t\t\t(normal),\n\t\t\t\t\tRenderTypeUtils.withDepth\t(renderType),\n\t\t\t\t\tminX,\n\t\t\t\t\tminY,\n\t\t\t\t\tmaxX,\n\t\t\t\t\tmaxY,\n\t\t\t\t\t0,\n\t\t\t\t\tcolor,\n\t\t\t\t\t0,\n\t\t\t\t\t0\n\t\t\t);\n\n\t\t\tfillDrawContexts.add(context);\n\t\t\tlayer\t\t\t.add(context);\n\t\t}\n\t}\n\n\tpublic void submitGradient(\n\t\t\tMatrix4f\ttransform,\n\t\t\tMatrix3f\tnormal,\n\t\t\tRenderType\trenderType,\n\t\t\tint\t\t\tminX,\n\t\t\tint\t\t\tminY,\n\t\t\tint\t\t\tmaxX,\n\t\t\tint\t\t\tmaxY,\n\t\t\tint\t\t\tblitOffset,\n\t\t\tint\t\t\tcolorFrom,\n\t\t\tint\t\t\tcolorTo\n\t) {\n\t\tif (RenderTypeUtils.hasDepth(renderType)) {\n\t\t\tvar layer = getLayer(getGlobalDepth(\n\t\t\t\t\ttransform.m22(),\n\t\t\t\t\ttransform.m32(),\n\t\t\t\t\tblitOffset\n\t\t\t));\n\n\t\t\tvar context = new GradientDrawContext(\n\t\t\t\t\tnew Matrix4f(transform),\n\t\t\t\t\tnew Matrix3f(normal),\n\t\t\t\t\trenderType,\n\t\t\t\t\tminX,\n\t\t\t\t\tminY,\n\t\t\t\t\tmaxX,\n\t\t\t\t\tmaxY,\n\t\t\t\t\tblitOffset,\n\t\t\t\t\tcolorFrom,\n\t\t\t\t\tcolorTo,\n\t\t\t\t\t0,\n\t\t\t\t\t0\n\t\t\t);\n\n\t\t\tgradientDrawContexts.add(context);\n\t\t\tlayer\t\t\t\t.add(context);\n\t\t} else {\n\t\t\tvar depth = depthLayers.lastFloatKey();\n\t\t\tvar layer = depthLayers.get\t\t\t(depth);\n\n\t\t\tvar context = new GradientDrawContext(\n\t\t\t\t\tnew Matrix4f\t\t\t\t(transform).translate(0.0f, 0.0f, depth),\n\t\t\t\t\tnew Matrix3f\t\t\t\t(normal),\n\t\t\t\t\tRenderTypeUtils.withDepth\t(renderType),\n\t\t\t\t\tminX,\n\t\t\t\t\tminY,\n\t\t\t\t\tmaxX,\n\t\t\t\t\tmaxY,\n\t\t\t\t\t0,\n\t\t\t\t\tcolorFrom,\n\t\t\t\t\tcolorTo,\n\t\t\t\t\t0,\n\t\t\t\t\t0\n\t\t\t);\n\n\t\t\tgradientDrawContexts.add(context);\n\t\t\tlayer\t\t\t\t.add(context);\n\t\t}\n\t}\n\n\t@SuppressWarnings(\"UnstableApiUsage\")\n\tpublic void submitCustomDecorator(\n\t\t\tMatrix4f\t\t\t\ttransform,\n\t\t\tMatrix3f\t\t\t\tnormal,\n\t\t\tItemDecoratorHandler\thandler,\n\t\t\tFont\t\t\t\t\tfont,\n\t\t\tItemStack\t\t\t\titemStack,\n\t\t\tint\t\t\t\t\t\txOffset,\n\t\t\tint\t\t\t\t\t\tyOffset\n\t) {\n\t\tvar layer = getLayer(getGlobalDepth(\n\t\t\t\ttransform.m22(),\n\t\t\t\ttransform.m32(),\n\t\t\t\t100.0f\n\t\t));\n\n\t\tvar context = new DecoratorDrawContext(\n\t\t\t\tnew Matrix4f(transform),\n\t\t\t\tnew Matrix3f(normal),\n\t\t\t\thandler,\n\t\t\t\tfont,\n\t\t\t\titemStack,\n\t\t\t\txOffset,\n\t\t\t\tyOffset\n\t\t);\n\n\t\tdecoratorDrawContexts\t.add(context);\n\t\tlayer\t\t\t\t\t.add(context);\n\t}\n\n\tpublic void submitHighlight(\n\t\t\tMatrix4f\ttransform,\n\t\t\tMatrix3f\tnormal,\n\t\t\tint\t\t\thighlightX,\n\t\t\tint\t\t\thighlightY,\n\t\t\tint\t\t\tblitOffset,\n\t\t\tint\t\t\tcolor\n\t) {\n\t\tvar layer = getLayer(getGlobalDepth(\n\t\t\t\ttransform.m22(),\n\t\t\t\ttransform.m32(),\n\t\t\t\tblitOffset\n\t\t));\n\n\t\tvar context = new HighlightDrawContext(\n\t\t\t\tnew Matrix4f(transform),\n\t\t\t\tnew Matrix3f(normal),\n\t\t\t\thighlightX,\n\t\t\t\thighlightY,\n\t\t\t\tblitOffset,\n\t\t\t\tcolor\n\t\t);\n\n\t\thighlightDrawContexts\t.add(context);\n\t\tlayer\t\t\t\t\t.add(context);\n\t}\n\n\tpublic void submitString(IStringDrawContext context) {\n\t\tvar layer = getLayer(getGlobalDepth(\n\t\t\t\tcontext.transform().m22(),\n\t\t\t\tcontext.transform().m32(),\n\t\t\t\t0.0f\n\t\t));\n\n\t\tstringDrawContexts\t.add(context);\n\t\tlayer\t\t\t\t.add(context);\n\t}\n\n\tprivate List<IGuiElementContext> getLayer(float depth) {\n\t\tvar layer = depthLayers.get(depth);\n\n\t\tif (layer == null) {\n\t\t\tlayer = new ReferenceArrayList<>();\n\t\t\tdepthLayers.put(depth, layer);\n\t\t}\n\n\t\treturn layer;\n\t}\n\n\tpublic static float getGlobalDepth(\n\t\t\tfloat m22,\n\t\t\tfloat m32,\n\t\t\tfloat localDepth\n\t) {\n\t\treturn m22 * localDepth + m32;\n\t}\n\n\tpublic void delete() {\n\t\tscissorDraw\t.delete();\n\t\tscissorFlush.delete();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/GuiRenderTypes.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.gui;\n\nimport com.mojang.blaze3d.vertex.DefaultVertexFormat;\nimport com.mojang.blaze3d.vertex.VertexFormat;\nimport net.minecraft.Util;\nimport net.minecraft.client.renderer.GameRenderer;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.resources.ResourceLocation;\n\nimport java.util.function.Function;\n\npublic class GuiRenderTypes extends RenderType {\n\n\tpublic static final ShaderStateShard POSITION_TEX_COLOR_SHADER = new ShaderStateShard(GameRenderer::getPositionTexColorShader);\n\n\tpublic static final Function<ResourceLocation, RenderType> BLIT = Util.memoize(atlasLocation -> create(\n\t\t\t\t\"acceleratedrendering:blit\",\n\t\t\t\tDefaultVertexFormat\t.POSITION_TEX_COLOR,\n\t\t\t\tVertexFormat.Mode\t.QUADS,\n\t\t\t\t256,\n\t\t\t\tfalse,\n\t\t\t\tfalse,\n\t\t\t\tCompositeState\n\t\t\t\t\t\t.builder()\n\t\t\t\t\t\t.setTextureState\t\t(new TextureStateShard(atlasLocation, false, false))\n\t\t\t\t\t\t.setShaderState\t\t\t(POSITION_TEX_COLOR_SHADER)\n\t\t\t\t\t\t.setDepthTestState\t\t(LEQUAL_DEPTH_TEST)\n\t\t\t\t\t\t.setTransparencyState\t(TRANSLUCENT_TRANSPARENCY)\n\t\t\t\t\t\t.createCompositeState\t(false)\n\t));\n\n\tprivate GuiRenderTypes(\n\t\t\tString\t\t\t\tname,\n\t\t\tVertexFormat\t\tformat,\n\t\t\tVertexFormat.Mode\tformatMode,\n\t\t\tint\t\t\t\t\tbufferSize,\n\t\t\tboolean\t\t\t\taffectsCrumbling,\n\t\t\tboolean\t\t\t\tsortOnUpload,\n\t\t\tRunnable\t\t\tsetupState,\n\t\t\tRunnable\t\t\tclearState\n\t) {\n\t\tsuper(\n\t\t\t\tname,\n\t\t\t\tformat,\n\t\t\t\tformatMode,\n\t\t\t\tbufferSize,\n\t\t\t\taffectsCrumbling,\n\t\t\t\tsortOnUpload,\n\t\t\t\tsetupState,\n\t\t\t\tclearState\n\t\t);\n\t}\n\n\tpublic static RenderType blit(ResourceLocation atlasLocation) {\n\t\treturn BLIT.apply(atlasLocation);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/BlitDrawContext.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.gui.contexts;\n\nimport net.minecraft.resources.ResourceLocation;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\npublic record BlitDrawContext(\n\t\tMatrix4f\t\t\ttransform,\n\t\tMatrix3f\t\t\tnormal,\n\t\tResourceLocation\tatlasLocation,\n\t\tint\t\t\t\t\tminX,\n\t\tint\t\t\t\t\tmaxX,\n\t\tint\t\t\t\t\tminY,\n\t\tint\t\t\t\t\tmaxY,\n\t\tint\t\t\t\t\tblitOffset,\n\t\tint\t\t\t\t\tblitColor,\n\t\tint\t\t\t\t\tblitLight,\n\t\tint\t\t\t\t\tblitOverlay,\n\t\tfloat\t\t\t\tminU,\n\t\tfloat\t\t\t\tmaxU,\n\t\tfloat\t\t\t\tminV,\n\t\tfloat\t\t\t\tmaxV\n) implements IGuiElementContext {\n\n\t@Override\n\tpublic float depth() {\n\t\treturn blitOffset;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/DecoratorDrawContext.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.gui.contexts;\n\nimport net.minecraft.client.gui.Font;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.client.ItemDecoratorHandler;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\n@SuppressWarnings(\"UnstableApiUsage\")\npublic record DecoratorDrawContext(\n\t\tMatrix4f\t\t\t\ttransform,\n\t\tMatrix3f\t\t\t\tnormal,\n\t\tItemDecoratorHandler\thandler,\n\t\tFont\t\t\t\t\tfont,\n\t\tItemStack\t\t\t\tstack,\n\t\tint\t\t\t\t\t\txOffset,\n\t\tint\t\t\t\t\t\tyOffset\n) implements IGuiElementContext {\n\n\t@Override\n\tpublic float depth() {\n\t\treturn 100.0f;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/FillDrawContext.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.gui.contexts;\n\nimport net.minecraft.client.renderer.RenderType;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\npublic record FillDrawContext(\n\t\tMatrix4f\ttransform,\n\t\tMatrix3f\tnormal,\n\t\tRenderType\trenderType,\n\t\tint\t\t\tminX,\n\t\tint\t\t\tminY,\n\t\tint\t\t\tmaxX,\n\t\tint\t\t\tmaxY,\n\t\tint\t\t\tblitOffset,\n\t\tint\t\t\tcolor,\n\t\tint\t\t\tlight,\n\t\tint\t\t\toverlay\n) implements IGuiElementContext {\n\n\t@Override\n\tpublic float depth() {\n\t\treturn blitOffset;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/GradientDrawContext.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.gui.contexts;\n\nimport net.minecraft.client.renderer.RenderType;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\npublic record GradientDrawContext(\n\t\tMatrix4f\ttransform,\n\t\tMatrix3f\tnormal,\n\t\tRenderType\trenderType,\n\t\tint\t\t\tminX,\n\t\tint\t\t\tminY,\n\t\tint\t\t\tmaxX,\n\t\tint\t\t\tmaxY,\n\t\tint\t\t\tblitOffset,\n\t\tint\t\t\tcolorFrom,\n\t\tint\t\t\tcolorTo,\n\t\tint\t\t\tlight,\n\t\tint\t\t\toverlay\n) implements IGuiElementContext {\n\n\t@Override\n\tpublic float depth() {\n\t\treturn blitOffset;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/HighlightDrawContext.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.gui.contexts;\n\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\npublic record HighlightDrawContext(\n\t\tMatrix4f\ttransform,\n\t\tMatrix3f\tnormal,\n\t\tint\t\t\thighlightX,\n\t\tint\t\t\thighlightY,\n\t\tint\t\t\tblitOffset,\n\t\tint\t\t\tcolor\n) implements IGuiElementContext {\n\n\t@Override\n\tpublic float depth() {\n\t\treturn blitOffset;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/IGuiElementContext.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.gui.contexts;\n\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\npublic interface IGuiElementContext {\n\n\tMatrix4f\ttransform\t();\n\tMatrix3f\tnormal\t\t();\n\tfloat\t\tdepth\t\t();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/ItemRenderContext.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.gui.contexts;\n\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.world.item.ItemDisplayContext;\nimport net.minecraft.world.item.ItemStack;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\npublic record ItemRenderContext(\n\t\tMatrix4f\t\t\ttransform,\n\t\tMatrix3f\t\t\tnormal,\n\t\tItemStack\t\t\titemStack,\n\t\tItemDisplayContext\tdisplayContext,\n\t\tboolean\t\t\t\tleftHand,\n\t\tint\t\t\t\t\tcombinedLight,\n\t\tint\t\t\t\t\tcombinedOverlay,\n\t\tBakedModel\t\t\tbakedModel\n) implements IGuiElementContext {\n\n\t@Override\n\tpublic float depth() {\n\t\treturn 0.0f;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/string/ComponentStringDrawContext.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string;\n\nimport net.minecraft.client.gui.Font;\nimport net.minecraft.client.renderer.MultiBufferSource;\nimport net.minecraft.network.chat.Component;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\npublic record ComponentStringDrawContext(\n\t\tMatrix4f\t\t\ttransform,\n\t\tFont\t\t\t\tfont,\n\t\tComponent\t\t\ttext,\n\t\tfloat\t\t\t\ttextX,\n\t\tfloat\t\t\t\ttextY,\n\t\tint\t\t\t\t\ttextColor,\n\t\tboolean\t\t\t\tdropShadow,\n\t\tFont.DisplayMode\tdisplayMode,\n\t\tint\t\t\t\t\tbackgroundColor,\n\t\tint\t\t\t\t\tpackedLight\n) implements IStringDrawContext {\n\n\tpublic static final Matrix3f NORMAL = new Matrix3f().identity();\n\n\t@Override\n\tpublic Matrix3f normal() {\n\t\treturn NORMAL;\n\t}\n\n\t@Override\n\tpublic float depth() {\n\t\treturn 0.0f;\n\t}\n\n\t@Override\n\tpublic void drawString(MultiBufferSource bufferSource) {\n\t\tfont.drawInBatch(\n\t\t\t\ttext,\n\t\t\t\ttextX,\n\t\t\t\ttextY,\n\t\t\t\ttextColor,\n\t\t\t\tdropShadow,\n\t\t\t\ttransform,\n\t\t\t\tbufferSource,\n\t\t\t\tdisplayMode,\n\t\t\t\tbackgroundColor,\n\t\t\t\tpackedLight\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/string/FormattedStringDrawContext.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string;\n\nimport net.minecraft.client.gui.Font;\nimport net.minecraft.client.renderer.MultiBufferSource;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.util.FormattedCharSequence;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\npublic record FormattedStringDrawContext(\n\t\tMatrix4f\t\t\t\ttransform,\n\t\tFont\t\t\t\t\tfont,\n\t\tFormattedCharSequence\ttext,\n\t\tfloat\t\t\t\t\ttextX,\n\t\tfloat\t\t\t\t\ttextY,\n\t\tint\t\t\t\t\t\ttextColor,\n\t\tboolean\t\t\t\t\tdropShadow,\n\t\tFont.DisplayMode\t\tdisplayMode,\n\t\tint\t\t\t\t\t\tbackgroundColor,\n\t\tint\t\t\t\t\t\tpackedLight\n) implements IStringDrawContext {\n\n\tpublic static final Matrix3f NORMAL = new Matrix3f().identity();\n\n\t@Override\n\tpublic Matrix3f normal() {\n\t\treturn NORMAL;\n\t}\n\n\t@Override\n\tpublic float depth() {\n\t\treturn 0.0f;\n\t}\n\n\t@Override\n\tpublic void drawString(MultiBufferSource bufferSource) {\n\t\tfont.drawInBatch(\n\t\t\t\ttext,\n\t\t\t\ttextX,\n\t\t\t\ttextY,\n\t\t\t\ttextColor,\n\t\t\t\tdropShadow,\n\t\t\t\ttransform,\n\t\t\t\tbufferSource,\n\t\t\t\tdisplayMode,\n\t\t\t\tbackgroundColor,\n\t\t\t\tpackedLight\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/string/IStringDrawContext.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string;\n\nimport com.github.argon4w.acceleratedrendering.features.items.gui.contexts.IGuiElementContext;\nimport net.minecraft.client.renderer.MultiBufferSource;\n\npublic interface IStringDrawContext extends IGuiElementContext {\n\n\tvoid drawString(MultiBufferSource buffer);\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/string/Outline8StringDrawContext.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string;\n\nimport net.minecraft.client.gui.Font;\nimport net.minecraft.client.renderer.MultiBufferSource;\nimport net.minecraft.util.FormattedCharSequence;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\npublic record Outline8StringDrawContext(\n\t\tMatrix4f\t\t\t\ttransform,\n\t\tFont\t\t\t\t\tfont,\n\t\tFormattedCharSequence\ttext,\n\t\tfloat\t\t\t\t\ttextX,\n\t\tfloat\t\t\t\t\ttextY,\n\t\tint\t\t\t\t\t\ttextColor,\n\t\tint\t\t\t\t\t\tbackgroundColor,\n\t\tint\t\t\t\t\t\tpackedLight\n) implements IStringDrawContext {\n\n\tpublic static final Matrix3f NORMAL = new Matrix3f().identity();\n\n\t@Override\n\tpublic Matrix3f normal() {\n\t\treturn NORMAL;\n\t}\n\n\t@Override\n\tpublic float depth() {\n\t\treturn 0.0f;\n\t}\n\n\t@Override\n\tpublic void drawString(MultiBufferSource bufferSource) {\n\t\tfont.drawInBatch8xOutline(\n\t\t\t\ttext,\n\t\t\t\ttextX,\n\t\t\t\ttextY,\n\t\t\t\ttextColor,\n\t\t\t\tbackgroundColor,\n\t\t\t\ttransform,\n\t\t\t\tbufferSource,\n\t\t\t\tpackedLight\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/string/RawStringDrawContext.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string;\n\nimport net.minecraft.client.gui.Font;\nimport net.minecraft.client.renderer.MultiBufferSource;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\npublic record RawStringDrawContext(\n\t\tMatrix4f\t\t\ttransform,\n\t\tFont\t\t\t\tfont,\n\t\tString\t\t\t\ttext,\n\t\tfloat\t\t\t\ttextX,\n\t\tfloat\t\t\t\ttextY,\n\t\tint\t\t\t\t\ttextColor,\n\t\tboolean\t\t\t\tdropShadow,\n\t\tFont.DisplayMode\tdisplayMode,\n\t\tint\t\t\t\t\tbackgroundColor,\n\t\tint\t\t\t\t\tpackedLight,\n\t\tboolean\t\t\t\tbidirectional\n) implements IStringDrawContext {\n\n\tpublic static final Matrix3f NORMAL = new Matrix3f().identity();\n\n\t@Override\n\tpublic Matrix3f normal() {\n\t\treturn NORMAL;\n\t}\n\n\t@Override\n\tpublic float depth() {\n\t\treturn 0.0f;\n\t}\n\n\t@Override\n\tpublic void drawString(MultiBufferSource bufferSource) {\n\t\tfont.drawInBatch(\n\t\t\t\ttext,\n\t\t\t\ttextX,\n\t\t\t\ttextY,\n\t\t\t\ttextColor,\n\t\t\t\tdropShadow,\n\t\t\t\ttransform,\n\t\t\t\tbufferSource,\n\t\t\t\tdisplayMode,\n\t\t\t\tbackgroundColor,\n\t\t\t\tpackedLight,\n\t\t\t\tbidirectional\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/renderer/AcceleratedBlitRenderer.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.gui.renderer;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.github.argon4w.acceleratedrendering.features.items.gui.contexts.BlitDrawContext;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.experimental.ExtensionMethod;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\n@ExtensionMethod(VertexConsumerExtension.class)\npublic class AcceleratedBlitRenderer implements IAcceleratedRenderer<BlitDrawContext> {\n\n\tpublic static final AcceleratedBlitRenderer INSTANCE = new AcceleratedBlitRenderer();\n\n\t@Override\n\tpublic void render(\n\t\t\tVertexConsumer\tvertexConsumer,\n\t\t\tBlitDrawContext\tcontext,\n\t\t\tMatrix4f\t\ttransform,\n\t\t\tMatrix3f\t\tnormal,\n\t\t\tint\t\t\t\tlight,\n\t\t\tint\t\t\t\toverlay,\n\t\t\tint\t\t\t\tcolor\n\t) {\n\t\tvar extension = vertexConsumer.getAccelerated();\n\n\t\textension.beginTransform(transform, normal);\n\n\t\tvar minU\t\t= context.minU\t\t();\n\t\tvar minV\t\t= context.minV\t\t();\n\t\tvar maxU\t\t= context.maxU\t\t();\n\t\tvar maxV\t\t= context.maxV\t\t();\n\t\tvar minX\t\t= context.minX\t\t();\n\t\tvar minY\t\t= context.minY\t\t();\n\t\tvar maxX\t\t= context.maxX\t\t();\n\t\tvar maxY\t\t= context.maxY\t\t();\n\t\tvar blitOffset\t= context.blitOffset();\n\n\t\tvertexConsumer.addVertex(minX, minY, blitOffset).setColor(color).setUv(minU, minV);\n\t\tvertexConsumer.addVertex(minX, maxY, blitOffset).setColor(color).setUv(minU, maxV);\n\t\tvertexConsumer.addVertex(maxX, maxY, blitOffset).setColor(color).setUv(maxU, maxV);\n\t\tvertexConsumer.addVertex(maxX, minY, blitOffset).setColor(color).setUv(maxU, minV);\n\n\t\textension.endTransform();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/renderer/AcceleratedFillRenderer.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.gui.renderer;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.github.argon4w.acceleratedrendering.features.items.gui.contexts.FillDrawContext;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.experimental.ExtensionMethod;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\n@ExtensionMethod(VertexConsumerExtension.class)\npublic class AcceleratedFillRenderer implements IAcceleratedRenderer<FillDrawContext> {\n\n\tpublic static final AcceleratedFillRenderer INSTANCE = new AcceleratedFillRenderer();\n\n\t@Override\n\tpublic void render(\n\t\t\tVertexConsumer\tvertexConsumer,\n\t\t\tFillDrawContext\tcontext,\n\t\t\tMatrix4f\t\ttransform,\n\t\t\tMatrix3f\t\tnormal,\n\t\t\tint\t\t\t\tlight,\n\t\t\tint\t\t\t\toverlay,\n\t\t\tint\t\t\t\tcolor\n\t) {\n\t\tvar extension = vertexConsumer.getAccelerated();\n\n\t\textension.beginTransform(transform, normal);\n\n\t\tvar blitOffset\t= context.blitOffset();\n\t\tvar minX\t\t= context.minX\t\t();\n\t\tvar minY\t\t= context.minY\t\t();\n\t\tvar maxX\t\t= context.maxX\t\t();\n\t\tvar maxY\t\t= context.maxY\t\t();\n\t\tvar swap\t\t= 0;\n\n\t\tif (minX < maxX) {\n\t\t\tswap = minX;\n\t\t\tminX = maxX;\n\t\t\tmaxX = swap;\n\t\t}\n\n\t\tif (minY < maxY) {\n\t\t\tswap = minY;\n\t\t\tminY = maxY;\n\t\t\tmaxY = swap;\n\t\t}\n\n\t\tvertexConsumer.addVertex(minX, minY, blitOffset).setColor(color);\n\t\tvertexConsumer.addVertex(minX, maxY, blitOffset).setColor(color);\n\t\tvertexConsumer.addVertex(maxX, maxY, blitOffset).setColor(color);\n\t\tvertexConsumer.addVertex(maxX, minY, blitOffset).setColor(color);\n\n\t\textension.endTransform();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/renderer/AcceleratedGradientRenderer.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.gui.renderer;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.github.argon4w.acceleratedrendering.features.items.gui.contexts.FillDrawContext;\nimport com.github.argon4w.acceleratedrendering.features.items.gui.contexts.GradientDrawContext;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.experimental.ExtensionMethod;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\n\n@ExtensionMethod(VertexConsumerExtension.class)\npublic class AcceleratedGradientRenderer implements IAcceleratedRenderer<GradientDrawContext> {\n\n\tpublic static final AcceleratedGradientRenderer INSTANCE = new AcceleratedGradientRenderer();\n\n\t@Override\n\tpublic void render(\n\t\t\tVertexConsumer\t\tvertexConsumer,\n\t\t\tGradientDrawContext\tcontext,\n\t\t\tMatrix4f\t\t\ttransform,\n\t\t\tMatrix3f\t\t\tnormal,\n\t\t\tint\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\tcolor\n\t) {\n\t\tvar extension = vertexConsumer.getAccelerated();\n\n\t\textension.beginTransform(transform, normal);\n\n\t\tvar blitOffset\t= context.blitOffset();\n\t\tvar minX\t\t= context.minX\t\t();\n\t\tvar minY\t\t= context.minY\t\t();\n\t\tvar maxX\t\t= context.maxX\t\t();\n\t\tvar maxY\t\t= context.maxY\t\t();\n\t\tvar colorFrom\t= context.colorFrom\t();\n\t\tvar colorTo\t\t= context.colorTo\t();\n\n\t\tvertexConsumer.addVertex(minX, minY, blitOffset).setColor(colorFrom);\n\t\tvertexConsumer.addVertex(minX, maxY, blitOffset).setColor(colorTo);\n\t\tvertexConsumer.addVertex(maxX, maxY, blitOffset).setColor(colorTo);\n\t\tvertexConsumer.addVertex(maxX, minY, blitOffset).setColor(colorFrom);\n\n\t\textension.endTransform();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/ItemRendererMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.mixins;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.utils.DirectionUtils;\nimport com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.items.AcceleratedQuadsRenderer;\nimport com.github.argon4w.acceleratedrendering.features.items.BakedModelExtension;\nimport com.github.argon4w.acceleratedrendering.features.items.colors.ItemLayerColors;\nimport com.github.argon4w.acceleratedrendering.features.items.contexts.AcceleratedQuadsRenderContext;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.entity.ItemRenderer;\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.util.RandomSource;\nimport net.minecraft.world.item.ItemStack;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.At;\n\n@ExtensionMethod(value = {VertexConsumerExtension\t.class, BakedModelExtension.class\t})\n@Mixin\t\t\t(value = {ItemRenderer\t\t\t\t.class\t\t\t\t\t\t\t\t})\npublic class ItemRendererMixin {\n\n\t@SuppressWarnings\t(\"deprecation\")\n\t@WrapOperation\t\t(\n\t\t\tmethod\t= \"render\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/minecraft/client/renderer/entity/ItemRenderer;renderModelLists(Lnet/minecraft/client/resources/model/BakedModel;Lnet/minecraft/world/item/ItemStack;IILcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;)V\"\n\t\t\t)\n\t)\n\tpublic void renderFast(\n\t\t\tItemRenderer\tinstance,\n\t\t\tBakedModel\t\tpModel,\n\t\t\tItemStack\t\tpStack,\n\t\t\tint\t\t\t\tpCombinedLight,\n\t\t\tint\t\t\t\tpCombinedOverlay,\n\t\t\tPoseStack\t\tpPoseStack,\n\t\t\tVertexConsumer\tpBuffer,\n\t\t\tOperation<Void>\toriginal\n\t) {\n\t\tvar extension1 = pBuffer.getAccelerated();\n\t\tvar extension2 = pModel\t.getAccelerated();\n\n\t\tif (\t\t\t!\t\tAcceleratedItemRenderingFeature\t.isEnabled\t\t\t\t\t\t()\n\t\t\t\t||\t\t!\t\tAcceleratedItemRenderingFeature\t.shouldUseAcceleratedPipeline\t()\n\t\t\t\t||\t(\t!\t\tCoreFeature\t\t\t\t\t\t.isRenderingLevel\t\t\t\t()\n\n\t\t\t\t&&\t\t!\t(\tCoreFeature\t\t\t\t\t\t.isRenderingHand\t\t\t\t()\n\t\t\t\t&&\t\t\t(\textension2\t\t\t\t\t\t.isAcceleratedInHand\t\t\t()\n\t\t\t\t||\t\t\t\tAcceleratedItemRenderingFeature\t.shouldAccelerateInHand\t\t\t()))\n\n\t\t\t\t&&\t\t!\t(\tCoreFeature\t\t\t\t\t\t.isRenderingGui\t\t\t\t\t()\n\t\t\t\t&&\t\t\t(\textension2\t\t\t\t\t\t.isAcceleratedInGui\t\t\t\t()\n\t\t\t\t||\t\t\t\tAcceleratedItemRenderingFeature\t.shouldAccelerateInGui\t\t\t())))\n\t\t\t\t||\t\t!\t\textension1\t\t\t\t\t\t.isAccelerated\t\t\t\t\t()\n\t\t) {\n\t\t\toriginal.call(\n\t\t\t\t\tinstance,\n\t\t\t\t\tpModel,\n\t\t\t\t\tpStack,\n\t\t\t\t\tpCombinedLight,\n\t\t\t\t\tpCombinedOverlay,\n\t\t\t\t\tpPoseStack,\n\t\t\t\t\tpBuffer\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (extension2.isAccelerated()) {\n\t\t\textension2.renderItemFast(\n\t\t\t\t\tpStack,\n\t\t\t\t\tRandomSource.create\t(42L),\n\t\t\t\t\tpPoseStack\t.last\t(),\n\t\t\t\t\textension1,\n\t\t\t\t\tpCombinedLight,\n\t\t\t\t\tpCombinedOverlay\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!AcceleratedItemRenderingFeature.shouldBakeMeshForQuad()) {\n\t\t\toriginal.call(\n\t\t\t\t\tinstance,\n\t\t\t\t\tpModel,\n\t\t\t\t\tpStack,\n\t\t\t\t\tpCombinedLight,\n\t\t\t\t\tpCombinedOverlay,\n\t\t\t\t\tpPoseStack,\n\t\t\t\t\tpBuffer\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tvar pose\t\t\t= pPoseStack\t.last\t();\n\t\tvar randomSource\t= RandomSource\t.create\t();\n\n\t\tfor (var direction : DirectionUtils.FULL) {\n\t\t\trandomSource.setSeed\t(42L);\n\t\t\textension1\t.doRender\t(\n\t\t\t\t\tAcceleratedQuadsRenderer.INSTANCE,\n\t\t\t\t\tnew AcceleratedQuadsRenderContext(\n\t\t\t\t\t\t\tpModel.getQuads(\n\t\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t\t\tdirection,\n\t\t\t\t\t\t\t\t\trandomSource\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tnew ItemLayerColors(pStack)\n\t\t\t\t\t),\n\t\t\t\t\tpose.pose\t(),\n\t\t\t\t\tpose.normal\t(),\n\t\t\t\t\tpCombinedLight,\n\t\t\t\t\tpCombinedOverlay,\n\t\t\t\t\t-1\n\t\t\t);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/ModelBlockRendererMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.mixins;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.utils.DirectionUtils;\nimport com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.items.AcceleratedQuadsRenderer;\nimport com.github.argon4w.acceleratedrendering.features.items.BakedModelExtension;\nimport com.github.argon4w.acceleratedrendering.features.items.colors.FixedColors;\nimport com.github.argon4w.acceleratedrendering.features.items.contexts.AcceleratedQuadsRenderContext;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.client.renderer.block.ModelBlockRenderer;\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.util.FastColor;\nimport net.minecraft.util.Mth;\nimport net.minecraft.util.RandomSource;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@ExtensionMethod(value = {VertexConsumerExtension\t.class, BakedModelExtension.class\t})\n@Mixin\t\t\t(value = {ModelBlockRenderer\t\t.class\t\t\t\t\t\t\t\t}, priority = 999)\npublic class ModelBlockRendererMixin {\n\n\t@Inject(\n\t\t\tcancellable\t= true,\n\t\t\tmethod\t\t= \"renderModel(Lcom/mojang/blaze3d/vertex/PoseStack$Pose;Lcom/mojang/blaze3d/vertex/VertexConsumer;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/client/resources/model/BakedModel;FFFIILnet/neoforged/neoforge/client/model/data/ModelData;Lnet/minecraft/client/renderer/RenderType;)V\",\n\t\t\tat\t\t\t= @At(\"HEAD\")\n\t)\n\tpublic void renderModelFast(\n\t\t\tPoseStack.Pose\t\tpose,\n\t\t\tVertexConsumer\t\tconsumer,\n\t\t\tBlockState\t\t\tstate,\n\t\t\tBakedModel\t\t\tmodel,\n\t\t\tfloat\t\t\t\tred,\n\t\t\tfloat\t\t\t\tgreen,\n\t\t\tfloat\t\t\t\tblue,\n\t\t\tint\t\t\t\t\tpackedLight,\n\t\t\tint\t\t\t\t\tpackedOverlay,\n\t\t\tModelData\t\t\tmodelData,\n\t\t\tRenderType\t\t\trenderType,\n\t\t\tCallbackInfo\t\tci\n\t) {\n\t\tvar extension1 = consumer\t.getAccelerated();\n\t\tvar extension2 = model\t\t.getAccelerated();\n\n\t\tif (\t\t\t!\t\tAcceleratedItemRenderingFeature\t.isEnabled\t\t\t\t\t\t()\n\t\t\t\t||\t\t!\t\tAcceleratedItemRenderingFeature\t.shouldUseAcceleratedPipeline\t()\n\t\t\t\t||\t(\t!\t\tCoreFeature\t\t\t\t\t\t.isRenderingLevel\t\t\t\t()\n\n\t\t\t\t&&\t\t!\t(\tCoreFeature\t\t\t\t\t\t.isRenderingHand\t\t\t\t()\n\t\t\t\t&&\t\t\t(\textension2\t\t\t\t\t\t.isAcceleratedInHand\t\t\t()\n\t\t\t\t||\t\t\t\tAcceleratedItemRenderingFeature\t.shouldAccelerateInHand\t\t\t()))\n\n\t\t\t\t&&\t\t!\t(\tCoreFeature\t\t\t\t\t\t.isRenderingGui\t\t\t\t\t()\n\t\t\t\t&&\t\t\t(\textension2\t\t\t\t\t\t.isAcceleratedInGui\t\t\t\t()\n\t\t\t\t||\t\t\t\tAcceleratedItemRenderingFeature\t.shouldAccelerateInGui\t\t\t())))\n\t\t\t\t||\t\t!\t\textension1\t\t\t\t\t\t.isAccelerated\t\t\t\t\t()\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (extension2.isAccelerated()) {\n\t\t\tci\t\t\t.cancel\t\t\t();\n\t\t\textension2\t.renderBlockFast(\n\t\t\t\t\tstate,\n\t\t\t\t\tRandomSource.create(42),\n\t\t\t\t\tpose,\n\t\t\t\t\textension1,\n\t\t\t\t\tpackedLight,\n\t\t\t\t\tpackedOverlay,\n\t\t\t\t\tFastColor.ARGB32.colorFromFloat(\n\t\t\t\t\t\t\t1.0f,\n\t\t\t\t\t\t\tMth.clamp(red,\t\t0.0f, 1.0f),\n\t\t\t\t\t\t\tMth.clamp(green,\t0.0f, 1.0f),\n\t\t\t\t\t\t\tMth.clamp(blue,\t\t0.0f, 1.0f)\n\t\t\t\t\t),\n\t\t\t\t\tmodelData,\n\t\t\t\t\trenderType\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!AcceleratedItemRenderingFeature.shouldBakeMeshForQuad()) {\n\t\t\treturn;\n\t\t}\n\n\t\tci.cancel();\n\n\t\tvar randomSource = RandomSource.create();\n\n\t\tfor (var direction : DirectionUtils.FULL) {\n\t\t\trandomSource.setSeed\t(42L);\n\t\t\textension1\t.doRender\t(\n\t\t\t\t\tAcceleratedQuadsRenderer.INSTANCE,\n\t\t\t\t\tnew AcceleratedQuadsRenderContext(\n\t\t\t\t\t\t\tmodel.getQuads(\n\t\t\t\t\t\t\t\t\tstate,\n\t\t\t\t\t\t\t\t\tdirection,\n\t\t\t\t\t\t\t\t\trandomSource,\n\t\t\t\t\t\t\t\t\tmodelData,\n\t\t\t\t\t\t\t\t\trenderType\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tnew FixedColors(FastColor.ARGB32.colorFromFloat(\n\t\t\t\t\t\t\t\t\t1.0f,\n\t\t\t\t\t\t\t\t\tMth.clamp(red,\t\t0.0f, 1.0f),\n\t\t\t\t\t\t\t\t\tMth.clamp(green,\t0.0f, 1.0f),\n\t\t\t\t\t\t\t\t\tMth.clamp(blue,\t\t0.0f, 1.0f)\n\t\t\t\t\t\t\t))\n\t\t\t\t\t),\n\t\t\t\t\tpose.pose\t(),\n\t\t\t\t\tpose.normal\t(),\n\t\t\t\t\tpackedLight,\n\t\t\t\t\tpackedOverlay,\n\t\t\t\t\t-1\n\t\t\t);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/accessors/BlockColorsAccessor.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.mixins.accessors;\n\nimport net.minecraft.client.color.block.BlockColor;\nimport net.minecraft.client.color.block.BlockColors;\nimport net.minecraft.world.level.block.Block;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.gen.Accessor;\n\nimport java.util.Map;\n\n@Mixin(BlockColors.class)\npublic interface BlockColorsAccessor {\n\n\t@Accessor(\"blockColors\")\n\tMap<Block, BlockColor> getBlockColors();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/accessors/ItemColorsAccessor.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.mixins.accessors;\n\nimport net.minecraft.client.color.item.ItemColor;\nimport net.minecraft.client.color.item.ItemColors;\nimport net.minecraft.world.item.Item;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.gen.Accessor;\n\nimport java.util.Map;\n\n@Mixin(ItemColors.class)\npublic interface ItemColorsAccessor {\n\n\t@Accessor(\"itemColors\")\n\tMap<Item, ItemColor> getItemColors();\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/compatibility/ClientHooksMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.mixins.compatibility;\n\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;\nimport net.neoforged.bus.api.Event;\nimport net.neoforged.bus.api.IEventBus;\nimport net.neoforged.neoforge.client.ClientHooks;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.At;\n\n@Mixin(ClientHooks.class)\npublic class ClientHooksMixin {\n\n\t@WrapOperation(\n\t\t\tmethod\t= \"drawScreenInternal\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/neoforged/bus/api/IEventBus;post(Lnet/neoforged/bus/api/Event;)Lnet/neoforged/bus/api/Event;\"\n\t\t\t)\n\t)\n\tprivate static Event disableAdditionalScreenAcceleration(\n\t\t\tIEventBus\t\t\tinstance,\n\t\t\tEvent\t\t\t\tevent,\n\t\t\tOperation<Event>\toriginal\n\t) {\n\t\tAcceleratedEntityRenderingFeature\t.useVanillaPipeline\t();\n\t\tAcceleratedItemRenderingFeature\t\t.useVanillaPipeline\t();\n\t\tAcceleratedTextRenderingFeature\t\t.useVanillaPipeline\t();\n\n\t\tvar result = original.call(instance, event);\n\n\t\tAcceleratedEntityRenderingFeature\t.resetPipeline\t\t();\n\t\tAcceleratedItemRenderingFeature\t\t.resetPipeline\t\t();\n\t\tAcceleratedTextRenderingFeature\t\t.resetPipeline\t\t();\n\n\t\treturn result;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/compatibility/GuiLayerManagerMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.mixins.compatibility;\n\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;\nimport net.neoforged.bus.api.Event;\nimport net.neoforged.bus.api.IEventBus;\nimport net.neoforged.neoforge.client.gui.GuiLayerManager;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.At;\n\n@SuppressWarnings\t(\"UnstableApiUsage\")\n@Mixin\t\t\t\t(GuiLayerManager.class)\npublic class GuiLayerManagerMixin {\n\n\t@WrapOperation(\n\t\t\tmethod\t= \"render\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/neoforged/bus/api/IEventBus;post(Lnet/neoforged/bus/api/Event;)Lnet/neoforged/bus/api/Event;\"\n\t\t\t)\n\t)\n\tprivate static Event disableAdditionalGuiAcceleration(\n\t\t\tIEventBus\t\t\tinstance,\n\t\t\tEvent\t\t\t\tevent,\n\t\t\tOperation<Event>\toriginal\n\t) {\n\t\tAcceleratedEntityRenderingFeature\t.useVanillaPipeline\t();\n\t\tAcceleratedItemRenderingFeature\t\t.useVanillaPipeline\t();\n\t\tAcceleratedTextRenderingFeature\t\t.useVanillaPipeline\t();\n\n\t\tvar result = original.call(instance, event);\n\n\t\tAcceleratedEntityRenderingFeature\t.resetPipeline\t\t();\n\t\tAcceleratedItemRenderingFeature\t\t.resetPipeline\t\t();\n\t\tAcceleratedTextRenderingFeature\t\t.resetPipeline\t\t();\n\n\t\treturn result;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/gui/AbstractContainerScreenMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.mixins.gui;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.items.gui.GuiBatchingController;\nimport com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@Mixin(AbstractContainerScreen.class)\npublic abstract class AbstractContainerScreenMixin {\n\n\t@Inject(\n\t\t\tmethod\t= \"render\",\n\t\t\tat\t\t= @At(\"HEAD\")\n\t)\n\tpublic void startBackgroundBatching(\n\t\t\tGuiGraphics\t\tguiGraphics,\n\t\t\tint\t\t\t\tmouseX,\n\t\t\tint\t\t\t\tmouseY,\n\t\t\tfloat\t\t\tpartialTick,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tGuiBatchingController.INSTANCE.startBatching(guiGraphics);\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"render\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lcom/mojang/blaze3d/vertex/PoseStack;translate(FFF)V\",\n\t\t\t\t\tshift\t= At.Shift.BEFORE\n\t\t\t)\n\t)\n\tpublic void flushBackgroundBatching(\n\t\t\tGuiGraphics\t\tguiGraphics,\n\t\t\tint\t\t\t\tmouseX,\n\t\t\tint\t\t\t\tmouseY,\n\t\t\tfloat\t\t\tpartialTick,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tif (!AcceleratedItemRenderingFeature.shouldMergeGuiItemBatches()) {\n\t\t\tGuiBatchingController.INSTANCE.flushBatching(guiGraphics);\n\t\t}\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"render\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lcom/mojang/blaze3d/vertex/PoseStack;translate(FFF)V\",\n\t\t\t\t\tshift\t= At.Shift.AFTER\n\t\t\t)\n\t)\n\tpublic void startItemBatching(\n\t\t\tGuiGraphics\t\tguiGraphics,\n\t\t\tint\t\t\t\tmouseX,\n\t\t\tint\t\t\t\tmouseY,\n\t\t\tfloat\t\t\tpartialTick,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tif (!AcceleratedItemRenderingFeature.shouldMergeGuiItemBatches()) {\n\t\t\tGuiBatchingController.INSTANCE.startBatching(guiGraphics);\n\t\t}\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"render\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/minecraft/client/gui/screens/inventory/AbstractContainerScreen;renderLabels(Lnet/minecraft/client/gui/GuiGraphics;II)V\",\n\t\t\t\t\tshift\t= At.Shift.AFTER\n\t\t\t)\n\t)\n\tpublic void flushItemBatching(\n\t\t\tGuiGraphics\t\tguiGraphics,\n\t\t\tint\t\t\t\tmouseX,\n\t\t\tint\t\t\t\tmouseY,\n\t\t\tfloat\t\t\tpartialTick,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tGuiBatchingController.INSTANCE.flushBatching(guiGraphics);\n\t}\n\n\t@WrapMethod(method = \"renderSlotHighlight(Lnet/minecraft/client/gui/GuiGraphics;IIII)V\")\n\tprivate static void startRenderHighlight(\n\t\t\tGuiGraphics\t\tguiGraphics,\n\t\t\tint\t\t\t\thighlightX,\n\t\t\tint\t\t\t\thighLightY,\n\t\t\tint\t\t\t\tblitOffset,\n\t\t\tint\t\t\t\tcolor,\n\t\t\tOperation<Void>\toriginal\n\t) {\n\t\tif (!CoreFeature.isGuiBatching()) {\n\t\t\toriginal.call(\n\t\t\t\t\tguiGraphics,\n\t\t\t\t\thighlightX,\n\t\t\t\t\thighLightY,\n\t\t\t\t\tblitOffset,\n\t\t\t\t\tcolor\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tvar last = guiGraphics.pose().last();\n\n\t\tGuiBatchingController.INSTANCE.submitHighlight(\n\t\t\t\tlast.pose\t(),\n\t\t\t\tlast.normal\t(),\n\t\t\t\thighlightX,\n\t\t\t\thighLightY,\n\t\t\t\tblitOffset,\n\t\t\t\tcolor\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/gui/FontMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.mixins.gui;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.features.items.gui.GuiBatchingController;\nimport com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string.ComponentStringDrawContext;\nimport com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string.FormattedStringDrawContext;\nimport com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string.Outline8StringDrawContext;\nimport com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string.RawStringDrawContext;\nimport com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport net.minecraft.client.gui.Font;\nimport net.minecraft.client.renderer.MultiBufferSource;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.util.FormattedCharSequence;\nimport org.joml.Matrix4f;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\n\n@Mixin(Font.class)\npublic abstract class FontMixin {\n\n\t@Shadow public abstract boolean isBidirectional();\n\n\t@WrapMethod(method = \"drawInBatch(Ljava/lang/String;FFIZLorg/joml/Matrix4f;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/client/gui/Font$DisplayMode;II)I\")\n\tpublic int renderGuiStringFast1(\n\t\t\tString\t\t\t\ttext,\n\t\t\tfloat\t\t\t\ttextX,\n\t\t\tfloat\t\t\t\ttextY,\n\t\t\tint\t\t\t\t\ttextColor,\n\t\t\tboolean\t\t\t\tdropShadow,\n\t\t\tMatrix4f\t\t\ttransform,\n\t\t\tMultiBufferSource\tbufferSource,\n\t\t\tFont.DisplayMode\tdisplayMode,\n\t\t\tint\t\t\t\t\tbackgroundColor,\n\t\t\tint\t\t\t\t\tpackedLight,\n\t\t\tOperation<Integer>\toriginal\n\t) {\n\t\tif (!CoreFeature.isGuiBatching()) {\n\t\t\treturn original.call(\n\t\t\t\t\ttext,\n\t\t\t\t\ttextX,\n\t\t\t\t\ttextY,\n\t\t\t\t\ttextColor,\n\t\t\t\t\tdropShadow,\n\t\t\t\t\ttransform,\n\t\t\t\t\tbufferSource,\n\t\t\t\t\tdisplayMode,\n\t\t\t\t\tbackgroundColor,\n\t\t\t\t\tpackedLight\n\t\t\t);\n\t\t}\n\n\t\tGuiBatchingController.INSTANCE.submitString(new RawStringDrawContext(\n\t\t\t\tnew Matrix4f(transform),\n\t\t\t\t(Font) (Object) this,\n\t\t\t\ttext,\n\t\t\t\ttextX,\n\t\t\t\ttextY,\n\t\t\t\ttextColor,\n\t\t\t\tdropShadow,\n\t\t\t\tdisplayMode,\n\t\t\t\tbackgroundColor,\n\t\t\t\tpackedLight,\n\t\t\t\tisBidirectional()\n\t\t));\n\n\t\treturn 0;\n\t}\n\n\t@WrapMethod(method = \"drawInBatch(Ljava/lang/String;FFIZLorg/joml/Matrix4f;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/client/gui/Font$DisplayMode;IIZ)I\")\n\tpublic int renderGuiStringFast2(\n\t\t\tString\t\t\t\ttext,\n\t\t\tfloat\t\t\t\ttextX,\n\t\t\tfloat\t\t\t\ttextY,\n\t\t\tint\t\t\t\t\ttextColor,\n\t\t\tboolean\t\t\t\tdropShadow,\n\t\t\tMatrix4f\t\t\ttransform,\n\t\t\tMultiBufferSource\tbufferSource,\n\t\t\tFont.DisplayMode\tdisplayMode,\n\t\t\tint\t\t\t\t\tbackgroundColor,\n\t\t\tint\t\t\t\t\tpackedLight,\n\t\t\tboolean\t\t\t\tbidirectional,\n\t\t\tOperation<Integer>\toriginal\n\t) {\n\t\tif (!CoreFeature.isGuiBatching()) {\n\t\t\treturn original.call(\n\t\t\t\t\ttext,\n\t\t\t\t\ttextX,\n\t\t\t\t\ttextY,\n\t\t\t\t\ttextColor,\n\t\t\t\t\tdropShadow,\n\t\t\t\t\ttransform,\n\t\t\t\t\tbufferSource,\n\t\t\t\t\tdisplayMode,\n\t\t\t\t\tbackgroundColor,\n\t\t\t\t\tpackedLight,\n\t\t\t\t\tbidirectional\n\t\t\t);\n\t\t}\n\n\t\tGuiBatchingController.INSTANCE.submitString(new RawStringDrawContext(\n\t\t\t\tnew Matrix4f(transform),\n\t\t\t\t(Font) (Object) this,\n\t\t\t\ttext,\n\t\t\t\ttextX,\n\t\t\t\ttextY,\n\t\t\t\ttextColor,\n\t\t\t\tdropShadow,\n\t\t\t\tdisplayMode,\n\t\t\t\tbackgroundColor,\n\t\t\t\tpackedLight,\n\t\t\t\tbidirectional\n\t\t));\n\n\t\treturn 0;\n\t}\n\n\t@WrapMethod(method = \"drawInBatch(Lnet/minecraft/network/chat/Component;FFIZLorg/joml/Matrix4f;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/client/gui/Font$DisplayMode;II)I\")\n\tpublic int renderGuiStringFast3(\n\t\t\tComponent\t\t\ttext,\n\t\t\tfloat\t\t\t\ttextX,\n\t\t\tfloat\t\t\t\ttextY,\n\t\t\tint\t\t\t\t\ttextColor,\n\t\t\tboolean\t\t\t\tdropShadow,\n\t\t\tMatrix4f\t\t\ttransform,\n\t\t\tMultiBufferSource\tbufferSource,\n\t\t\tFont.DisplayMode\tdisplayMode,\n\t\t\tint\t\t\t\t\tbackgroundColor,\n\t\t\tint\t\t\t\t\tpackedLight,\n\t\t\tOperation<Integer>\toriginal\n\t) {\n\t\tif (!CoreFeature.isGuiBatching()) {\n\t\t\treturn original.call(\n\t\t\t\t\ttext,\n\t\t\t\t\ttextX,\n\t\t\t\t\ttextY,\n\t\t\t\t\ttextColor,\n\t\t\t\t\tdropShadow,\n\t\t\t\t\ttransform,\n\t\t\t\t\tbufferSource,\n\t\t\t\t\tdisplayMode,\n\t\t\t\t\tbackgroundColor,\n\t\t\t\t\tpackedLight\n\t\t\t);\n\t\t}\n\n\t\tGuiBatchingController.INSTANCE.submitString(new ComponentStringDrawContext(\n\t\t\t\tnew Matrix4f(transform),\n\t\t\t\t(Font) (Object) this,\n\t\t\t\ttext,\n\t\t\t\ttextX,\n\t\t\t\ttextY,\n\t\t\t\ttextColor,\n\t\t\t\tdropShadow,\n\t\t\t\tdisplayMode,\n\t\t\t\tbackgroundColor,\n\t\t\t\tpackedLight\n\t\t));\n\n\t\treturn 0;\n\t}\n\n\t@WrapMethod(method = \"drawInBatch(Lnet/minecraft/util/FormattedCharSequence;FFIZLorg/joml/Matrix4f;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/client/gui/Font$DisplayMode;II)I\")\n\tpublic int renderGuiStringFast4(\n\t\t\tFormattedCharSequence\ttext,\n\t\t\tfloat\t\t\t\t\ttextX,\n\t\t\tfloat\t\t\t\t\ttextY,\n\t\t\tint\t\t\t\t\t\ttextColor,\n\t\t\tboolean\t\t\t\t\tdropShadow,\n\t\t\tMatrix4f\t\t\t\ttransform,\n\t\t\tMultiBufferSource\t\tbufferSource,\n\t\t\tFont.DisplayMode\t\tdisplayMode,\n\t\t\tint\t\t\t\t\t\tbackgroundColor,\n\t\t\tint\t\t\t\t\t\tpackedLight,\n\t\t\tOperation<Integer>\t\toriginal\n\t) {\n\t\tif (!CoreFeature.isGuiBatching()) {\n\t\t\treturn original.call(\n\t\t\t\t\ttext,\n\t\t\t\t\ttextX,\n\t\t\t\t\ttextY,\n\t\t\t\t\ttextColor,\n\t\t\t\t\tdropShadow,\n\t\t\t\t\ttransform,\n\t\t\t\t\tbufferSource,\n\t\t\t\t\tdisplayMode,\n\t\t\t\t\tbackgroundColor,\n\t\t\t\t\tpackedLight\n\t\t\t);\n\t\t}\n\n\t\tGuiBatchingController.INSTANCE.submitString(new FormattedStringDrawContext(\n\t\t\t\tnew Matrix4f(transform),\n\t\t\t\t(Font) (Object) this,\n\t\t\t\ttext,\n\t\t\t\ttextX,\n\t\t\t\ttextY,\n\t\t\t\ttextColor,\n\t\t\t\tdropShadow,\n\t\t\t\tdisplayMode,\n\t\t\t\tbackgroundColor,\n\t\t\t\tpackedLight\n\t\t));\n\n\t\treturn 0;\n\t}\n\n\t@WrapMethod(method = \"drawInBatch8xOutline\")\n\tpublic void renderGuiStringFast5(\n\t\t\tFormattedCharSequence\ttext,\n\t\t\tfloat\t\t\t\t\ttextX,\n\t\t\tfloat\t\t\t\t\ttextY,\n\t\t\tint\t\t\t\t\t\ttextColor,\n\t\t\tint\t\t\t\t\t\tbackgroundColor,\n\t\t\tMatrix4f\t\t\t\ttransform,\n\t\t\tMultiBufferSource\t\tbufferSource,\n\t\t\tint\t\t\t\t\t\tpackedLight,\n\t\t\tOperation<Integer>\t\toriginal\n\t) {\n\t\tif (!CoreFeature.isGuiBatching()) {\n\t\t\toriginal.call(\n\t\t\t\t\ttext,\n\t\t\t\t\ttextX,\n\t\t\t\t\ttextY,\n\t\t\t\t\ttextColor,\n\t\t\t\t\tbackgroundColor,\n\t\t\t\t\ttransform,\n\t\t\t\t\tbufferSource,\n\t\t\t\t\tpackedLight\n\t\t\t);\n\n\t\t\treturn;\n\t\t}\n\n\t\tGuiBatchingController.INSTANCE.submitString(new Outline8StringDrawContext(\n\t\t\t\tnew Matrix4f(transform),\n\t\t\t\t(Font) (Object) this,\n\t\t\t\ttext,\n\t\t\t\ttextX,\n\t\t\t\ttextY,\n\t\t\t\ttextColor,\n\t\t\t\tbackgroundColor,\n\t\t\t\tpackedLight\n\t\t));\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/gui/GuiGraphicsMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.mixins.gui;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.items.gui.GuiBatchingController;\nimport com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport net.minecraft.client.gui.Font;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.renderer.MultiBufferSource;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.client.renderer.entity.ItemRenderer;\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.util.FastColor;\nimport net.minecraft.world.item.ItemDisplayContext;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.client.ItemDecoratorHandler;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.injection.At;\n\n\n@Mixin(GuiGraphics.class)\npublic class GuiGraphicsMixin {\n\n\t@Shadow @Final private PoseStack pose;\n\n\t@WrapMethod(method\t= \"fill(IIIII)V\")\n\tpublic void renderFillFast(\n\t\t\tint\t\t\t\tminX,\n\t\t\tint\t\t\t\tminY,\n\t\t\tint\t\t\t\tmaxX,\n\t\t\tint\t\t\t\tmaxY,\n\t\t\tint\t\t\t\tcolor,\n\t\t\tOperation<Void>\toriginal\n\t) {\n\t\tif (!CoreFeature.isGuiBatching()) {\n\t\t\toriginal.call(\n\t\t\t\t\tminX,\n\t\t\t\t\tminY,\n\t\t\t\t\tmaxX,\n\t\t\t\t\tmaxY,\n\t\t\t\t\tcolor\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tvar last = pose.last();\n\n\t\tGuiBatchingController.INSTANCE.submitFill(\n\t\t\t\tlast\t\t.pose\t(),\n\t\t\t\tlast\t\t.normal\t(),\n\t\t\t\tRenderType\t.gui\t(),\n\t\t\t\tminX,\n\t\t\t\tminY,\n\t\t\t\tmaxX,\n\t\t\t\tmaxY,\n\t\t\t\t-1,\n\t\t\t\tcolor\n\t\t);\n\t}\n\n\t@WrapMethod(method\t= \"fill(Lnet/minecraft/client/renderer/RenderType;IIIIII)V\")\n\tpublic void renderFillFast(\n\t\t\tRenderType\t\trenderType,\n\t\t\tint\t\t\t\tminX,\n\t\t\tint\t\t\t\tminY,\n\t\t\tint\t\t\t\tmaxX,\n\t\t\tint\t\t\t\tmaxY,\n\t\t\tint\t\t\t\tblitOffset,\n\t\t\tint\t\t\t\tcolor,\n\t\t\tOperation<Void>\toriginal\n\t) {\n\t\tif (!CoreFeature.isGuiBatching()) {\n\t\t\toriginal.call(\n\t\t\t\t\trenderType,\n\t\t\t\t\tminX,\n\t\t\t\t\tminY,\n\t\t\t\t\tmaxX,\n\t\t\t\t\tmaxY,\n\t\t\t\t\tblitOffset,\n\t\t\t\t\tcolor\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tvar last = pose.last();\n\n\t\tGuiBatchingController.INSTANCE.submitFill(\n\t\t\t\tlast.pose\t(),\n\t\t\t\tlast.normal\t(),\n\t\t\t\trenderType,\n\t\t\t\tminX,\n\t\t\t\tminY,\n\t\t\t\tmaxX,\n\t\t\t\tmaxY,\n\t\t\t\tblitOffset,\n\t\t\t\tcolor\n\t\t);\n\t}\n\n\t@WrapMethod(method = \"fillGradient(Lnet/minecraft/client/renderer/RenderType;IIIIIII)V\")\n\tpublic void renderGradientFast(\n\t\t\tRenderType\t\trenderType,\n\t\t\tint\t\t\t\tminX,\n\t\t\tint\t\t\t\tminY,\n\t\t\tint\t\t\t\tmaxX,\n\t\t\tint\t\t\t\tmaxY,\n\t\t\tint\t\t\t\tcolorFrom,\n\t\t\tint\t\t\t\tcolorTo,\n\t\t\tint\t\t\t\tblitOffset,\n\t\t\tOperation<Void>\toriginal\n\t) {\n\t\tif (!CoreFeature.isGuiBatching()) {\n\t\t\toriginal.call(\n\t\t\t\t\trenderType,\n\t\t\t\t\tminX,\n\t\t\t\t\tminY,\n\t\t\t\t\tmaxX,\n\t\t\t\t\tmaxY,\n\t\t\t\t\tcolorFrom,\n\t\t\t\t\tcolorTo,\n\t\t\t\t\tblitOffset\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tvar last = pose.last();\n\n\t\tGuiBatchingController.INSTANCE.submitGradient(\n\t\t\t\tlast.pose\t(),\n\t\t\t\tlast.normal\t(),\n\t\t\t\trenderType,\n\t\t\t\tminX,\n\t\t\t\tminY,\n\t\t\t\tmaxX,\n\t\t\t\tmaxY,\n\t\t\t\tblitOffset,\n\t\t\t\tcolorFrom,\n\t\t\t\tcolorTo\n\t\t);\n\t}\n\n\t@WrapMethod(method = \"fillRenderType\")\n\tpublic void renderRenderTypeFast(\n\t\t\tRenderType\t\trenderType,\n\t\t\tint\t\t\t\tminX,\n\t\t\tint\t\t\t\tminY,\n\t\t\tint\t\t\t\tmaxX,\n\t\t\tint\t\t\t\tmaxY,\n\t\t\tint\t\t\t\tblitOffset,\n\t\t\tOperation<Void>\toriginal\n\t) {\n\t\tif (!CoreFeature.isGuiBatching()) {\n\t\t\toriginal.call(\n\t\t\t\t\trenderType,\n\t\t\t\t\tminX,\n\t\t\t\t\tminY,\n\t\t\t\t\tmaxX,\n\t\t\t\t\tmaxY,\n\t\t\t\t\tblitOffset\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tvar last = pose.last();\n\n\t\tGuiBatchingController.INSTANCE.submitGradient(\n\t\t\t\tlast.pose\t(),\n\t\t\t\tlast.normal\t(),\n\t\t\t\trenderType,\n\t\t\t\tminX,\n\t\t\t\tminY,\n\t\t\t\tmaxX,\n\t\t\t\tmaxY,\n\t\t\t\tblitOffset,\n\t\t\t\t-1,\n\t\t\t\t-1\n\t\t);\n\t}\n\n\t@WrapMethod(method = \"innerBlit(Lnet/minecraft/resources/ResourceLocation;IIIIIFFFF)V\")\n\tpublic void renderBlitFast(\n\t\t\tResourceLocation atlasLocation,\n\t\t\tint\t\t\t\t\tminX,\n\t\t\tint\t\t\t\t\tmaxX,\n\t\t\tint\t\t\t\t\tminY,\n\t\t\tint\t\t\t\t\tmaxY,\n\t\t\tint\t\t\t\t\tblitOffset,\n\t\t\tfloat\t\t\t\tminU,\n\t\t\tfloat\t\t\t\tmaxU,\n\t\t\tfloat\t\t\t\tminV,\n\t\t\tfloat\t\t\t\tmaxV,\n\t\t\tOperation<Void>\t\toriginal\n\t) {\n\t\tif (!CoreFeature.isGuiBatching()) {\n\t\t\toriginal.call(\n\t\t\t\t\tatlasLocation,\n\t\t\t\t\tminX,\n\t\t\t\t\tmaxX,\n\t\t\t\t\tminY,\n\t\t\t\t\tmaxY,\n\t\t\t\t\tblitOffset,\n\t\t\t\t\tminU,\n\t\t\t\t\tmaxU,\n\t\t\t\t\tminV,\n\t\t\t\t\tmaxV\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tvar last = pose.last();\n\n\t\tGuiBatchingController.INSTANCE.submitBlit(\n\t\t\t\tlast.pose\t(),\n\t\t\t\tlast.normal\t(),\n\t\t\t\tatlasLocation,\n\t\t\t\tminX,\n\t\t\t\tmaxX,\n\t\t\t\tminY,\n\t\t\t\tmaxY,\n\t\t\t\tblitOffset,\n\t\t\t\t-1,\n\t\t\t\tminU,\n\t\t\t\tmaxU,\n\t\t\t\tminV,\n\t\t\t\tmaxV\n\t\t);\n\t}\n\n\t@WrapMethod(method = \"innerBlit(Lnet/minecraft/resources/ResourceLocation;IIIIIFFFFFFFF)V\")\n\tpublic void renderBlitFast(\n\t\t\tResourceLocation\tatlasLocation,\n\t\t\tint\t\t\t\t\tminX,\n\t\t\tint\t\t\t\t\tmaxX,\n\t\t\tint\t\t\t\t\tminY,\n\t\t\tint\t\t\t\t\tmaxY,\n\t\t\tint\t\t\t\t\tblitOffset,\n\t\t\tfloat\t\t\t\tminU,\n\t\t\tfloat\t\t\t\tmaxU,\n\t\t\tfloat\t\t\t\tminV,\n\t\t\tfloat\t\t\t\tmaxV,\n\t\t\tfloat\t\t\t\tred,\n\t\t\tfloat\t\t\t\tgreen,\n\t\t\tfloat\t\t\t\tblue,\n\t\t\tfloat\t\t\t\talpha,\n\t\t\tOperation<Void>\t\toriginal\n\t) {\n\t\tif (!CoreFeature.isGuiBatching()) {\n\t\t\toriginal.call(\n\t\t\t\t\tatlasLocation,\n\t\t\t\t\tminX,\n\t\t\t\t\tmaxX,\n\t\t\t\t\tminY,\n\t\t\t\t\tmaxY,\n\t\t\t\t\tblitOffset,\n\t\t\t\t\tminU,\n\t\t\t\t\tmaxU,\n\t\t\t\t\tminV,\n\t\t\t\t\tmaxV,\n\t\t\t\t\tred,\n\t\t\t\t\tgreen,\n\t\t\t\t\tblue,\n\t\t\t\t\talpha\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tvar last = pose.last();\n\n\t\tGuiBatchingController.INSTANCE.submitBlit(\n\t\t\t\tlast.pose\t(),\n\t\t\t\tlast.normal\t(),\n\t\t\t\tatlasLocation,\n\t\t\t\tminX,\n\t\t\t\tmaxX,\n\t\t\t\tminY,\n\t\t\t\tmaxY,\n\t\t\t\tblitOffset,\n\t\t\t\tFastColor.ARGB32.color(\n\t\t\t\t\t\t(int) (alpha\t* 255.0f),\n\t\t\t\t\t\t(int) (red\t\t* 255.0f),\n\t\t\t\t\t\t(int) (green\t* 255.0f),\n\t\t\t\t\t\t(int) (blue\t\t* 255.0f)\n\t\t\t\t),\n\t\t\t\tminU,\n\t\t\t\tmaxU,\n\t\t\t\tminV,\n\t\t\t\tmaxV\n\t\t);\n\t}\n\n\t@SuppressWarnings\t(\"UnstableApiUsage\")\n\t@WrapOperation\t\t(\n\t\t\tmethod\t= \"renderItemDecorations(Lnet/minecraft/client/gui/Font;Lnet/minecraft/world/item/ItemStack;IILjava/lang/String;)V\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/neoforged/neoforge/client/ItemDecoratorHandler;render(Lnet/minecraft/client/gui/GuiGraphics;Lnet/minecraft/client/gui/Font;Lnet/minecraft/world/item/ItemStack;II)V\"\n\t\t\t)\n\t)\n\tpublic void renderDecorationCustomFast(\n\t\t\tItemDecoratorHandler\tinstance,\n\t\t\tGuiGraphics\t\t\t\tguiGraphics,\n\t\t\tFont\t\t\t\t\tfont,\n\t\t\tItemStack\t\t\t\tstack,\n\t\t\tint\t\t\t\t\t\txOffset,\n\t\t\tint\t\t\t\t\t\tyOffset,\n\t\t\tOperation<Void>\t\t\toriginal\n\t) {\n\t\tif (!CoreFeature.isGuiBatching()) {\n\t\t\toriginal.call(\n\t\t\t\t\tinstance,\n\t\t\t\t\tguiGraphics,\n\t\t\t\t\tfont,\n\t\t\t\t\tstack,\n\t\t\t\t\txOffset,\n\t\t\t\t\tyOffset\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tvar last = pose.last();\n\n\t\tGuiBatchingController.INSTANCE.submitCustomDecorator(\n\t\t\t\tlast.pose\t(),\n\t\t\t\tlast.normal\t(),\n\t\t\t\tinstance,\n\t\t\t\tfont,\n\t\t\t\tstack,\n\t\t\t\txOffset,\n\t\t\t\tyOffset\n\t\t);\n\t}\n\n\t@WrapOperation(\n\t\t\tmethod\t= \"renderItem(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;IIII)V\",\n\t\t\tat\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lnet/minecraft/client/renderer/entity/ItemRenderer;render(Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemDisplayContext;ZLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;IILnet/minecraft/client/resources/model/BakedModel;)V\"\n\t\t\t)\n\t)\n\tpublic void renderItemFast(\n\t\t\tItemRenderer\t\tinstance,\n\t\t\tItemStack\t\t\titemStack,\n\t\t\tItemDisplayContext\tdisplayContext,\n\t\t\tboolean\t\t\t\tleftHand,\n\t\t\tPoseStack\t\t\tposeStack,\n\t\t\tMultiBufferSource\tbufferSource,\n\t\t\tint\t\t\t\t\tcombinedLight,\n\t\t\tint\t\t\t\t\tcombinedOverlay,\n\t\t\tBakedModel\t\t\tbakedModel,\n\t\t\tOperation<Void>\t\toriginal\n\t) {\n\t\tif (\t\t!AcceleratedItemRenderingFeature.isEnabled\t\t\t\t\t\t()\n\t\t\t\t||\t!AcceleratedItemRenderingFeature.shouldUseAcceleratedPipeline\t()\n\t\t\t\t||\t!AcceleratedItemRenderingFeature.shouldAccelerateInGui\t\t\t()\n\t\t\t\t||\t!CoreFeature\t\t\t\t\t.isLoaded\t\t\t\t\t\t()\n\t\t) {\n\t\t\toriginal.call(\n\t\t\t\t\tinstance,\n\t\t\t\t\titemStack,\n\t\t\t\t\tdisplayContext,\n\t\t\t\t\tleftHand,\n\t\t\t\t\tposeStack,\n\t\t\t\t\tbufferSource,\n\t\t\t\t\tcombinedLight,\n\t\t\t\t\tcombinedOverlay,\n\t\t\t\t\tbakedModel\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (CoreFeature.isGuiBatching()) {\n\t\t\tvar last = pose.last();\n\n\t\t\tGuiBatchingController.INSTANCE.submitItem(\n\t\t\t\t\tlast.pose\t(),\n\t\t\t\t\tlast.normal\t(),\n\t\t\t\t\titemStack,\n\t\t\t\t\tdisplayContext,\n\t\t\t\t\tleftHand,\n\t\t\t\t\tcombinedLight,\n\t\t\t\t\tcombinedOverlay,\n\t\t\t\t\tbakedModel,\n\t\t\t\t\tbakedModel.usesBlockLight()\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tCoreFeature.setRenderingGui();\n\n\t\toriginal.call(\n\t\t\t\tinstance,\n\t\t\t\titemStack,\n\t\t\t\tdisplayContext,\n\t\t\t\tleftHand,\n\t\t\t\tposeStack,\n\t\t\t\tbufferSource,\n\t\t\t\tcombinedLight,\n\t\t\t\tcombinedOverlay,\n\t\t\t\tbakedModel\n\t\t);\n\n\t\tCoreFeature\t\t\t\t\t\t.resetRenderingGui\t();\n\t\tGuiBatchingController.INSTANCE\t.flushBatching\t\t();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/gui/GuiMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.mixins.gui;\n\nimport com.github.argon4w.acceleratedrendering.features.items.gui.GuiBatchingController;\nimport net.minecraft.client.DeltaTracker;\nimport net.minecraft.client.gui.Gui;\nimport net.minecraft.client.gui.GuiGraphics;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@Mixin(Gui.class)\npublic class GuiMixin {\n\n\t@Inject(\n\t\t\tmethod\t= \"renderItemHotbar\",\n\t\t\tat\t\t= @At(\"HEAD\")\n\t)\n\tpublic void startBatching(\n\t\t\tGuiGraphics\t\tguiGraphics,\n\t\t\tDeltaTracker\tdeltaTracker,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tGuiBatchingController.INSTANCE.startBatching(guiGraphics);\n\t}\n\n\t@Inject(\n\t\t\tmethod\t= \"renderItemHotbar\",\n\t\t\tat\t\t= @At(\"TAIL\")\n\t)\n\tpublic void flushBatching(\n\t\t\tGuiGraphics\t\tguiGraphics,\n\t\t\tDeltaTracker\tdeltaTracker,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tGuiBatchingController.INSTANCE.flushBatching(guiGraphics);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/models/BakedCompositeModelMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.mixins.models;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.features.items.BakedModelExtension;\nimport com.github.argon4w.acceleratedrendering.features.items.IAcceleratedBakedModel;\nimport com.google.common.collect.ImmutableList;\nimport com.google.common.collect.ImmutableMap;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport lombok.Getter;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.client.renderer.block.model.ItemOverrides;\nimport net.minecraft.client.renderer.block.model.ItemTransforms;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.util.RandomSource;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.CompositeModel;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.Unique;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@Getter\n@ExtensionMethod(BakedModelExtension\t.class)\n@Mixin\t\t\t(CompositeModel.Baked\t.class)\npublic class BakedCompositeModelMixin implements IAcceleratedBakedModel {\n\n\t@Shadow @Final private\tImmutableMap<String, BakedModel>\tchildren;\n\t@Unique private\t\t\tboolean\t\t\t\t\t\t\t\taccelerated;\n\t@Unique private\t\t\tboolean\t\t\t\t\t\t\t\tacceleratedInHand;\n\t@Unique private\t\t\tboolean\t\t\t\t\t\t\t\tacceleratedInGui;\n\n\t@Inject(\n\t\t\tmethod\t= \"<init>\",\n\t\t\tat\t\t= @At(\"TAIL\")\n\t)\n\tpublic void checkAccelerationSupport(\n\t\t\tboolean\t\t\t\t\t\t\t\tisGui3d,\n\t\t\tboolean\t\t\t\t\t\t\t\tisSideLit,\n\t\t\tboolean\t\t\t\t\t\t\t\tisAmbientOcclusion,\n\t\t\tTextureAtlasSprite\t\t\t\t\tparticle,\n\t\t\tItemTransforms\t\t\t\t\t\ttransforms,\n\t\t\tItemOverrides\t\t\t\t\t\toverrides,\n\t\t\tImmutableMap<String, BakedModel>\tchildren,\n\t\t\tImmutableList<BakedModel>\t\t\titemPasses,\n\t\t\tCallbackInfo\t\t\t\t\t\tci\n\t) {\n\t\taccelerated\t\t\t= true;\n\t\tacceleratedInHand\t= true;\n\t\tacceleratedInGui\t= true;\n\n\t\tfor (BakedModel childModel : children.values()) {\n\t\t\tvar extension = childModel.getAccelerated();\n\n\t\t\taccelerated\t\t\t&= extension.isAccelerated\t\t();\n\t\t\tacceleratedInHand\t&= extension.isAcceleratedInHand();\n\t\t\tacceleratedInGui\t&= extension.isAcceleratedInGui\t();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void renderItemFast(\n\t\t\tItemStack\t\t\t\t\titemStack,\n\t\t\tRandomSource\t\t\t\trandom,\n\t\t\tPoseStack.Pose\t\t\t\tpose,\n\t\t\tIAcceleratedVertexConsumer\textension,\n\t\t\tint\t\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\t\toverlay\n\t) {\n\t\tfor (BakedModel child : children.values()) {\n\t\t\tchild\n\t\t\t\t\t.getAccelerated\t()\n\t\t\t\t\t.renderItemFast(\n\t\t\t\t\t\t\titemStack,\n\t\t\t\t\t\t\trandom,\n\t\t\t\t\t\t\tpose,\n\t\t\t\t\t\t\textension,\n\t\t\t\t\t\t\tlight,\n\t\t\t\t\t\t\toverlay\n\t\t\t\t\t);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void renderBlockFast(\n\t\t\tBlockState\t\t\t\t\tblockState,\n\t\t\tRandomSource\t\t\t\trandom,\n\t\t\tPoseStack.Pose\t\t\t\tpose,\n\t\t\tIAcceleratedVertexConsumer\textension,\n\t\t\tint\t\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\t\t\tcolor,\n\t\t\tModelData\t\t\t\t\tdata,\n\t\t\tRenderType\t\t\t\t\trenderType\n\t) {\n\t\tfor (BakedModel child : children.values()) {\n\t\t\tvar renderTypeSet = blockState == null ? null : child.getRenderTypes(\n\t\t\t\t\tblockState,\n\t\t\t\t\trandom,\n\t\t\t\t\tdata\n\t\t\t);\n\n\t\t\tif (\t\t\trenderType\t\t== null\n\t\t\t\t\t||\t(\trenderTypeSet\t!= null\n\t\t\t\t\t&&\t\trenderTypeSet.contains(renderType))\n\t\t\t) {\n\t\t\t\tchild\n\t\t\t\t\t\t.getAccelerated\t()\n\t\t\t\t\t\t.renderBlockFast(\n\t\t\t\t\t\t\t\tblockState,\n\t\t\t\t\t\t\t\trandom,\n\t\t\t\t\t\t\t\tpose,\n\t\t\t\t\t\t\t\textension,\n\t\t\t\t\t\t\t\tlight,\n\t\t\t\t\t\t\t\toverlay,\n\t\t\t\t\t\t\t\tgetCustomColor(-1, color),\n\t\t\t\t\t\t\t\tdata,\n\t\t\t\t\t\t\t\trenderType\n\t\t\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic int getCustomColor(int layer, int color) {\n\t\treturn color;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/models/BakedModelMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.mixins.models;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.features.items.IAcceleratedBakedModel;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.util.RandomSource;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Unique;\n\n@Mixin(BakedModel.class)\npublic interface BakedModelMixin extends IAcceleratedBakedModel {\n\n\t@Unique\n\t@Override\n\tdefault void renderItemFast(\n\t\t\tItemStack\t\t\t\t\titemStack,\n\t\t\tRandomSource\t\t\t\trandom,\n\t\t\tPoseStack.Pose\t\t\t\tpose,\n\t\t\tIAcceleratedVertexConsumer\tvertexConsumer,\n\t\t\tint\t\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\t\toverlay\n\t) {\n\t\tthrow new UnsupportedOperationException(\"Unsupported Operation.\");\n\t}\n\n\t@Unique\n\t@Override\n\tdefault void renderBlockFast(\n\t\t\tBlockState\t\t\t\t\tstate,\n\t\t\tRandomSource\t\t\t\trandom,\n\t\t\tPoseStack.Pose\t\t\t\tpose,\n\t\t\tIAcceleratedVertexConsumer\textension,\n\t\t\tint\t\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\t\t\tcolor,\n\t\t\tModelData\t\t\t\t\tdata,\n\t\t\tRenderType\t\t\t\t\trenderType\n\t) {\n\t\tthrow new UnsupportedOperationException(\"Unsupported Operation.\");\n\t}\n\n\t@Unique\n\t@Override\n\tdefault boolean isAccelerated() {\n\t\treturn false;\n\t}\n\n\t@Unique\n\t@Override\n\tdefault boolean isAcceleratedInHand() {\n\t\treturn false;\n\t}\n\n\t@Unique\n\t@Override\n\tdefault boolean isAcceleratedInGui() {\n\t\treturn false;\n\t}\n\n\t@Unique\n\t@Override\n\tdefault int getCustomColor(int layer, int color) {\n\t\treturn color;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/models/BakedQuadMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.mixins.models;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IBufferGraph;\nimport com.github.argon4w.acceleratedrendering.core.meshes.IMesh;\nimport com.github.argon4w.acceleratedrendering.core.meshes.collectors.CulledMeshCollector;\nimport com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData;\nimport com.github.argon4w.acceleratedrendering.core.utils.FastColorUtils;\nimport com.github.argon4w.acceleratedrendering.core.utils.IntArrayHashStrategy;\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.items.IAcceleratedBakedQuad;\nimport it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap;\nimport it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.neoforged.neoforge.client.model.IQuadTransformer;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.Unique;\n\nimport java.util.Map;\n\n@Mixin(BakedQuad.class)\npublic abstract class BakedQuadMixin implements IAcceleratedBakedQuad {\n\n\t@Unique private static final\tMap<int[], Map<IBufferGraph,\tIMesh>>\tMESHES = new Object2ObjectOpenCustomHashMap<>(IntArrayHashStrategy.INSTANCE);\n\t@Unique private static final\tMap<int[], Map<MeshData,\t\tIMesh>>\tMERGES = new Object2ObjectOpenCustomHashMap<>(IntArrayHashStrategy.INSTANCE);\n\n\t@Shadow @Final protected\t\tint[]\t\t\t\t\t\t\t\t\tvertices;\n\n\t@Shadow public abstract\t\t\tboolean\t\t\t\t\t\t\t\t\tisTinted();\n\n\t@Unique\n\t@Override\n\tpublic void renderFast(\n\t\t\tMatrix4f\t\t\t\t\ttransform,\n\t\t\tMatrix3f\t\t\t\t\tnormal,\n\t\t\tIAcceleratedVertexConsumer\textension,\n\t\t\tint\t\t\t\t\t\t\tcombinedLight,\n\t\t\tint\t\t\t\t\t\t\tcombinedOverlay,\n\t\t\tint\t\t\t\t\t\t\tcolor\n\t) {\n\t\tvar meshes = MESHES.get(vertices);\n\t\tvar merges = MERGES.get(vertices);\n\n\t\tif (meshes == null) {\n\t\t\tmeshes = new Object2ObjectOpenHashMap<>\t();\n\t\t\tmerges = new Object2ObjectOpenHashMap<>\t();\n\t\t\tMESHES.put\t\t\t\t\t\t\t\t(vertices, meshes);\n\t\t\tMERGES.put\t\t\t\t\t\t\t\t(vertices, merges);\n\t\t}\n\n\t\tvar mesh = meshes.get(extension);\n\n\t\tif (mesh != null) {\n\t\t\tmesh.write(\n\t\t\t\t\textension,\n\t\t\t\t\tgetCustomColor(color),\n\t\t\t\t\tcombinedLight,\n\t\t\t\t\tcombinedOverlay\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tvar culledMeshCollector\t= new CulledMeshCollector\t(extension);\n\t\tvar meshBuilder\t\t\t= extension.decorate\t\t(culledMeshCollector);\n\n\t\tfor (var i = 0; i < vertices.length / 8; i++) {\n\t\t\tvar vertexOffset\t= i\t\t\t\t* IQuadTransformer.STRIDE;\n\t\t\tvar posOffset\t\t= vertexOffset\t+ IQuadTransformer.POSITION;\n\t\t\tvar colorOffset\t\t= vertexOffset\t+ IQuadTransformer.COLOR;\n\t\t\tvar uv0Offset\t\t= vertexOffset\t+ IQuadTransformer.UV0;\n\t\t\tvar uv2Offset\t\t= vertexOffset\t+ IQuadTransformer.UV2;\n\t\t\tvar normalOffset\t= vertexOffset\t+ IQuadTransformer.NORMAL;\n\t\t\tvar packedNormal\t= vertices[normalOffset];\n\n\t\t\tmeshBuilder.addVertex(\n\t\t\t\t\tFloat\t\t\t.intBitsToFloat\t(vertices[posOffset + 0]),\n\t\t\t\t\tFloat\t\t\t.intBitsToFloat\t(vertices[posOffset + 1]),\n\t\t\t\t\tFloat\t\t\t.intBitsToFloat\t(vertices[posOffset + 2]),\n\t\t\t\t\tFastColorUtils\t.convert\t\t(vertices[colorOffset]),\n\t\t\t\t\tFloat\t\t\t.intBitsToFloat\t(vertices[uv0Offset + 0]),\n\t\t\t\t\tFloat\t\t\t.intBitsToFloat\t(vertices[uv0Offset + 1]),\n\t\t\t\t\tcombinedOverlay,\n\t\t\t\t\tvertices[uv2Offset],\n\t\t\t\t\t((byte) (\tpackedNormal\t\t& 0xFF)) / 127.0f,\n\t\t\t\t\t((byte) ((\tpackedNormal >> 8)\t& 0xFF)) / 127.0f,\n\t\t\t\t\t((byte) ((\tpackedNormal >> 16)\t& 0xFF)) / 127.0f\n\t\t\t);\n\t\t}\n\n\t\tculledMeshCollector.flush();\n\n\t\tvar data\t= culledMeshCollector\t.getData\t();\n\t\tvar buffer\t= culledMeshCollector\t.getBuffer\t();\n\t\tmesh\t\t= merges\t\t\t\t.get\t\t(data);\n\n\t\tif (mesh != null) {\n\t\t\tbuffer.discard\t();\n\t\t\tbuffer.close\t();\n\t\t} else {\n\t\t\tmesh = AcceleratedEntityRenderingFeature\n\t\t\t\t\t.getMeshType()\n\t\t\t\t\t.getBuilder\t()\n\t\t\t\t\t.build\t\t(culledMeshCollector);\n\t\t}\n\n\t\tmeshes\t.put\t(extension, mesh);\n\t\tmerges\t.put\t(data,\t\tmesh);\n\t\tmesh\t.write\t(\n\t\t\t\textension,\n\t\t\t\tgetCustomColor(color),\n\t\t\t\tcombinedLight,\n\t\t\t\tcombinedOverlay\n\t\t);\n\t}\n\n\t@Unique\n\t@Override\n\tpublic int getCustomColor(int color) {\n\t\treturn isTinted() ? color : -1;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/models/BakedSeparateTransformsModelMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.mixins.models;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.features.items.BakedModelExtension;\nimport com.github.argon4w.acceleratedrendering.features.items.IAcceleratedBakedModel;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.util.RandomSource;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.SeparateTransformsModel;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\n\n@ExtensionMethod(BakedModelExtension\t\t\t.class)\n@Mixin\t\t\t(SeparateTransformsModel.Baked\t.class)\npublic class BakedSeparateTransformsModelMixin implements IAcceleratedBakedModel {\n\n\t@Shadow @Final private BakedModel baseModel;\n\n\t@Override\n\tpublic void renderItemFast(\n\t\t\tItemStack\t\t\t\t\titemStack,\n\t\t\tRandomSource\t\t\t\trandom,\n\t\t\tPoseStack.Pose\t\t\t\tpose,\n\t\t\tIAcceleratedVertexConsumer\textension,\n\t\t\tint\t\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\t\toverlay\n\t) {\n\t\tbaseModel\n\t\t\t\t.getAccelerated()\n\t\t\t\t.renderItemFast(\n\t\t\t\t\t\titemStack,\n\t\t\t\t\t\trandom,\n\t\t\t\t\t\tpose,\n\t\t\t\t\t\textension,\n\t\t\t\t\t\tlight,\n\t\t\t\t\t\toverlay\n\t\t\t\t);\n\t}\n\n\t@Override\n\tpublic void renderBlockFast(\n\t\t\tBlockState\t\t\t\t\tblockState,\n\t\t\tRandomSource\t\t\t\trandom,\n\t\t\tPoseStack.Pose\t\t\t\tpose,\n\t\t\tIAcceleratedVertexConsumer\textension,\n\t\t\tint\t\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\t\t\tcolor,\n\t\t\tModelData\t\t\t\t\tdata,\n\t\t\tRenderType\t\t\t\t\trenderType\n\t) {\n\t\tbaseModel\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.renderBlockFast(\n\t\t\t\t\t\tblockState,\n\t\t\t\t\t\trandom,\n\t\t\t\t\t\tpose,\n\t\t\t\t\t\textension,\n\t\t\t\t\t\tlight,\n\t\t\t\t\t\toverlay,\n\t\t\t\t\t\tcolor,\n\t\t\t\t\t\tdata,\n\t\t\t\t\t\trenderType\n\t\t\t\t);\n\t}\n\n\t@Override\n\tpublic int getCustomColor(int layer, int color) {\n\t\treturn baseModel\n\t\t\t\t.getAccelerated()\n\t\t\t\t.getCustomColor(layer, color);\n\t}\n\n\t@Override\n\tpublic boolean isAccelerated() {\n\t\treturn baseModel\n\t\t\t\t.getAccelerated\t()\n\t\t\t\t.isAccelerated\t();\n\t}\n\n\t@Override\n\tpublic boolean isAcceleratedInHand() {\n\t\treturn baseModel\n\t\t\t\t.getAccelerated\t\t()\n\t\t\t\t.isAcceleratedInHand();\n\t}\n\n\t@Override\n\tpublic boolean isAcceleratedInGui() {\n\t\treturn baseModel\n\t\t\t\t.getAccelerated\t\t()\n\t\t\t\t.isAcceleratedInGui\t();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/models/MultipartBakedModelMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.mixins.models;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.features.items.BakedModelExtension;\nimport com.github.argon4w.acceleratedrendering.features.items.IAcceleratedBakedModel;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport lombok.Getter;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.client.resources.model.MultiPartBakedModel;\nimport net.minecraft.util.RandomSource;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport org.apache.commons.lang3.tuple.Pair;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.Unique;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\nimport java.util.BitSet;\nimport java.util.List;\nimport java.util.function.Predicate;\n\n@Getter\n@ExtensionMethod(BakedModelExtension.class)\n@Mixin\t\t\t(MultiPartBakedModel.class)\npublic abstract class MultipartBakedModelMixin implements IAcceleratedBakedModel {\n\n\n\t@Unique private\t\t\tboolean\t\t\t\t\t\t\t\t\t\t\taccelerated;\n\t@Unique private\t\t\tboolean\t\t\t\t\t\t\t\t\t\t\tacceleratedInHand;\n\t@Unique private\t\t\tboolean\t\t\t\t\t\t\t\t\t\t\tacceleratedInGui;\n\n\t@Shadow @Final private\tList<Pair<Predicate<BlockState>, BakedModel>>\tselectors;\n\n\t@Shadow public abstract BitSet getSelectors(BlockState p_235050_);\n\n\n\t@Inject(\n\t\t\tmethod\t= \"<init>\",\n\t\t\tat\t\t= @At(\"TAIL\")\n\t)\n\tpublic void checkAccelerationSupport(List<Pair<Predicate<BlockState>, BakedModel>> selectors, CallbackInfo ci) {\n\t\taccelerated\t\t\t= true;\n\t\tacceleratedInHand\t= true;\n\t\tacceleratedInGui\t= true;\n\n\t\tfor (Pair<Predicate<BlockState>, BakedModel> selector : selectors) {\n\t\t\tvar extension = selector.getRight().getAccelerated();\n\n\t\t\taccelerated\t\t\t&= extension.isAccelerated\t\t();\n\t\t\tacceleratedInHand\t&= extension.isAcceleratedInHand();\n\t\t\tacceleratedInGui\t&= extension.isAcceleratedInGui\t();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void renderItemFast(\n\t\t\tItemStack\t\t\t\t\titemStack,\n\t\t\tRandomSource\t\t\t\trandom,\n\t\t\tPoseStack.Pose\t\t\t\tpose,\n\t\t\tIAcceleratedVertexConsumer\textension,\n\t\t\tint\t\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\t\toverlay\n\t) {\n\n\t}\n\n\t@Override\n\tpublic void renderBlockFast(\n\t\t\tBlockState\t\t\t\t\tblockState,\n\t\t\tRandomSource\t\t\t\trandom,\n\t\t\tPoseStack.Pose\t\t\t\tpose,\n\t\t\tIAcceleratedVertexConsumer\textension,\n\t\t\tint\t\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\t\t\tcolor,\n\t\t\tModelData\t\t\t\t\tdata,\n\t\t\tRenderType\t\t\t\t\trenderType\n\t) {\n\t\tif (blockState == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar bitset\t= getSelectors\t\t(blockState);\n\t\tvar seed\t= random.nextLong\t();\n\n\t\tfor (var j = 0; j < bitset.length(); j ++) {\n\t\t\tif (bitset.get(j)) {\n\t\t\t\tvar selector\t\t= selectors\t.get\t\t\t(j);\n\t\t\t\tvar selected\t\t= selector\t.getRight\t\t();\n\t\t\t\tvar renderTypeSet\t= selected\t.getRenderTypes\t(\n\t\t\t\t\t\tblockState,\n\t\t\t\t\t\trandom,\n\t\t\t\t\t\tdata\n\t\t\t\t);\n\n\t\t\t\tif (\t\trenderType == null\n\t\t\t\t\t\t||\trenderTypeSet.contains(renderType)\n\t\t\t\t) {\n\t\t\t\t\tselected\n\t\t\t\t\t\t\t.getAccelerated\t()\n\t\t\t\t\t\t\t.renderBlockFast(\n\t\t\t\t\t\t\t\t\tblockState,\n\t\t\t\t\t\t\t\t\tRandomSource.create(seed),\n\t\t\t\t\t\t\t\t\tpose,\n\t\t\t\t\t\t\t\t\textension,\n\t\t\t\t\t\t\t\t\tlight,\n\t\t\t\t\t\t\t\t\toverlay,\n\t\t\t\t\t\t\t\t\tgetCustomColor(-1, color),\n\t\t\t\t\t\t\t\t\tdata,\n\t\t\t\t\t\t\t\t\trenderType\n\t\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic int getCustomColor(int layer, int color) {\n\t\treturn color;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/models/SimpleBakedModelMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.mixins.models;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IBufferGraph;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.github.argon4w.acceleratedrendering.core.meshes.IMesh;\nimport com.github.argon4w.acceleratedrendering.core.meshes.collectors.CulledMeshCollector;\nimport com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData;\nimport com.github.argon4w.acceleratedrendering.core.utils.DirectionUtils;\nimport com.github.argon4w.acceleratedrendering.core.utils.FastColorUtils;\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.items.IAcceleratedBakedModel;\nimport com.github.argon4w.acceleratedrendering.features.items.colors.FixedColors;\nimport com.github.argon4w.acceleratedrendering.features.items.colors.ItemLayerColors;\nimport com.github.argon4w.acceleratedrendering.features.items.contexts.AcceleratedModelRenderContext;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap;\nimport it.unimi.dsi.fastutil.ints.Int2ObjectMap;\nimport it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;\nimport it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.minecraft.client.resources.model.SimpleBakedModel;\nimport net.minecraft.core.Direction;\nimport net.minecraft.util.RandomSource;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.IQuadTransformer;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.Unique;\n\nimport java.util.List;\nimport java.util.Map;\n\n@ExtensionMethod(VertexConsumerExtension.class)\n@Mixin\t\t\t(SimpleBakedModel\t\t.class)\npublic abstract class SimpleBakedModelMixin implements IAcceleratedBakedModel, IAcceleratedRenderer<AcceleratedModelRenderContext> {\n\n\t@Shadow public abstract List<BakedQuad> getQuads(BlockState pState, Direction pDirection, RandomSource pRandom);\n\n\t@Unique private final Map<IBufferGraph,\tInt2ObjectMap<IMesh>>\tmeshes = new Object2ObjectOpenHashMap<>();\n\t@Unique private final Map<MeshData,\t\tIMesh>\t\t\t\t\tmerges = new Object2ObjectOpenHashMap<>();\n\n\t@Unique\n\t@Override\n\tpublic void renderItemFast(\n\t\t\tItemStack\t\t\t\t\titemStack,\n\t\t\tRandomSource\t\t\t\trandom,\n\t\t\tPoseStack.Pose\t\t\t\tpose,\n\t\t\tIAcceleratedVertexConsumer\textension,\n\t\t\tint\t\t\t\t\t\t\tcombinedLight,\n\t\t\tint\t\t\t\t\t\t\tcombinedOverlay\n\t) {\n\t\textension.doRender(\n\t\t\t\tthis,\n\t\t\t\tnew AcceleratedModelRenderContext(random, new ItemLayerColors(itemStack)),\n\t\t\t\tpose.pose\t(),\n\t\t\t\tpose.normal\t(),\n\t\t\t\tcombinedLight,\n\t\t\t\tcombinedOverlay,\n\t\t\t\t-1\n\t\t);\n\t}\n\n\t@Override\n\tpublic void renderBlockFast(\n\t\t\tBlockState\t\t\t\t\tstate,\n\t\t\tRandomSource\t\t\t\trandom,\n\t\t\tPoseStack.Pose\t\t\t\tpose,\n\t\t\tIAcceleratedVertexConsumer\textension,\n\t\t\tint\t\t\t\t\t\t\tcombinedLight,\n\t\t\tint\t\t\t\t\t\t\tcombinedOverlay,\n\t\t\tint\t\t\t\t\t\t\tcolor,\n\t\t\tModelData\t\t\t\t\tdata,\n\t\t\tRenderType\t\t\t\t\trenderType\n\t) {\n\t\textension.doRender(\n\t\t\t\tthis,\n\t\t\t\tnew AcceleratedModelRenderContext(random, new FixedColors(color)),\n\t\t\t\tpose.pose\t(),\n\t\t\t\tpose.normal\t(),\n\t\t\t\tcombinedLight,\n\t\t\t\tcombinedOverlay,\n\t\t\t\t-1\n\t\t);\n\t}\n\n\t@Unique\n\t@Override\n\tpublic void render(\n\t\t\tVertexConsumer\t\t\t\t\tvertexConsumer,\n\t\t\tAcceleratedModelRenderContext\tcontext,\n\t\t\tMatrix4f\t\t\t\t\t\ttransform,\n\t\t\tMatrix3f\t\t\t\t\t\tnormal,\n\t\t\tint\t\t\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\t\t\t\tcolor\n\t) {\n\t\tvar extension\t\t= vertexConsumer.getAccelerated\t();\n\t\tvar randomSource\t= context\t\t.randomSource\t();\n\t\tvar layerColors\t\t= context\t\t.layerColors\t();\n\t\tvar layers\t\t\t= meshes\t\t.get\t\t\t(extension);\n\n\t\textension.beginTransform(transform, normal);\n\n\t\tif (layers != null) {\n\t\t\tfor (int layer : layers.keySet()) {\n\t\t\t\tvar mesh = layers.get(layer);\n\n\t\t\t\tmesh.write(\n\t\t\t\t\t\textension,\n\t\t\t\t\t\tgetCustomColor(layer, layerColors.getColor(layer)),\n\t\t\t\t\t\tlight,\n\t\t\t\t\t\toverlay\n\t\t\t\t);\n\t\t\t}\n\n\t\t\textension.endTransform();\n\t\t\treturn;\n\t\t}\n\n\t\tvar culledMeshCollectors\t= new Int2ObjectOpenHashMap\t<CulledMeshCollector>\t();\n\t\tlayers \t\t\t\t\t\t= new Int2ObjectAVLTreeMap\t<>\t\t\t\t\t\t();\n\n\t\tmeshes.put(extension, layers);\n\n\t\tfor (var direction : DirectionUtils.FULL) {\n\t\t\tfor (var quad : getQuads(\n\t\t\t\t\tnull,\n\t\t\t\t\tdirection,\n\t\t\t\t\trandomSource\n\t\t\t)) {\n\t\t\t\tvar culledMeshCollector = culledMeshCollectors.get(quad.getTintIndex());\n\n\t\t\t\tif (culledMeshCollector == null) {\n\t\t\t\t\tculledMeshCollector = new CulledMeshCollector\t(extension);\n\t\t\t\t\tculledMeshCollectors.put\t\t\t\t\t\t(quad.getTintIndex(), culledMeshCollector);\n\t\t\t\t}\n\n\t\t\t\tvar meshBuilder = extension\t.decorate\t(culledMeshCollector);\n\t\t\t\tvar data\t\t= quad\t\t.getVertices();\n\n\t\t\t\tfor (int i = 0; i < data.length / 8; i++) {\n\t\t\t\t\tvar vertexOffset\t= i\t\t\t\t* IQuadTransformer.STRIDE;\n\t\t\t\t\tvar posOffset\t\t= vertexOffset\t+ IQuadTransformer.POSITION;\n\t\t\t\t\tvar colorOffset\t\t= vertexOffset\t+ IQuadTransformer.COLOR;\n\t\t\t\t\tvar uv0Offset\t\t= vertexOffset\t+ IQuadTransformer.UV0;\n\t\t\t\t\tvar uv2Offset\t\t= vertexOffset\t+ IQuadTransformer.UV2;\n\t\t\t\t\tvar normalOffset\t= vertexOffset\t+ IQuadTransformer.NORMAL;\n\t\t\t\t\tvar packedNormal\t= data[normalOffset];\n\n\t\t\t\t\tmeshBuilder.addVertex(\n\t\t\t\t\t\t\tFloat\t\t\t.intBitsToFloat\t(data[posOffset + 0]),\n\t\t\t\t\t\t\tFloat\t\t\t.intBitsToFloat\t(data[posOffset + 1]),\n\t\t\t\t\t\t\tFloat\t\t\t.intBitsToFloat\t(data[posOffset + 2]),\n\t\t\t\t\t\t\tFastColorUtils\t.convert\t\t(data[colorOffset]),\n\t\t\t\t\t\t\tFloat\t\t\t.intBitsToFloat\t(data[uv0Offset + 0]),\n\t\t\t\t\t\t\tFloat\t\t\t.intBitsToFloat\t(data[uv0Offset + 1]),\n\t\t\t\t\t\t\t-1,\n\t\t\t\t\t\t\tdata[uv2Offset],\n\t\t\t\t\t\t\t((byte) (\tpackedNormal\t\t& 0xFF)) / 127.0f,\n\t\t\t\t\t\t\t((byte) ((\tpackedNormal >> 8)\t& 0xFF)) / 127.0f,\n\t\t\t\t\t\t\t((byte) ((\tpackedNormal >> 16)\t& 0xFF)) / 127.0f\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (int layer : culledMeshCollectors.keySet()) {\n\t\t\tvar culledMeshCollector = culledMeshCollectors.get(layer);\n\n\t\t\tculledMeshCollector.flush();\n\n\t\t\tvar data\t= culledMeshCollector\t.getData\t();\n\t\t\tvar buffer\t= culledMeshCollector\t.getBuffer\t();\n\t\t\tvar mesh\t= merges\t\t\t\t.get\t\t(data);\n\n\t\t\tif (mesh != null) {\n\t\t\t\tbuffer.discard\t();\n\t\t\t\tbuffer.close\t();\n\t\t\t} else {\n\t\t\t\tmesh = AcceleratedEntityRenderingFeature\n\t\t\t\t\t\t.getMeshType()\n\t\t\t\t\t\t.getBuilder\t()\n\t\t\t\t\t\t.build\t\t(culledMeshCollector);\n\t\t\t}\n\n\t\t\tlayers\t.put\t(layer, mesh);\n\t\t\tmerges\t.put\t(data,\tmesh);\n\t\t\tmesh\t.write\t(\n\t\t\t\t\textension,\n\t\t\t\t\tgetCustomColor(layer, layerColors.getColor(layer)),\n\t\t\t\t\tlight,\n\t\t\t\t\toverlay\n\t\t\t);\n\t\t}\n\n\t\textension.endTransform();\n\t}\n\n\n\t@Unique\n\t@Override\n\tpublic boolean isAccelerated() {\n\t\treturn true;\n\t}\n\n\t@Unique\n\t@Override\n\tpublic boolean isAcceleratedInHand() {\n\t\treturn false;\n\t}\n\n\t@Unique\n\t@Override\n\tpublic boolean isAcceleratedInGui() {\n\t\treturn false;\n\t}\n\n\t@Unique\n\t@Override\n\tpublic int getCustomColor(int layer, int color) {\n\t\treturn layer == -1 ? -1 : color;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/models/WeightedBakedModelMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.items.mixins.models;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.features.items.BakedModelExtension;\nimport com.github.argon4w.acceleratedrendering.features.items.IAcceleratedBakedModel;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport lombok.Getter;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.client.resources.model.WeightedBakedModel;\nimport net.minecraft.util.RandomSource;\nimport net.minecraft.util.random.WeightedEntry;\nimport net.minecraft.util.random.WeightedRandom;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.Unique;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\nimport java.util.List;\n\n@Getter\n@ExtensionMethod(BakedModelExtension.class)\n@Mixin\t\t\t(WeightedBakedModel\t.class)\npublic class WeightedBakedModelMixin implements IAcceleratedBakedModel {\n\n\t@Unique private\t\t\tboolean\t\t\t\t\t\t\t\t\taccelerated;\n\t@Unique private\t\t\tboolean\t\t\t\t\t\t\t\t\tacceleratedInHand;\n\t@Unique private\t\t\tboolean\t\t\t\t\t\t\t\t\tacceleratedInGui;\n\n\t@Shadow @Final private\tList<WeightedEntry.Wrapper<BakedModel>>\tlist;\n\t@Shadow @Final private\tint\t\t\t\t\t\t\t\t\t\ttotalWeight;\n\n\t@Inject(\n\t\t\tmethod\t= \"<init>\",\n\t\t\tat\t\t= @At(\"TAIL\")\n\t)\n\tpublic void checkAccelerationSupport(List<WeightedEntry.Wrapper<BakedModel>> list, CallbackInfo ci) {\n\t\taccelerated\t\t\t= true;\n\t\tacceleratedInHand\t= true;\n\t\tacceleratedInGui\t= true;\n\n\t\tfor (WeightedEntry.Wrapper<BakedModel> wrapper : list) {\n\t\t\tvar extension = wrapper.data().getAccelerated();\n\n\t\t\taccelerated\t\t\t&= extension.isAccelerated\t\t();\n\t\t\tacceleratedInHand\t&= extension.isAcceleratedInHand();\n\t\t\tacceleratedInGui\t&= extension.isAcceleratedInGui\t();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void renderItemFast(\n\t\t\tItemStack\t\t\t\t\titemStack,\n\t\t\tRandomSource\t\t\t\trandom,\n\t\t\tPoseStack.Pose\t\t\t\tpose,\n\t\t\tIAcceleratedVertexConsumer\textension,\n\t\t\tint\t\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\t\toverlay\n\t) {\n\t\tvar model = WeightedRandom.getWeightedItem(list, Math.abs((int) random.nextLong()) % totalWeight);\n\n\t\tif (model.isPresent()) {\n\t\t\tmodel\n\t\t\t\t\t.get\t\t\t()\n\t\t\t\t\t.data\t\t\t()\n\t\t\t\t\t.getAccelerated\t()\n\t\t\t\t\t.renderItemFast\t(\n\t\t\t\t\t\t\titemStack,\n\t\t\t\t\t\t\trandom,\n\t\t\t\t\t\t\tpose,\n\t\t\t\t\t\t\textension,\n\t\t\t\t\t\t\tlight,\n\t\t\t\t\t\t\toverlay\n\t\t\t\t\t);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void renderBlockFast(\n\t\t\tBlockState\t\t\t\t\tstate,\n\t\t\tRandomSource\t\t\t\trandom,\n\t\t\tPoseStack.Pose\t\t\t\tpose,\n\t\t\tIAcceleratedVertexConsumer\textension,\n\t\t\tint\t\t\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\t\t\tcolor,\n\t\t\tModelData\t\t\t\t\tdata,\n\t\t\tRenderType\t\t\t\t\trenderType\n\t) {\n\t\tvar model = WeightedRandom.getWeightedItem(list, Math.abs((int) random.nextLong()) % totalWeight);\n\n\t\tif (model.isPresent()) {\n\t\t\tmodel\n\t\t\t\t\t.get\t\t\t()\n\t\t\t\t\t.data\t\t\t()\n\t\t\t\t\t.getAccelerated\t()\n\t\t\t\t\t.renderBlockFast(\n\t\t\t\t\t\t\tstate,\n\t\t\t\t\t\t\trandom,\n\t\t\t\t\t\t\tpose,\n\t\t\t\t\t\t\textension,\n\t\t\t\t\t\t\tlight,\n\t\t\t\t\t\t\toverlay,\n\t\t\t\t\t\t\tgetCustomColor(-1, color),\n\t\t\t\t\t\t\tdata,\n\t\t\t\t\t\t\trenderType\n\t\t\t\t\t);\n\t\t}\n\t}\n\n\t@Override\n\tpublic int getCustomColor(int layer, int color) {\n\t\treturn color;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/modelparts/mixins/ModelPartMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.modelparts.mixins;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IBufferGraph;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.github.argon4w.acceleratedrendering.core.meshes.IMesh;\nimport com.github.argon4w.acceleratedrendering.core.meshes.collectors.CulledMeshCollector;\nimport com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData;\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.model.geom.ModelPart;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.Unique;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\nimport java.util.List;\nimport java.util.Map;\n\n@ExtensionMethod\t(VertexConsumerExtension.class)\n@Mixin\t\t\t\t(ModelPart\t\t\t\t.class)\npublic class ModelPartMixin implements IAcceleratedRenderer<Void> {\n\n\t@Shadow @Final public\tList<ModelPart.Cube>\t\tcubes;\n\n\t@Unique private final\tMap<IBufferGraph,\tIMesh>\tmeshes = new Object2ObjectOpenHashMap<>();\n\t@Unique private final\tMap<MeshData,\t\tIMesh>\tmerges = new Object2ObjectOpenHashMap<>();\n\n\t@Inject(\n\t\t\tmethod\t\t= \"render(Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;III)V\",\n\t\t\tat\t\t\t= @At(\"HEAD\"),\n\t\t\tcancellable\t= true\n\t)\n\tpublic void renderFast(\n\t\t\tPoseStack\t\tposeStack,\n\t\t\tVertexConsumer\tbuffer,\n\t\t\tint\t\t\t\tpackedLight,\n\t\t\tint\t\t\t\tpackedOverlay,\n\t\t\tint\t\t\t\tcolor,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tvar extension = buffer.getAccelerated();\n\n\t\tif (\t\t\tAcceleratedEntityRenderingFeature\t.isEnabled\t\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedEntityRenderingFeature\t.shouldUseAcceleratedPipeline\t()\n\t\t\t\t&&\t(\tCoreFeature\t\t\t\t\t\t\t.isRenderingLevel\t\t\t\t()\n\t\t\t\t||\t(\tCoreFeature\t\t\t\t\t\t\t.isRenderingGui\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedEntityRenderingFeature\t.shouldAccelerateInGui\t\t\t()))\n\t\t\t\t&&\t\textension\t\t\t\t\t\t\t.isAccelerated\t\t\t\t\t()\n\t\t) {\n\t\t\tci.cancel();\n\n\t\t\trenderFast(\n\t\t\t\t\t(ModelPart) (Object) this,\n\t\t\t\t\tposeStack,\n\t\t\t\t\textension,\n\t\t\t\t\tpackedLight,\n\t\t\t\t\tpackedOverlay,\n\t\t\t\t\tcolor\n\t\t\t);\n\t\t}\n\t}\n\n\t@Inject(\n\t\t\tmethod\t\t= \"compile\",\n\t\t\tat\t\t\t= @At(\"HEAD\"),\n\t\t\tcancellable\t= true\n\t)\n\tpublic void compileFast(\n\t\t\tPoseStack.Pose\tpPose,\n\t\t\tVertexConsumer\tpBuffer,\n\t\t\tint\t\t\t\tpPackedLight,\n\t\t\tint\t\t\t\tpPackedOverlay,\n\t\t\tint\t\t\t\tpColor,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tvar extension = pBuffer.getAccelerated();\n\n\t\tif (\t\t\tAcceleratedEntityRenderingFeature\t.isEnabled\t\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedEntityRenderingFeature\t.shouldUseAcceleratedPipeline\t()\n\t\t\t\t&&\t(\tCoreFeature\t\t\t\t\t\t\t.isRenderingLevel\t\t\t\t()\n\t\t\t\t||\t(\tCoreFeature\t\t\t\t\t\t\t.isRenderingGui\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedEntityRenderingFeature\t.shouldAccelerateInGui\t\t\t()))\n\t\t\t\t&&\t\textension\t\t\t\t\t\t\t.isAccelerated\t\t\t\t\t()\n\t\t) {\n\t\t\tci\t\t\t.cancel\t\t();\n\t\t\textension\t.doRender\t(\n\t\t\t\t\tthis,\n\t\t\t\t\tnull,\n\t\t\t\t\tpPose.pose\t(),\n\t\t\t\t\tpPose.normal(),\n\t\t\t\t\tpPackedLight,\n\t\t\t\t\tpPackedOverlay,\n\t\t\t\t\tpColor\n\t\t\t);\n\t\t}\n\t}\n\n\t@Unique\n\t@Override\n\tpublic void render(\n\t\t\tVertexConsumer\tvertexConsumer,\n\t\t\tVoid\t\t\tcontext,\n\t\t\tMatrix4f\t\ttransform,\n\t\t\tMatrix3f\t\tnormal,\n\t\t\tint\t\t\t\tlight,\n\t\t\tint\t\t\t\toverlay,\n\t\t\tint\t\t\t\tcolor\n\t) {\n\t\tvar extension\t= vertexConsumer.getAccelerated\t();\n\t\tvar mesh\t\t= meshes\t\t.get\t\t\t(extension);\n\n\t\textension.beginTransform(transform, normal);\n\n\t\tif (mesh != null) {\n\t\t\tmesh.write(\n\t\t\t\t\textension,\n\t\t\t\t\tcolor,\n\t\t\t\t\tlight,\n\t\t\t\t\toverlay\n\t\t\t);\n\n\t\t\textension.endTransform();\n\t\t\treturn;\n\t\t}\n\n\t\tvar culledMeshCollector\t= new CulledMeshCollector\t(extension);\n\t\tvar meshBuilder\t\t\t= extension.decorate\t\t(culledMeshCollector);\n\n\t\tfor (var cube : cubes) {\n\t\t\tfor (var polygon : cube.polygons) {\n\t\t\t\tvar polygonNormal = polygon.normal;\n\n\t\t\t\tfor (var vertex : polygon.vertices) {\n\t\t\t\t\tvar vertexPosition = vertex.pos;\n\n\t\t\t\t\tmeshBuilder.addVertex(\n\t\t\t\t\t\t\tvertexPosition.x / 16.0f,\n\t\t\t\t\t\t\tvertexPosition.y / 16.0f,\n\t\t\t\t\t\t\tvertexPosition.z / 16.0f,\n\t\t\t\t\t\t\t-1,\n\t\t\t\t\t\t\tvertex.u,\n\t\t\t\t\t\t\tvertex.v,\n\t\t\t\t\t\t\toverlay,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\tpolygonNormal.x,\n\t\t\t\t\t\t\tpolygonNormal.y,\n\t\t\t\t\t\t\tpolygonNormal.z\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tculledMeshCollector.flush();\n\n\t\tvar data\t= culledMeshCollector\t.getData\t();\n\t\tvar buffer\t= culledMeshCollector\t.getBuffer\t();\n\t\tmesh\t\t= merges\t\t\t\t.get\t\t(data);\n\n\t\tif (mesh != null) {\n\t\t\tbuffer.discard\t();\n\t\t\tbuffer.close\t();\n\t\t} else {\n\t\t\tmesh = AcceleratedEntityRenderingFeature\n\t\t\t\t\t.getMeshType()\n\t\t\t\t\t.getBuilder\t()\n\t\t\t\t\t.build\t\t(culledMeshCollector);\n\t\t}\n\n\t\tmeshes\t.put\t(extension, mesh);\n\t\tmerges\t.put\t(data,\t\tmesh);\n\t\tmesh\t.write\t(\n\t\t\t\textension,\n\t\t\t\tcolor,\n\t\t\t\tlight,\n\t\t\t\toverlay\n\t\t);\n\n\t\textension.endTransform();\n\t}\n\n\t@Unique\n\t@SuppressWarnings(\"unchecked\")\n\tprivate static void renderFast(\n\t\t\tModelPart\t\t\t\t\tmodelPart,\n\t\t\tPoseStack\t\t\t\t\tposeStack,\n\t\t\tIAcceleratedVertexConsumer\textension,\n\t\t\tint\t\t\t\t\t\t\tpackedLight,\n\t\t\tint\t\t\t\t\t\t\tpackedOverlay,\n\t\t\tint\t\t\t\t\t\t\tpackedColor\n\t) {\n\t\tif (!modelPart.visible) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (\t\tmodelPart.cubes\t\t.isEmpty()\n\t\t\t\t&&\tmodelPart.children\t.isEmpty()\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tposeStack.pushPose();\n\n\t\tmodelPart.translateAndRotate(poseStack);\n\n\t\tif (!modelPart.skipDraw) {\n\t\t\tvar last = poseStack.last();\n\n\t\t\textension.doRender(\n\t\t\t\t\t(IAcceleratedRenderer<Void>) (Object) modelPart,\n\t\t\t\t\tnull,\n\t\t\t\t\tlast.pose\t(),\n\t\t\t\t\tlast.normal\t(),\n\t\t\t\t\tpackedLight,\n\t\t\t\t\tpackedOverlay,\n\t\t\t\t\tpackedColor\n\t\t\t);\n\t\t}\n\n\t\tfor(var child : modelPart.children.values()) {\n\t\t\trenderFast(\n\t\t\t\t\tchild,\n\t\t\t\t\tposeStack,\n\t\t\t\t\textension,\n\t\t\t\t\tpackedLight,\n\t\t\t\t\tpackedOverlay,\n\t\t\t\t\tpackedColor\n\t\t\t);\n\t\t}\n\n\t\tposeStack.popPose();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/simplebedrockmodel/mixins/BedrockPartMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.simplebedrockmodel.mixins;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IBufferGraph;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.github.argon4w.acceleratedrendering.core.meshes.IMesh;\nimport com.github.argon4w.acceleratedrendering.core.meshes.collectors.CulledMeshCollector;\nimport com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData;\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.github.tartaricacid.simplebedrockmodel.client.bedrock.model.BedrockCube;\nimport com.github.tartaricacid.simplebedrockmodel.client.bedrock.model.BedrockPart;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;\nimport it.unimi.dsi.fastutil.objects.ObjectList;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.LightTexture;\nimport net.minecraft.util.FastColor;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.joml.Vector3f;\nimport org.spongepowered.asm.mixin.*;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\nimport java.util.Map;\n\n@Pseudo\n@ExtensionMethod(VertexConsumerExtension.class)\n@Mixin\t\t\t(BedrockPart\t\t\t.class)\npublic class BedrockPartMixin implements IAcceleratedRenderer<Void> {\n\n\t@Unique\tprivate static\tfinal\tPoseStack.Pose\t\t\t\tPOSE\t\t\t= new PoseStack().last();\n\t@Unique private static\tfinal\tVector3f[]\t\t\t\t\tFIXED_NORMALS\t= {\n\t\t\tnew Vector3f(-0.0f, -1.0f, -0.0f),\n\t\t\tnew Vector3f(+0.0f, +1.0f, +0.0f),\n\t\t\tnew Vector3f(-0.0f, -0.0f, -1.0f),\n\t\t\tnew Vector3f(+0.0f, +0.0f, +1.0f),\n\t\t\tnew Vector3f(-1.0f, -0.0f, -0.0f),\n\t\t\tnew Vector3f(+1.0f, +0.0f, +0.0f)\n\t};\n\n\t@Shadow @Final public\t\t\tObjectList<BedrockCube>\t\tcubes;\n\n\t@Unique private final\t\t\tMap<IBufferGraph,\tIMesh>\tmeshes = new Object2ObjectOpenHashMap<>();\n\t@Unique private final\t\t\tMap<MeshData,\t\tIMesh>\tmerges = new Object2ObjectOpenHashMap<>();\n\n\t@Inject(method = \"render(Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;IIFFFF)V\", at = @At(\"HEAD\"), cancellable = true)\n\tpublic void renderFast(\n\t\t\tPoseStack\t\tposeStack,\n\t\t\tVertexConsumer\tconsumer,\n\t\t\tint\t\t\t\tlightmap,\n\t\t\tint\t\t\t\toverlay,\n\t\t\tfloat\t\t\tred,\n\t\t\tfloat\t\t\tgreen,\n\t\t\tfloat\t\t\tblue,\n\t\t\tfloat\t\t\talpha,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tvar extension = consumer.getAccelerated();\n\n\t\tif (\t\t\tAcceleratedEntityRenderingFeature\t.isEnabled\t\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedEntityRenderingFeature\t.shouldUseAcceleratedPipeline\t()\n\t\t\t\t&&\t(\tCoreFeature\t\t\t\t\t\t\t.isRenderingLevel\t\t\t\t()\n\t\t\t\t||\t(\tCoreFeature\t\t\t\t\t\t\t.isRenderingGui\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedEntityRenderingFeature\t.shouldAccelerateInGui\t\t\t()))\n\t\t\t\t&&\t\textension\t\t\t\t\t\t\t.isAccelerated\t\t\t\t\t()\n\t\t) {\n\t\t\tci.cancel();\n\n\t\t\trenderFast(\n\t\t\t\t\t(BedrockPart) (Object) this,\n\t\t\t\t\tposeStack,\n\t\t\t\t\textension,\n\t\t\t\t\tlightmap,\n\t\t\t\t\toverlay,\n\t\t\t\t\tFastColor.ARGB32.color(\n\t\t\t\t\t\t\t(int) (alpha\t* 255.0f),\n\t\t\t\t\t\t\t(int) (red\t\t* 255.0f),\n\t\t\t\t\t\t\t(int) (green\t* 255.0f),\n\t\t\t\t\t\t\t(int) (blue\t\t* 255.0f)\n\t\t\t\t\t)\n\t\t\t);\n\t\t}\n\t}\n\n\t@Inject(\n\t\t\tmethod\t\t= \"compile\",\n\t\t\tat\t\t\t= @At(\"HEAD\"),\n\t\t\tcancellable\t= true\n\t)\n\tpublic void compileFast(\n\t\t\tPoseStack.Pose\tpose,\n\t\t\tVertexConsumer\tconsumer,\n\t\t\tint\t\t\t\ttexU,\n\t\t\tint\t\t\t\ttexV,\n\t\t\tfloat\t\t\tred,\n\t\t\tfloat\t\t\tgreen,\n\t\t\tfloat\t\t\tblue,\n\t\t\tfloat\t\t\talpha,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tvar extension = consumer.getAccelerated();\n\n\t\tif (\t\t\tAcceleratedEntityRenderingFeature\t.isEnabled\t\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedEntityRenderingFeature\t.shouldUseAcceleratedPipeline\t()\n\t\t\t\t&&\t(\tCoreFeature\t\t\t\t\t\t\t.isRenderingLevel\t\t\t\t()\n\t\t\t\t||\t(\tCoreFeature\t\t\t\t\t\t\t.isRenderingGui\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedEntityRenderingFeature\t.shouldAccelerateInGui\t\t\t()))\n\t\t\t\t&&\t\textension\t\t\t\t\t\t\t.isAccelerated\t\t\t\t\t()\n\t\t) {\n\t\t\tci.cancel();\n\n\t\t\textension.doRender(\n\t\t\t\t\tthis,\n\t\t\t\t\tnull,\n\t\t\t\t\tpose.pose\t(),\n\t\t\t\t\tpose.normal\t(),\n\t\t\t\t\ttexU,\n\t\t\t\t\ttexV,\n\t\t\t\t\tFastColor.ARGB32.color\t(\n\t\t\t\t\t\t\t(int) (alpha\t* 255.0f),\n\t\t\t\t\t\t\t(int) (red\t\t* 255.0f),\n\t\t\t\t\t\t\t(int) (green\t* 255.0f),\n\t\t\t\t\t\t\t(int) (blue\t\t* 255.0f)\n\t\t\t\t\t)\n\t\t\t);\n\t\t}\n\t}\n\n\t@Unique\n\t@Override\n\tpublic void render(\n\t\t\tVertexConsumer\tvertexConsumer,\n\t\t\tVoid\t\t\tcontext,\n\t\t\tMatrix4f\t\ttransform,\n\t\t\tMatrix3f\t\tnormal,\n\t\t\tint\t\t\t\tlight,\n\t\t\tint\t\t\t\toverlay,\n\t\t\tint\t\t\t\tcolor\n\t) {\n\t\tvar extension\t= vertexConsumer.getAccelerated\t();\n\t\tvar mesh\t\t= meshes\t\t.get\t\t\t(extension);\n\n\t\textension.beginTransform(transform, normal);\n\n\t\tif (mesh != null) {\n\t\t\tmesh.write(\n\t\t\t\t\textension,\n\t\t\t\t\tcolor,\n\t\t\t\t\tlight,\n\t\t\t\t\toverlay\n\t\t\t);\n\n\t\t\textension.endTransform();\n\t\t\treturn;\n\t\t}\n\n\t\tvar culledMeshCollector\t= new CulledMeshCollector\t(extension);\n\t\tvar meshBuilder\t\t\t= extension.decorate\t\t(culledMeshCollector);\n\n\t\tfor (var cube : cubes) {\n\t\t\tcube.compile(\n\t\t\t\t\tPOSE,\n\t\t\t\t\tFIXED_NORMALS,\n\t\t\t\t\tmeshBuilder,\n\t\t\t\t\t0,\n\t\t\t\t\toverlay,\n\t\t\t\t\t1.0f,\n\t\t\t\t\t1.0f,\n\t\t\t\t\t1.0f,\n\t\t\t\t\t1.0f\n\t\t\t);\n\t\t}\n\n\t\tculledMeshCollector.flush();\n\n\t\tvar data\t= culledMeshCollector\t.getData\t();\n\t\tvar buffer\t= culledMeshCollector\t.getBuffer\t();\n\t\tmesh\t\t= merges\t\t\t\t.get\t\t(data);\n\n\t\tif (mesh != null) {\n\t\t\tbuffer.discard\t();\n\t\t\tbuffer.close\t();\n\t\t} else {\n\t\t\tmesh = AcceleratedEntityRenderingFeature\n\t\t\t\t\t.getMeshType()\n\t\t\t\t\t.getBuilder\t()\n\t\t\t\t\t.build\t\t(culledMeshCollector);\n\t\t}\n\n\t\tmeshes\t.put\t(extension, mesh);\n\t\tmerges\t.put\t(data,\t\tmesh);\n\t\tmesh\t.write\t(\n\t\t\t\textension,\n\t\t\t\tcolor,\n\t\t\t\tlight,\n\t\t\t\toverlay\n\t\t);\n\n\t\textension.endTransform();\n\t}\n\n\t@Unique\n\t@SuppressWarnings(\"unchecked\")\n\tprivate static void renderFast(\n\t\t\tBedrockPart\t\t\t\t\tbedrockPart,\n\t\t\tPoseStack\t\t\t\t\tposeStack,\n\t\t\tIAcceleratedVertexConsumer\textension,\n\t\t\tint\t\t\t\t\t\t\tpackedLight,\n\t\t\tint\t\t\t\t\t\t\tpackedOverlay,\n\t\t\tint\t\t\t\t\t\t\tpackedColor\n\t) {\n\t\tif (!bedrockPart.visible) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar xNearZero = -1E-5F < bedrockPart.xScale && bedrockPart.xScale < 1E-5F;\n\t\tvar yNearZero = -1E-5F < bedrockPart.yScale && bedrockPart.yScale < 1E-5F;\n\t\tvar zNearZero = -1E-5F < bedrockPart.zScale && bedrockPart.zScale < 1E-5F;\n\n\t\tif ((xNearZero && yNearZero) || (xNearZero && zNearZero) || (yNearZero && zNearZero)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (\t\tbedrockPart.cubes\t.isEmpty()\n\t\t\t\t&&\tbedrockPart.children.isEmpty()\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tposeStack.pushPose();\n\n\t\tbedrockPart.translateAndRotateAndScale(poseStack);\n\n\t\tvar last = poseStack.last();\n\n\t\textension.doRender(\n\t\t\t\t(IAcceleratedRenderer<Void>) bedrockPart,\n\t\t\t\tnull,\n\t\t\t\tlast.pose\t(),\n\t\t\t\tlast.normal\t(),\n\t\t\t\tbedrockPart.illuminated ? LightTexture.FULL_BRIGHT : packedLight,\n\t\t\t\tpackedOverlay,\n\t\t\t\tpackedColor\n\t\t);\n\n\t\tfor(var child : bedrockPart.children) {\n\t\t\trenderFast(\n\t\t\t\t\tchild,\n\t\t\t\t\tposeStack,\n\t\t\t\t\textension,\n\t\t\t\t\tpackedLight,\n\t\t\t\t\tpackedOverlay,\n\t\t\t\t\tpackedColor\n\t\t\t);\n\t\t}\n\n\t\tposeStack.popPose();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/text/AcceleratedBakedGlyphRenderer.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.text;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IBufferGraph;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.github.argon4w.acceleratedrendering.core.meshes.IMesh;\nimport com.github.argon4w.acceleratedrendering.core.meshes.collectors.SimpleMeshCollector;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.gui.font.glyphs.BakedGlyph;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.joml.Vector2f;\nimport org.joml.Vector3f;\n\nimport java.util.Map;\n\n@ExtensionMethod(VertexConsumerExtension.class)\npublic class AcceleratedBakedGlyphRenderer implements IAcceleratedRenderer<Vector2f> {\n\n\tprivate static final Matrix4f TRANSFORM\t= new Matrix4f();\n\tprivate static final Matrix3f NORMAL\t= new Matrix3f();\n\n\tprivate final Map<IBufferGraph, IMesh>\tmeshes;\n\tprivate final BakedGlyph\t\t\t\tbakedGlyph;\n\tprivate final boolean\t\t\t\t\titalic;\n\n\tpublic AcceleratedBakedGlyphRenderer(BakedGlyph bakedGlyph, boolean italic) {\n\t\tthis.meshes\t\t= new Object2ObjectOpenHashMap<>();\n\t\tthis.bakedGlyph\t= bakedGlyph;\n\t\tthis.italic\t\t= italic;\n\t}\n\n\t@Override\n\tpublic void render(\n\t\t\tVertexConsumer\tvertexConsumer,\n\t\t\tVector2f\t\tcontext,\n\t\t\tMatrix4f\t\ttransform,\n\t\t\tMatrix3f\t\tnormal,\n\t\t\tint\t\t\t\tlight,\n\t\t\tint\t\t\t\toverlay,\n\t\t\tint\t\t\t\tcolor\n\t) {\n\t\tvar extension\t= vertexConsumer.getAccelerated\t();\n\t\tvar mesh\t\t= meshes\t\t.get\t\t\t(extension);\n\n\t\tTRANSFORM.set\t\t(transform);\n\t\tTRANSFORM.translate\t(\n\t\t\t\tcontext.x,\n\t\t\t\tcontext.y,\n\t\t\t\t0.0f\n\t\t);\n\n\t\textension.beginTransform(TRANSFORM, NORMAL);\n\n\t\tif (mesh != null) {\n\t\t\tmesh.write(\n\t\t\t\t\textension,\n\t\t\t\t\tcolor,\n\t\t\t\t\tlight,\n\t\t\t\t\toverlay\n\t\t\t);\n\n\t\t\textension.endTransform();\n\t\t\treturn;\n\t\t}\n\n\t\tvar meshCollector\t\t= new SimpleMeshCollector\t(extension.getLayout());\n\t\tvar meshBuilder\t\t\t= extension.decorate\t\t(meshCollector);\n\n\t\tvar italicOffsetUp\t\t= italic ? 1.0f - 0.25f * bakedGlyph.up\t\t: 0.0f;\n\t\tvar italicOffsetDown\t= italic ? 1.0f - 0.25f * bakedGlyph.down\t: 0.0f;\n\n\t\tvar positions = new Vector2f[] {\n\t\t\t\tnew Vector2f(bakedGlyph.left\t+ italicOffsetUp,\tbakedGlyph.up),\n\t\t\t\tnew Vector2f(bakedGlyph.left\t+ italicOffsetDown,\tbakedGlyph.down),\n\t\t\t\tnew Vector2f(bakedGlyph.right\t+ italicOffsetDown,\tbakedGlyph.down),\n\t\t\t\tnew Vector2f(bakedGlyph.right\t+ italicOffsetUp,\tbakedGlyph.up)\n\t\t};\n\n\t\tvar texCoords = new Vector2f[] {\n\t\t\t\tnew Vector2f(bakedGlyph.u0, bakedGlyph.v0),\n\t\t\t\tnew Vector2f(bakedGlyph.u0, bakedGlyph.v1),\n\t\t\t\tnew Vector2f(bakedGlyph.u1, bakedGlyph.v1),\n\t\t\t\tnew Vector2f(bakedGlyph.u1, bakedGlyph.v0),\n\t\t};\n\n\t\tfor (var i = 0; i < 4; i ++) {\n\t\t\tvar position = new Vector3f(positions[i], 0.0f);\n\t\t\tvar texCoord = texCoords[i];\n\n\t\t\tmeshBuilder\n\t\t\t\t\t.addVertex\t(position)\n\t\t\t\t\t.setColor\t(-1)\n\t\t\t\t\t.setUv\t\t(texCoord.x, texCoord.y)\n\t\t\t\t\t.setLight\t(0);\n\t\t}\n\n\t\tmesh = AcceleratedTextRenderingFeature\n\t\t\t\t.getMeshType()\n\t\t\t\t.getBuilder\t()\n\t\t\t\t.build\t\t(meshCollector);\n\n\t\tmeshes\t.put\t(extension, mesh);\n\t\tmesh\t.write\t(\n\t\t\t\textension,\n\t\t\t\tcolor,\n\t\t\t\tlight,\n\t\t\t\toverlay\n\t\t);\n\n\t\textension.endTransform();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/text/AcceleratedTextRenderingFeature.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.text;\n\nimport com.github.argon4w.acceleratedrendering.configs.FeatureConfig;\nimport com.github.argon4w.acceleratedrendering.configs.FeatureStatus;\nimport com.github.argon4w.acceleratedrendering.configs.PipelineSetting;\nimport com.github.argon4w.acceleratedrendering.core.meshes.MeshType;\n\nimport java.util.ArrayDeque;\nimport java.util.Deque;\n\npublic class AcceleratedTextRenderingFeature {\n\n\tprivate static final Deque<PipelineSetting> PIPELINE_CONTROLLER_STACK = new ArrayDeque<>();\n\n\tpublic static boolean isEnabled() {\n\t\treturn FeatureConfig.CONFIG.acceleratedTextRenderingFeatureStatus.get() == FeatureStatus.ENABLED;\n\t}\n\n\tpublic static boolean shouldUseAcceleratedPipeline() {\n\t\treturn getPipelineSetting() == PipelineSetting.ACCELERATED;\n\t}\n\n\tpublic static MeshType getMeshType() {\n\t\treturn FeatureConfig.CONFIG.acceleratedTextRenderingMeshType.get();\n\t}\n\n\tpublic static void useVanillaPipeline() {\n\t\tPIPELINE_CONTROLLER_STACK.push(PipelineSetting.VANILLA);\n\t}\n\n\tpublic static void forceUseAcceleratedPipeline() {\n\t\tPIPELINE_CONTROLLER_STACK.push(PipelineSetting.ACCELERATED);\n\t}\n\n\tpublic static void forceSetPipeline(PipelineSetting pipeline) {\n\t\tPIPELINE_CONTROLLER_STACK.push(pipeline);\n\t}\n\n\tpublic static void resetPipeline() {\n\t\tPIPELINE_CONTROLLER_STACK.pop();\n\t}\n\n\tpublic static PipelineSetting getPipelineSetting() {\n\t\treturn PIPELINE_CONTROLLER_STACK.isEmpty() ? getDefaultPipelineSetting() : PIPELINE_CONTROLLER_STACK.peek();\n\t}\n\n\tpublic static PipelineSetting getDefaultPipelineSetting() {\n\t\treturn FeatureConfig.CONFIG.acceleratedTextRenderingDefaultPipeline.get();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/text/mixins/BakedGlyphEffectMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.text.mixins;\n\nimport lombok.EqualsAndHashCode;\nimport net.minecraft.client.gui.font.glyphs.BakedGlyph;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\n\n@EqualsAndHashCode\n@Mixin(BakedGlyph.Effect.class)\npublic class BakedGlyphEffectMixin {\n\n\t@Shadow @Final public float x0;\n\t@Shadow @Final public float x1;\n\t@Shadow @Final public float y0;\n\t@Shadow @Final public float y1;\n\t@Shadow @Final public float depth;\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/text/mixins/BakedGlyphMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.text.mixins;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IBufferGraph;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.github.argon4w.acceleratedrendering.core.meshes.IMesh;\nimport com.github.argon4w.acceleratedrendering.core.meshes.collectors.SimpleMeshCollector;\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.github.argon4w.acceleratedrendering.features.text.AcceleratedBakedGlyphRenderer;\nimport com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.gui.font.glyphs.BakedGlyph;\nimport net.minecraft.client.renderer.texture.OverlayTexture;\nimport net.minecraft.util.FastColor;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.joml.Vector2f;\nimport org.joml.Vector3f;\nimport org.spongepowered.asm.mixin.Final;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Shadow;\nimport org.spongepowered.asm.mixin.Unique;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\nimport java.util.Map;\n\n@ExtensionMethod(value = VertexConsumerExtension.class)\n@Mixin\t\t\t(value = BakedGlyph\t\t\t\t.class, priority = Integer.MIN_VALUE)\npublic class BakedGlyphMixin implements IAcceleratedRenderer<BakedGlyph.Effect> {\n\n\t@Shadow @Final public\t\t\tfloat\t\t\t\t\t\t\t\t\t\t\t\tu0;\n\t@Shadow @Final public\t\t\tfloat\t\t\t\t\t\t\t\t\t\t\t\tv0;\n\t@Shadow @Final public\t\t\tfloat\t\t\t\t\t\t\t\t\t\t\t\tu1;\n\t@Shadow @Final public\t\t\tfloat\t\t\t\t\t\t\t\t\t\t\t\tv1;\n\n\t@Unique private static\tfinal\tMatrix3f\t\t\t\t\t\t\t\t\t\t\tNORMAL\t\t\t= new Matrix3f();\n\n\t@Unique private\t\t\tfinal\tAcceleratedBakedGlyphRenderer\t\t\t\t\t\tnormalRenderer\t= new AcceleratedBakedGlyphRenderer\t((BakedGlyph) (Object) this, false);\n\t@Unique private\t\t\tfinal\tAcceleratedBakedGlyphRenderer\t\t\t\t\t\titalicRenderer\t= new AcceleratedBakedGlyphRenderer\t((BakedGlyph) (Object) this, true);\n\t@Unique private\t\t\tfinal\tMap<BakedGlyph.Effect, Map<IBufferGraph, IMesh>>\teffectMeshes\t= new Object2ObjectOpenHashMap<>\t();\n\n\t@Inject(\n\t\t\tmethod\t\t= \"render\",\n\t\t\tat\t\t\t= @At(\"HEAD\"),\n\t\t\tcancellable\t= true\n\t)\n\tpublic void renderFast(\n\t\t\tboolean\t\t\tpItalic,\n\t\t\tfloat\t\t\tpX,\n\t\t\tfloat\t\t\tpY,\n\t\t\tMatrix4f\t\tpMatrix,\n\t\t\tVertexConsumer\tpBuffer,\n\t\t\tfloat\t\t\tpRed,\n\t\t\tfloat\t\t\tpGreen,\n\t\t\tfloat\t\t\tpBlue,\n\t\t\tfloat\t\t\tpAlpha,\n\t\t\tint\t\t\t\tpPackedLight,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tvar extension = pBuffer.getAccelerated();\n\n\t\tif (\t\t\tAcceleratedTextRenderingFeature\t.isEnabled\t\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedTextRenderingFeature\t.shouldUseAcceleratedPipeline\t()\n\t\t\t\t&&\t(\tCoreFeature\t\t\t\t\t\t.isRenderingLevel\t\t\t\t()\n\t\t\t\t||\t\tCoreFeature\t\t\t\t\t\t.isRenderingGui\t\t\t\t\t())\n\t\t\t\t&&\t\textension\t\t\t\t\t\t.isAccelerated\t\t\t\t\t()\n\t\t) {\n\t\t\tci\t\t\t.cancel\t\t();\n\t\t\textension\t.doRender\t(\n\t\t\t\t\tpItalic\n\t\t\t\t\t\t\t? italicRenderer\n\t\t\t\t\t\t\t: normalRenderer,\n\t\t\t\t\tnew Vector2f(pX, pY),\n\t\t\t\t\tpMatrix,\n\t\t\t\t\tnull,\n\t\t\t\t\tpPackedLight,\n\t\t\t\t\tOverlayTexture\t.NO_OVERLAY,\n\t\t\t\t\tFastColor.ARGB32.color(\n\t\t\t\t\t\t\t(int) (pAlpha\t* 255.0f),\n\t\t\t\t\t\t\t(int) (pRed\t\t* 255.0f),\n\t\t\t\t\t\t\t(int) (pGreen\t* 255.0f),\n\t\t\t\t\t\t\t(int) (pBlue\t* 255.0f)\n\t\t\t\t\t)\n\t\t\t);\n\t\t}\n\t}\n\n\t@Inject(\n\t\t\tmethod\t\t= \"renderEffect\",\n\t\t\tat\t\t\t= @At(\"HEAD\"),\n\t\t\tcancellable\t= true\n\t)\n\tpublic void renderEffectFast(\n\t\t\tBakedGlyph.Effect\teffect,\n\t\t\tMatrix4f\t\t\tmatrix,\n\t\t\tVertexConsumer\t\tbuffer,\n\t\t\tint\t\t\t\t\tpackedLight,\n\t\t\tCallbackInfo\t\tci\n\t) {\n\t\tvar extension = buffer.getAccelerated();\n\n\t\tif (\t\t\tAcceleratedTextRenderingFeature\t.isEnabled\t\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedTextRenderingFeature\t.shouldUseAcceleratedPipeline\t()\n\t\t\t\t&&\t(\tCoreFeature\t\t\t\t\t\t.isRenderingLevel\t\t\t\t()\n\t\t\t\t||\t\tCoreFeature\t\t\t\t\t\t.isRenderingGui\t\t\t\t\t())\n\t\t\t\t&&\t\textension\t\t\t\t\t\t.isAccelerated\t\t\t\t\t()\n\t\t) {\n\t\t\tci\t\t\t.cancel\t\t();\n\t\t\textension\t.doRender\t(\n\t\t\t\t\tthis,\n\t\t\t\t\teffect,\n\t\t\t\t\tmatrix,\n\t\t\t\t\tNORMAL,\n\t\t\t\t\tpackedLight,\n\t\t\t\t\tOverlayTexture\t.NO_OVERLAY,\n\t\t\t\t\tFastColor.ARGB32.color(\n\t\t\t\t\t\t\t(int) (effect.a * 255.0f),\n\t\t\t\t\t\t\t(int) (effect.r * 255.0f),\n\t\t\t\t\t\t\t(int) (effect.g * 255.0f),\n\t\t\t\t\t\t\t(int) (effect.b * 255.0f)\n\t\t\t\t\t)\n\t\t\t);\n\t\t}\n\t}\n\n\t@Unique\n\t@Override\n\tpublic void render(\n\t\t\tVertexConsumer\t\tvertexConsumer,\n\t\t\tBakedGlyph.Effect\tcontext,\n\t\t\tMatrix4f\t\t\ttransform,\n\t\t\tMatrix3f\t\t\tnormal,\n\t\t\tint\t\t\t\t\tlight,\n\t\t\tint\t\t\t\t\toverlay,\n\t\t\tint\t\t\t\t\tcolor\n\t) {\n\t\tvar extension\t= vertexConsumer.getAccelerated\t();\n\t\tvar meshes\t\t= effectMeshes\t.get\t\t\t(context);\n\n\t\textension.beginTransform(transform, normal);\n\n\t\tif (meshes == null) {\n\t\t\tmeshes = new Object2ObjectOpenHashMap<>\t();\n\t\t\teffectMeshes.put\t\t\t\t\t\t(context, meshes);\n\t\t}\n\n\t\tvar mesh = meshes.get(extension);\n\n\t\tif (mesh != null) {\n\t\t\tmesh.write(\n\t\t\t\t\textension,\n\t\t\t\t\tcolor,\n\t\t\t\t\tlight,\n\t\t\t\t\toverlay\n\t\t\t);\n\n\t\t\textension.endTransform();\n\t\t\treturn;\n\t\t}\n\n\t\tvar meshCollector\t= new SimpleMeshCollector\t(extension.getLayout());\n\t\tvar meshBuilder\t\t= extension.decorate\t\t(meshCollector);\n\n\t\tvar positions = new Vector2f[] {\n\t\t\t\tnew Vector2f(context.x0, context.y0),\n\t\t\t\tnew Vector2f(context.x1, context.y0),\n\t\t\t\tnew Vector2f(context.x1, context.y1),\n\t\t\t\tnew Vector2f(context.x0, context.y1),\n\t\t};\n\n\t\tvar texCoords = new Vector2f[] {\n\t\t\t\tnew Vector2f(u0, v0),\n\t\t\t\tnew Vector2f(u0, v1),\n\t\t\t\tnew Vector2f(u1, v1),\n\t\t\t\tnew Vector2f(u1, v0),\n\t\t};\n\n\t\tfor (var i = 0; i < 4; i ++) {\n\t\t\tvar position = new Vector3f(positions[i], context.depth);\n\t\t\tvar texCoord = texCoords[i];\n\n\t\t\tmeshBuilder\n\t\t\t\t\t.addVertex\t(position)\n\t\t\t\t\t.setColor\t(-1)\n\t\t\t\t\t.setUv\t\t(texCoord.x, texCoord.y)\n\t\t\t\t\t.setLight\t(0);\n\t\t}\n\n\t\tmesh = AcceleratedTextRenderingFeature\n\t\t\t\t.getMeshType()\n\t\t\t\t.getBuilder\t()\n\t\t\t\t.build\t\t(meshCollector);\n\n\t\tmeshes\t.put\t(extension, mesh);\n\t\tmesh\t.write\t(\n\t\t\t\textension,\n\t\t\t\tcolor,\n\t\t\t\tlight,\n\t\t\t\toverlay\n\t\t);\n\n\t\textension.endTransform();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/touhoulittlemaid/mixins/GeoBoneMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.touhoulittlemaid.mixins;\n\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IBufferGraph;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.github.argon4w.acceleratedrendering.core.meshes.IMesh;\nimport com.github.argon4w.acceleratedrendering.core.meshes.collectors.CulledMeshCollector;\nimport com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData;\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.github.tartaricacid.touhoulittlemaid.geckolib3.geo.render.built.GeoBone;\nimport com.github.tartaricacid.touhoulittlemaid.geckolib3.geo.render.built.GeoMesh;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;\nimport lombok.experimental.ExtensionMethod;\nimport org.joml.Matrix3f;\nimport org.joml.Matrix4f;\nimport org.joml.Vector2i;\nimport org.joml.Vector3f;\nimport org.spongepowered.asm.mixin.*;\n\nimport java.util.Map;\n\n@Pseudo\n@ExtensionMethod(VertexConsumerExtension.class)\n@Mixin\t\t\t(GeoBone\t\t\t\t.class)\npublic class GeoBoneMixin implements IAcceleratedRenderer<Void> {\n\n\t@Shadow @Final private GeoMesh\t\t\t\t\t\tcubes;\n\n\t@Unique private final\tMap<IBufferGraph,\tIMesh>\tmeshes = new Object2ObjectOpenHashMap<>();\n\t@Unique private final\tMap<MeshData,\t\tIMesh>\tmerges = new Object2ObjectOpenHashMap<>();\n\n\t@Unique\n\t@Override\n\tpublic void render(\n\t\t\tVertexConsumer\tvertexConsumer,\n\t\t\tVoid\t\t\tcontext,\n\t\t\tMatrix4f\t\ttransformMatrix,\n\t\t\tMatrix3f\t\tnormalMatrix,\n\t\t\tint\t\t\t\tlight,\n\t\t\tint\t\t\t\toverlay,\n\t\t\tint\t\t\t\tcolor\n\t) {\n\t\tvar extension\t= vertexConsumer.getAccelerated\t();\n\t\tvar mesh\t\t= meshes\t\t.get\t\t\t(extension);\n\n\t\textension.beginTransform(transformMatrix, normalMatrix);\n\n\t\tif (mesh != null) {\n\t\t\tmesh.write(\n\t\t\t\t\textension,\n\t\t\t\t\tcolor,\n\t\t\t\t\tlight,\n\t\t\t\t\toverlay\n\t\t\t);\n\n\t\t\textension.endTransform();\n\t\t\treturn;\n\t\t}\n\n\t\tvar culledMeshCollector\t= new CulledMeshCollector\t(extension);\n\t\tvar meshBuilder\t\t\t= extension.decorate\t\t(culledMeshCollector);\n\n\t\tfor(int i = 0; i < cubes.getCubeCount(); ++i) {\n\t\t\tvar deltaX\t\t\t= new Vector3f\t(cubes.dx(i));\n\t\t\tvar deltaY\t\t\t= new Vector3f\t(cubes.dy(i));\n\t\t\tvar deltaZ\t\t\t= new Vector3f\t(cubes.dz(i));\n\n\t\t\tvar p000\t\t\t= new Vector3f\t(cubes.position(i));\n\t\t\tvar p100\t\t\t= p000\t.add\t(deltaX, new Vector3f());\n\t\t\tvar p110\t\t\t= p100\t.add\t(deltaY, new Vector3f());\n\t\t\tvar p010\t\t\t= p000\t.add\t(deltaY, new Vector3f());\n\t\t\tvar p001\t\t\t= p000\t.add\t(deltaZ, new Vector3f());\n\t\t\tvar p101\t\t\t= p100\t.add\t(deltaZ, new Vector3f());\n\t\t\tvar p111\t\t\t= p110\t.add\t(deltaZ, new Vector3f());\n\t\t\tvar p011\t\t\t= p010\t.add\t(deltaZ, new Vector3f());\n\t\t\t\n\t\t\tvar positiveNormalZ\t= deltaX.cross\t(deltaY, new Vector3f()).normalize();\n\t\t\tvar positiveNormalX\t= deltaY.cross\t(deltaZ, new Vector3f()).normalize();\n\t\t\tvar positiveNormalY\t= deltaZ.cross\t(deltaX, new Vector3f()).normalize();\n\t\t\tvar faces\t\t\t= cubes\t.faces\t(i);\n\t\t\tvar mirrored\t\t= (faces & 64) != 0;\n\n\t\t\tif (mirrored) {\n\t\t\t\tpositiveNormalX.mul(-1.0F);\n\t\t\t\tpositiveNormalY.mul(-1.0F);\n\t\t\t\tpositiveNormalZ.mul(-1.0F);\n\t\t\t}\n\n\t\t\tvar negativeNormalX\t= positiveNormalX.negate(new Vector3f());\n\t\t\tvar negativeNormalY\t= positiveNormalY.negate(new Vector3f());\n\t\t\tvar negativeNormalZ\t= positiveNormalZ.negate(new Vector3f());\n\n\t\t\tvar positions\t\t= new Vector3f[][] {\n\t\t\t\t\t{p101, p001, p000, p100},\n\t\t\t\t\t{p110, p010, p011, p111},\n\t\t\t\t\t{p100, p000, p010, p110},\n\t\t\t\t\t{p001, p101, p111, p011},\n\t\t\t\t\t{p000, p001, p011, p010},\n\t\t\t\t\t{p101, p100, p110, p111}\n\t\t\t};\n\n\t\t\tvar texCoords\t\t= new float[][] {\n\t\t\t\t\t{cubes.downU0\t(i), cubes.downU1\t(i), cubes.downV0\t(i), cubes.downV1\t(i)},\n\t\t\t\t\t{cubes.upU0\t\t(i), cubes.upU1\t\t(i), cubes.upV0\t\t(i), cubes.upV1\t\t(i)},\n\t\t\t\t\t{cubes.northU0\t(i), cubes.northU1\t(i), cubes.northV0\t(i), cubes.northV1\t(i)},\n\t\t\t\t\t{cubes.southU0\t(i), cubes.southU1\t(i), cubes.southV0\t(i), cubes.southV1\t(i)},\n\t\t\t\t\t{cubes.westU0\t(i), cubes.westU1\t(i), cubes.westV0\t(i), cubes.westV1\t(i)},\n\t\t\t\t\t{cubes.eastU0\t(i), cubes.eastU1\t(i), cubes.eastV0\t(i), cubes.eastV1\t(i)},\n\t\t\t};\n\n\t\t\tvar texOrders\t\t= new Vector2i[] {\n\t\t\t\t\tnew Vector2i(0, 3),\n\t\t\t\t\tnew Vector2i(1, 3),\n\t\t\t\t\tnew Vector2i(1, 2),\n\t\t\t\t\tnew Vector2i(0, 2)\n\t\t\t};\n\n\t\t\tvar normals\t\t\t= new Vector3f[] {\n\t\t\t\t\tnegativeNormalY,\n\t\t\t\t\tpositiveNormalY,\n\t\t\t\t\tnegativeNormalZ,\n\t\t\t\t\tpositiveNormalZ,\n\t\t\t\t\tnegativeNormalX,\n\t\t\t\t\tpositiveNormalX,\n\t\t\t};\n\n\t\t\tfor (var j = 0; j < 6; j ++) {\n\t\t\t\tif ((faces & (1 << j)) != 0) {\n\t\t\t\t\tfor (var k = 0; k < 4; k ++) {\n\t\t\t\t\t\tvar position\t= positions\t[j][k];\n\t\t\t\t\t\tvar texCoord\t= texCoords\t[j];\n\t\t\t\t\t\tvar texOrder\t= texOrders\t[k];\n\t\t\t\t\t\tvar normal\t\t= normals\t[j];\n\n\t\t\t\t\t\tmeshBuilder.addVertex(\n\t\t\t\t\t\t\t\tposition.x,\n\t\t\t\t\t\t\t\tposition.y,\n\t\t\t\t\t\t\t\tposition.z,\n\t\t\t\t\t\t\t\t-1,\n\t\t\t\t\t\t\t\ttexCoord[texOrder.x],\n\t\t\t\t\t\t\t\ttexCoord[texOrder.y],\n\t\t\t\t\t\t\t\toverlay,\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnormal.x,\n\t\t\t\t\t\t\t\tnormal.y,\n\t\t\t\t\t\t\t\tnormal.z\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tculledMeshCollector.flush();\n\n\t\tvar data\t= culledMeshCollector\t.getData\t();\n\t\tvar buffer\t= culledMeshCollector\t.getBuffer\t();\n\t\tmesh\t\t= merges\t\t\t\t.get\t\t(data);\n\n\t\tif (mesh != null) {\n\t\t\tbuffer.discard\t();\n\t\t\tbuffer.close\t();\n\t\t} else {\n\t\t\tmesh = AcceleratedEntityRenderingFeature\n\t\t\t\t\t.getMeshType()\n\t\t\t\t\t.getBuilder\t()\n\t\t\t\t\t.build\t\t(culledMeshCollector);\n\t\t}\n\n\t\tmeshes\t.put\t(extension, mesh);\n\t\tmerges\t.put\t(data,\t\tmesh);\n\t\tmesh\t.write\t(\n\t\t\t\textension,\n\t\t\t\tcolor,\n\t\t\t\tlight,\n\t\t\t\toverlay\n\t\t);\n\n\t\textension.endTransform();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/com/github/argon4w/acceleratedrendering/features/touhoulittlemaid/mixins/IGeoRendererMixin.java",
    "content": "package com.github.argon4w.acceleratedrendering.features.touhoulittlemaid.mixins;\n\nimport com.github.argon4w.acceleratedrendering.core.CoreFeature;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension;\nimport com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer;\nimport com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature;\nimport com.github.tartaricacid.touhoulittlemaid.geckolib3.geo.IGeoRenderer;\nimport com.github.tartaricacid.touhoulittlemaid.geckolib3.geo.animated.AnimatedGeoBone;\nimport com.github.tartaricacid.touhoulittlemaid.geckolib3.util.RenderUtils;\nimport com.llamalad7.mixinextras.injector.wrapoperation.Operation;\nimport com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport lombok.experimental.ExtensionMethod;\nimport net.minecraft.client.renderer.LightTexture;\nimport net.minecraft.util.FastColor;\nimport org.spongepowered.asm.mixin.Mixin;\nimport org.spongepowered.asm.mixin.Pseudo;\nimport org.spongepowered.asm.mixin.Unique;\nimport org.spongepowered.asm.mixin.injection.At;\nimport org.spongepowered.asm.mixin.injection.Inject;\nimport org.spongepowered.asm.mixin.injection.callback.CallbackInfo;\n\n@Pseudo\n@ExtensionMethod(VertexConsumerExtension.class)\n@Mixin\t\t\t(IGeoRenderer\t\t\t.class)\npublic interface IGeoRendererMixin {\n\n\t@Inject(\n\t\t\tmethod\t\t= \"renderRecursively\",\n\t\t\tat\t\t\t= @At(\"HEAD\"),\n\t\t\tcancellable\t= true\n\t)\n\tdefault void renderRecursivelyFast(\n\t\t\tAnimatedGeoBone\tbone,\n\t\t\tPoseStack\t\tposeStack,\n\t\t\tVertexConsumer\tbuffer,\n\t\t\tint\t\t\t\tpackedLight,\n\t\t\tint\t\t\t\tpackedOverlay,\n\t\t\tfloat\t\t\tred,\n\t\t\tfloat\t\t\tgreen,\n\t\t\tfloat\t\t\tblue,\n\t\t\tfloat\t\t\talpha,\n\t\t\tCallbackInfo\tci\n\t) {\n\t\tvar extension = buffer.getAccelerated();\n\n\t\tif (\t\t\tAcceleratedEntityRenderingFeature\t.isEnabled\t\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedEntityRenderingFeature\t.shouldUseAcceleratedPipeline\t()\n\t\t\t\t&&\t(\tCoreFeature\t\t\t\t\t\t\t.isRenderingLevel\t\t\t\t()\n\t\t\t\t||\t(\tCoreFeature\t\t\t\t\t\t\t.isRenderingGui\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedEntityRenderingFeature\t.shouldAccelerateInGui\t\t\t()))\n\t\t\t\t&&\t\textension\t\t\t\t\t\t\t.isAccelerated\t\t\t\t\t()\n\t\t) {\n\t\t\tci.cancel();\n\n\t\t\trenderRecursivelyFast(\n\t\t\t\t\tbone,\n\t\t\t\t\tposeStack,\n\t\t\t\t\textension,\n\t\t\t\t\tpackedLight,\n\t\t\t\t\tpackedOverlay,\n\t\t\t\t\tFastColor.ARGB32.color(\n\t\t\t\t\t\t\t(int) (alpha\t* 255.0f),\n\t\t\t\t\t\t\t(int) (red\t\t* 255.0f),\n\t\t\t\t\t\t\t(int) (green\t* 255.0f),\n\t\t\t\t\t\t\t(int) (blue\t\t* 255.0f)\n\t\t\t\t\t)\n\t\t\t);\n\t\t}\n\t}\n\n\t@SuppressWarnings\t(\"unchecked\")\n\t@WrapOperation\t\t(\n\t\t\tmethod\t\t= \"renderRecursively\",\n\t\t\tat\t\t\t= @At(\n\t\t\t\t\tvalue\t= \"INVOKE\",\n\t\t\t\t\ttarget\t= \"Lcom/github/tartaricacid/touhoulittlemaid/compat/sodium/SodiumCompat;sodiumRenderCubesOfBone(Lcom/github/tartaricacid/touhoulittlemaid/geckolib3/geo/animated/AnimatedGeoBone;Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;IIFFFF)Z\"\n\t\t\t)\n\t)\n\tdefault boolean renderBoneFast(\n\t\t\tAnimatedGeoBone\t\tbone,\n\t\t\tPoseStack\t\t\tposeStack,\n\t\t\tVertexConsumer\t\tbuffer,\n\t\t\tint\t\t\t\t\tcubePackedLight,\n\t\t\tint\t\t\t\t\tpackedOverlay,\n\t\t\tfloat\t\t\t\tred,\n\t\t\tfloat\t\t\t\tgreen,\n\t\t\tfloat\t\t\t\tblue,\n\t\t\tfloat\t\t\t\talpha,\n\t\t\tOperation<Boolean>\toriginal\n\t) {\n\t\tvar extension = buffer.getAccelerated();\n\n\t\tif (\t\t\tAcceleratedEntityRenderingFeature\t.isEnabled\t\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedEntityRenderingFeature\t.shouldUseAcceleratedPipeline\t()\n\t\t\t\t&&\t(\tCoreFeature\t\t\t\t\t\t\t.isRenderingLevel\t\t\t\t()\n\t\t\t\t||\t(\tCoreFeature\t\t\t\t\t\t\t.isRenderingGui\t\t\t\t\t()\n\t\t\t\t&&\t\tAcceleratedEntityRenderingFeature\t.shouldAccelerateInGui\t\t\t()))\n\t\t\t\t&&\t\textension\t\t\t\t\t\t\t.isAccelerated\t\t\t\t\t()\n\t\t) {\n\t\t\tif (\t\t!bone.isHidden\t\t()\n\t\t\t\t\t&&\t!bone.cubesAreHidden()\n\t\t\t) {\n\t\t\t\tvar last = poseStack.last();\n\n\t\t\t\textension.doRender(\n\t\t\t\t\t\t(IAcceleratedRenderer<Void>) bone.geoBone(),\n\t\t\t\t\t\tnull,\n\t\t\t\t\t\tlast.pose\t(),\n\t\t\t\t\t\tlast.normal\t(),\n\t\t\t\t\t\tcubePackedLight,\n\t\t\t\t\t\tpackedOverlay,\n\t\t\t\t\t\tFastColor.ARGB32.color(\n\t\t\t\t\t\t\t\t(int) (alpha\t* 255.0f),\n\t\t\t\t\t\t\t\t(int) (red\t\t* 255.0f),\n\t\t\t\t\t\t\t\t(int) (green\t* 255.0f),\n\t\t\t\t\t\t\t\t(int) (blue\t\t* 255.0f)\n\t\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn original.call(\n\t\t\t\tbone,\n\t\t\t\tposeStack,\n\t\t\t\tbuffer,\n\t\t\t\tcubePackedLight,\n\t\t\t\tpackedOverlay,\n\t\t\t\tred,\n\t\t\t\tgreen,\n\t\t\t\tblue,\n\t\t\t\talpha\n\t\t);\n\t}\n\n\t@Unique\n\t@SuppressWarnings(\"unchecked\")\n\tprivate static void renderRecursivelyFast(\n\t\t\tAnimatedGeoBone\t\t\t\tanimated,\n\t\t\tPoseStack\t\t\t\t\tposeStack,\n\t\t\tIAcceleratedVertexConsumer\textension,\n\t\t\tint\t\t\t\t\t\t\tpackedLight,\n\t\t\tint\t\t\t\t\t\t\tpackedOverlay,\n\t\t\tint\t\t\t\t\t\t\tpackedColor\n\t) {\n\t\tif (\t\t(animated.getScaleX() == 0.0F ? 0 : 1)\n\t\t\t\t+\t(animated.getScaleY() == 0.0F ? 0 : 1)\n\t\t\t\t+\t(animated.getScaleZ() == 0.0F ? 0 : 1) >= 2\n\t\t) {\n\t\t\tposeStack.pushPose();\n\n\t\t\tRenderUtils.prepMatrixForBone(poseStack, animated);\n\n\t\t\tif (\t\t!animated.isHidden\t\t()\n\t\t\t\t\t&&\t!animated.cubesAreHidden()\n\t\t\t) {\n\t\t\t\tvar last = poseStack.last\t();\n\t\t\t\tvar bone = animated\t.geoBone();\n\n\t\t\t\textension.doRender(\n\t\t\t\t\t\t(IAcceleratedRenderer<Void>) bone,\n\t\t\t\t\t\tnull,\n\t\t\t\t\t\tlast.pose\t(),\n\t\t\t\t\t\tlast.normal\t(),\n\t\t\t\t\t\tbone.glow\t() ? LightTexture.FULL_BRIGHT : packedLight,\n\t\t\t\t\t\tpackedOverlay,\n\t\t\t\t\t\tpackedColor\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (!animated.childBonesAreHiddenToo()) {\n\t\t\t\tfor(var childBone : animated.children()) {\n\t\t\t\t\trenderRecursivelyFast(\n\t\t\t\t\t\t\tchildBone,\n\t\t\t\t\t\t\tposeStack,\n\t\t\t\t\t\t\textension,\n\t\t\t\t\t\t\tpackedLight,\n\t\t\t\t\t\t\tpackedOverlay,\n\t\t\t\t\t\t\tpackedColor\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tposeStack.popPose();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/resources/META-INF/accesstransformer.cfg",
    "content": "# Core\npublic net.minecraft.client.renderer.OutlineBufferSource$EntityOutlineGenerator\npublic net.minecraft.client.renderer.RenderType$CompositeState texturingState\n\n# ModelPart\npublic net.minecraft.client.model.geom.ModelPart cubes\npublic net.minecraft.client.model.geom.ModelPart children\n\n# Mesh caching\npublic net.minecraft.client.model.geom.ModelPart$Cube polygons\npublic net.minecraft.client.model.geom.ModelPart$Polygon\npublic net.minecraft.client.model.geom.ModelPart$Vertex\n\n# For Texture based pre-render culling and gpu-based culling\npublic net.minecraft.client.renderer.RenderType$CompositeRenderType\npublic net.minecraft.client.renderer.RenderType$CompositeRenderType state\n\n# Texture based pre-render culling\npublic net.minecraft.client.renderer.RenderType$CompositeState textureState\npublic net.minecraft.client.renderer.RenderStateShard$EmptyTextureStateShard cutoutTexture()Ljava/util/Optional;\npublic net.minecraft.client.renderer.RenderStateShard$TextureStateShard cutoutTexture()Ljava/util/Optional;\npublic net.minecraft.client.renderer.RenderStateShard$MultiTextureStateShard cutoutTexture()Ljava/util/Optional;\n\n# GPU based culling\npublic net.minecraft.client.renderer.RenderType$CompositeState cullState\npublic net.minecraft.client.renderer.RenderStateShard$BooleanStateShard enabled\n\n# Text Rendering\npublic net.minecraft.client.gui.font.glyphs.BakedGlyph u0\npublic net.minecraft.client.gui.font.glyphs.BakedGlyph u1\npublic net.minecraft.client.gui.font.glyphs.BakedGlyph v0\npublic net.minecraft.client.gui.font.glyphs.BakedGlyph v1\npublic net.minecraft.client.gui.font.glyphs.BakedGlyph left\npublic net.minecraft.client.gui.font.glyphs.BakedGlyph right\npublic net.minecraft.client.gui.font.glyphs.BakedGlyph up\npublic net.minecraft.client.gui.font.glyphs.BakedGlyph down\npublic net.minecraft.client.gui.font.glyphs.BakedGlyph$Effect x0\npublic net.minecraft.client.gui.font.glyphs.BakedGlyph$Effect y0\npublic net.minecraft.client.gui.font.glyphs.BakedGlyph$Effect x1\npublic net.minecraft.client.gui.font.glyphs.BakedGlyph$Effect y1\npublic net.minecraft.client.gui.font.glyphs.BakedGlyph$Effect depth\npublic net.minecraft.client.gui.font.glyphs.BakedGlyph$Effect r\npublic net.minecraft.client.gui.font.glyphs.BakedGlyph$Effect g\npublic net.minecraft.client.gui.font.glyphs.BakedGlyph$Effect b\npublic net.minecraft.client.gui.font.glyphs.BakedGlyph$Effect a\n\n# Item Rendering\npublic net.minecraft.client.gui.GuiGraphics renderItem(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;IIII)V\npublic net.minecraft.world.inventory.AbstractContainerMenu menuType\npublic net.minecraft.client.gui.GuiGraphics innerBlit(Lnet/minecraft/resources/ResourceLocation;IIIIIFFFFFFFF)V\npublic net.minecraft.client.renderer.RenderStateShard$WriteMaskStateShard writeColor\npublic net.minecraft.client.renderer.RenderStateShard$WriteMaskStateShard writeDepth\npublic net.minecraft.client.renderer.RenderType$CompositeState shaderState\npublic net.minecraft.client.renderer.RenderType$CompositeState transparencyState\npublic net.minecraft.client.renderer.RenderType$CompositeState depthTestState\npublic net.minecraft.client.renderer.RenderType$CompositeState cullState\npublic net.minecraft.client.renderer.RenderType$CompositeState lightmapState\npublic net.minecraft.client.renderer.RenderType$CompositeState overlayState\npublic net.minecraft.client.renderer.RenderType$CompositeState layeringState\npublic net.minecraft.client.renderer.RenderType$CompositeState outputState\npublic net.minecraft.client.renderer.RenderType$CompositeState texturingState\npublic net.minecraft.client.renderer.RenderType$CompositeState writeMaskState\npublic net.minecraft.client.renderer.RenderType$CompositeState lineState\npublic net.minecraft.client.renderer.RenderType$CompositeState colorLogicState\npublic net.minecraft.client.renderer.RenderType$CompositeState outlineProperty\n\n# Scissor State\npublic net.minecraft.client.gui.GuiGraphics scissorStack\npublic net.minecraft.client.gui.GuiGraphics$ScissorStack\npublic net.minecraft.client.gui.GuiGraphics$ScissorStack stack"
  },
  {
    "path": "src/main/resources/META-INF/neoforge.mods.toml",
    "content": "# This is an example neoforge.mods.toml file. It contains the data relating to the loading mods.\n# There are several mandatory fields (#mandatory), and many more that are optional (#optional).\n# The overall format is standard TOML format, v0.5.0.\n# Note that there are a couple of TOML lists in this file.\n# Find more information on toml format here:  https://github.com/toml-lang/toml\n# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml\nmodLoader=\"javafml\" #mandatory\n\n# A version range to match for said mod loader - for regular FML @Mod it will be the FML version. This is currently 2.\nloaderVersion=\"${loader_version_range}\" #mandatory\n\n# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties.\n# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here.\nlicense=\"${mod_license}\"\n\n# A URL to refer people to when problems occur with this mod\nissueTrackerURL=\"https://github.com/Argon4W/AcceleratedRendering/issues\" #optional\n\n# A list of mods - how many allowed here is determined by the individual mod loader\n[[mods]] #mandatory\n\n# The modid of the mod\nmodId=\"${mod_id}\" #mandatory\n\n# The version number of the mod\nversion=\"${mod_version}\" #mandatory\n\n# A display name for the mod\ndisplayName=\"${mod_name}\" #mandatory\n\n# A URL to query for updates for this mod. See the JSON update specification https://docs.neoforged.net/docs/misc/updatechecker/\n#updateJSONURL=\"https://change.me.example.invalid/updates.json\" #optional\n\n# A URL for the \"homepage\" for this mod, displayed in the mod UI\ndisplayURL=\"https://github.com/Argon4W/AcceleratedRendering\" #optional\n\n# A file name (in the root of the mod JAR) containing a logo for display\nlogoFile=\"logo.png\" #optional\n\n# A text field displayed in the mod UI\n#credits=\"\" #optional\n\n# A text field displayed in the mod UI\nauthors=\"${mod_authors}\" #optional\n\n# The description text for the mod (multi line!) (#mandatory)\ndescription='''${mod_description}'''\n\n# The [[mixins]] block allows you to declare your mixin config to FML so that it gets loaded.\n\n# Accelerated Rendering Core Mixins\n# Provides core functions to make Accelerated Rendering works.\n[[mixins]]\nconfig=\"${mod_id}.core.mixins.json\"\n\n# Accelerated Rendering Compatibility Feature Mixins\n# Provides shaders and post processings that supports modified vertex formats by Iris Shaders\n[[mixins]]\nconfig=\"${mod_id}.compat.iris.mixins.json\"\n\n# Immediately Fast Compatibility Feature Mixins\n# Provides comparibility of Accelerated Rendering to BatchableBufferSource in Immediately Fast.\n[[mixins]]\nconfig=\"${mod_id}.compat.immediatelyfast.mixins.json\"\n\n# Accelerated Rendering Curios Compatibility Feature Mixins\n# Provides compatibility features that prevents some bad rendering code from breaking Accelerated Rendering.\n[[mixins]]\nconfig=\"${mod_id}.compat.curios.mixins.json\"\n\n# Accelerated Entity Rendering Feature Mixins\n# Provides basic entity acceleration feature controllers and entity shadows acceleration.\n[[mixins]]\nconfig=\"${mod_id}.feature.entities.mixins.json\"\n\n# Accelerated Entity ModelPart Rendering Feature Mixins\n# Accelerates the rendering of vanilla entities or modded vanilla-Like entities that uses ModelPart.\n[[mixins]]\nconfig=\"${mod_id}.feature.modelparts.mixins.json\"\n\n# Accelerated Item Rendering Feature Mixins\n# Accelerates the rendering of simple item models that use BakedModel/BakedQuads and provides acceleration feature controller of them.\n[[mixins]]\nconfig=\"${mod_id}.feature.items.mixins.json\"\n\n# Accelerated Text Rendering Feature Mixins\n# Accekerates the rendering of BakedGlyph which is the most common way of rendering text in Minecraft and provides acceleration feature controller of them.\n[[mixins]]\nconfig=\"${mod_id}.feature.text.mixins.json\"\n\n# Filter Feature Mixins\n# Prevent specific entities/block entities from being accelerated when rendering to achieve better compatibility.\n[[mixins]]\nconfig=\"${mod_id}.feature.filter.mixins.json\"\n\n# Simple Bedrock Model Acceleration Feature Mixins\n# Accelerates the rendering of entities that uses BedrockPart provided by the SimpleBedrockModel such as older version model in Touhou Little Maid.\n[[mixins]]\nconfig=\"${mod_id}.feature.simplebedrockmodel.mixins.json\"\n\n# Touhou Little Maid Acceleration Feature Mixins\n# Accelerates the rendering of maids in Touhou Little Maid that uses modified version of the GeckoLib.\n[[mixins]]\nconfig=\"${mod_id}.feature.touhoulittlemaid.mixins.json\"\n\n# FTB Library Acceleration Feature Mixins\n# Batch the rendering of items in GUI screens provided by mods like FTB Quests.\n[[mixins]]\nconfig=\"${mod_id}.feature.ftb.mixins.json\"\n\n# Geckolib Acceleration Feature Mixins\n# Accelerated the rendering of entities and block entities that uses the GeoBone provided by GeckoLib.\n[[mixins]]\nconfig=\"${mod_id}.feature.geckolib.mixins.json\"\n\n# Entity Model Feature Acceleration Feature Mixins\n# Entity Model Feature modifies and uses its own compile method same as vanilla ModelPart so it has to be injected manully to be accelerated.\n[[mixins]]\nconfig=\"${mod_id}.feature.entitymodelfeature.mixins.json\"\n\n# The [[accessTransformers]] block allows you to declare where your AT file is.\n# If this block is omitted, a fallback attempt will be made to load an AT from META-INF/accesstransformer.cfg\n#[[accessTransformers]]\n#file=\"META-INF/accesstransformer.cfg\"\n\n# The coremods config file path is not configurable and is always loaded from META-INF/coremods.json\n\n# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional.\n[[dependencies.${mod_id}]] #optional\n    # the modid of the dependency\n    modId=\"neoforge\" #mandatory\n    # The type of the dependency. Can be one of \"required\", \"optional\", \"incompatible\" or \"discouraged\" (case insensitive).\n    # 'required' requires the mod to exist, 'optional' does not\n    # 'incompatible' will prevent the game from loading when the mod exists, and 'discouraged' will show a warning\n    type=\"required\" #mandatory\n    # Optional field describing why the dependency is required or why it is incompatible\n    # reason=\"...\"\n    # The version range of the dependency\n    versionRange=\"${neo_version_range}\" #mandatory\n    # An ordering relationship for the dependency.\n    # BEFORE - This mod is loaded BEFORE the dependency\n    # AFTER - This mod is loaded AFTER the dependency\n    ordering=\"NONE\"\n    # Side this dependency is applied on - BOTH, CLIENT, or SERVER\n    side=\"CLIENT\"\n\n# Here's another dependency\n[[dependencies.${mod_id}]]\n    # the modid of the dependency\n    modId=\"minecraft\"\n    # The type of the dependency. Can be one of \"required\", \"optional\", \"incompatible\" or \"discouraged\" (case insensitive).\n    # 'required' requires the mod to exist, 'optional' does not\n    # 'incompatible' will prevent the game from loading when the mod exists, and 'discouraged' will show a warning\n    type=\"required\"\n    # Optional field describing why the dependency is required or why it is incompatible\n    # reason=\"...\"\n    # The version range of the dependency\n    # This version range declares a minimum of the current minecraft version up to but not including the next major version\n    versionRange=\"${minecraft_version_range}\"\n    # An ordering relationship for the dependency.\n    # BEFORE - This mod is loaded BEFORE the dependency\n    # AFTER - This mod is loaded AFTER the dependency\n    ordering=\"NONE\"\n    # Side this dependency is applied on - BOTH, CLIENT, or SERVER\n    side=\"CLIENT\"\n\n# Features are specific properties of the game environment, that you may want to declare you require. This example declares\n# that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't\n# stop your mod loading on the server for example.\n[features.${mod_id}]\nopenGLVersion=\"[4.6,)\"\n"
  },
  {
    "path": "src/main/resources/acceleratedrendering.compat.curios.mixins.json",
    "content": "{\n  \"required\": true,\n  \"minVersion\": \"0.8\",\n  \"package\": \"com.github.argon4w.acceleratedrendering.compat.curios.mixins\",\n  \"compatibilityLevel\": \"JAVA_21\",\n  \"client\": [\n    \"CuriosLayerMixin\"\n  ],\n  \"injectors\": {\n    \"defaultRequire\": 1\n  }\n}"
  },
  {
    "path": "src/main/resources/acceleratedrendering.compat.immediatelyfast.mixins.json",
    "content": "{\n  \"required\": true,\n  \"minVersion\": \"0.8\",\n  \"package\": \"com.github.argon4w.acceleratedrendering.compat.immediatelyfast.mixins\",\n  \"compatibilityLevel\": \"JAVA_21\",\n  \"client\": [\n    \"BatchableBufferSourceMixin\",\n    \"BatchingBuffersMixin\",\n    \"WrappedRenderLayerMixin\"\n  ],\n  \"injectors\": {\n    \"defaultRequire\": 1\n  }\n}"
  },
  {
    "path": "src/main/resources/acceleratedrendering.compat.iris.mixins.json",
    "content": "{\n  \"required\": true,\n  \"minVersion\": \"0.8\",\n  \"package\": \"com.github.argon4w.acceleratedrendering.compat.iris.mixins\",\n  \"compatibilityLevel\": \"JAVA_21\",\n  \"plugin\": \"com.github.argon4w.acceleratedrendering.compat.iris.mixins.plugin.IrisCompatMixinPlugin\",\n  \"client\": [\n    \"acceleratedrendering.AcceleratedBufferBuilderMixin\",\n    \"acceleratedrendering.AcceleratedBufferSourceMixin\",\n    \"acceleratedrendering.AcceleratedRenderingModEntryMixin\",\n    \"acceleratedrendering.CoreBuffersProviderMixin\",\n    \"acceleratedrendering.FlattenMeshInfoCacheMixin\",\n    \"acceleratedrendering.IBufferEnvironmentPresetsMixin\",\n    \"acceleratedrendering.SimpleMeshInfoMixin\",\n    \"acceleratedrendering.MeshUploaderMixin\",\n    \"acceleratedrendering.MeshUploadingProgramDispatcherMixin\",\n    \"acceleratedrendering.RenderTypeUtilsMixin\",\n    \"acceleratedrendering.SimpleMeshInfoCacheMixin\",\n    \"acceleratedrendering.UnsafeMemoryMeshInfoCacheMixin\",\n    \"iris.FullyBufferedMultiBufferSourceMixin\",\n    \"iris.HandRendererMixin\",\n    \"iris.IrisVertexFormatsMixin\",\n    \"iris.ModelToEntityVertexSerializerMixin\",\n    \"iris.ShadowRendererMixin\",\n    \"vanilla.LevelRendererMixin\"\n  ],\n  \"injectors\": {\n    \"defaultRequire\": 1\n  }\n}"
  },
  {
    "path": "src/main/resources/acceleratedrendering.core.mixins.json",
    "content": "{\n  \"required\": true,\n  \"minVersion\": \"0.8\",\n  \"package\": \"com.github.argon4w.acceleratedrendering.core.mixins\",\n  \"compatibilityLevel\": \"JAVA_21\",\n  \"client\": [\n    \"buffers.BufferBuilderMixin\",\n    \"buffers.BufferSourceMixin\",\n    \"buffers.EntityOutlineGeneratorMixin\",\n    \"buffers.MinecraftMixin\",\n    \"buffers.OutlineBufferSourceMixin\",\n    \"buffers.SheetedDecalTextureGeneratorMixin\",\n    \"buffers.SpriteCoordinateExpanderMixin\",\n    \"buffers.VertexConsumerMixin\",\n    \"buffers.VertexDoubleConsumerMixin\",\n    \"buffers.VertexMultipleConsumerMixin\",\n    \"compatibility.MinecraftMixin\",\n    \"compatibility.ParticleEngineMixin\",\n    \"compatibility.RenderTypeMixin\",\n    \"compatibility.WindowMixin\",\n    \"GameRendererMixin\",\n    \"LevelRendererMixin\"\n  ],\n  \"injectors\": {\n    \"defaultRequire\": 1\n  }\n}"
  },
  {
    "path": "src/main/resources/acceleratedrendering.feature.entities.mixins.json",
    "content": "{\n  \"required\": true,\n  \"minVersion\": \"0.8\",\n  \"package\": \"com.github.argon4w.acceleratedrendering.features.entities.mixins\",\n  \"compatibilityLevel\": \"JAVA_21\",\n  \"client\": [\n    \"EntityRenderDispatcherMixin\",\n    \"InventoryScreenMixin\"\n  ],\n  \"injectors\": {\n    \"defaultRequire\": 1\n  }\n}"
  },
  {
    "path": "src/main/resources/acceleratedrendering.feature.entitymodelfeature.mixins.json",
    "content": "{\n  \"required\": true,\n  \"minVersion\": \"0.8\",\n  \"package\": \"com.github.argon4w.acceleratedrendering.features.emf.mixins\",\n  \"compatibilityLevel\": \"JAVA_21\",\n  \"client\": [\n    \"EMFModelPartMixin\",\n    \"EMFModelPartWithStateMixin\"\n  ],\n  \"injectors\": {\n    \"defaultRequire\": 1\n  }\n}"
  },
  {
    "path": "src/main/resources/acceleratedrendering.feature.filter.mixins.json",
    "content": "{\n  \"required\": true,\n  \"minVersion\": \"0.8\",\n  \"package\": \"com.github.argon4w.acceleratedrendering.features.filter.mixins\",\n  \"compatibilityLevel\": \"JAVA_21\",\n  \"client\": [\n    \"AbstractContainerScreenMixin\",\n    \"BlockEntityRenderDispatcherMixin\",\n    \"ClientHooksMixin\",\n    \"ItemRendererMixin\",\n    \"LevelRendererMixin\"\n  ],\n  \"injectors\": {\n    \"defaultRequire\": 1\n  }\n}"
  },
  {
    "path": "src/main/resources/acceleratedrendering.feature.ftb.mixins.json",
    "content": "{\n  \"required\": true,\n  \"minVersion\": \"0.8\",\n  \"package\": \"com.github.argon4w.acceleratedrendering.features.ftb.mixins\",\n  \"compatibilityLevel\": \"JAVA_21\",\n  \"client\": [\n    \"BaseScreenMixin\"\n  ],\n  \"injectors\": {\n    \"defaultRequire\": 1\n  }\n}"
  },
  {
    "path": "src/main/resources/acceleratedrendering.feature.geckolib.mixins.json",
    "content": "{\n  \"required\": true,\n  \"minVersion\": \"0.8\",\n  \"package\": \"com.github.argon4w.acceleratedrendering.features.geckolib.mixins\",\n  \"compatibilityLevel\": \"JAVA_21\",\n  \"client\": [\n    \"GeoBoneMixin\",\n    \"GeoRendererMixin\"\n  ],\n  \"injectors\": {\n    \"defaultRequire\": 1\n  }\n}"
  },
  {
    "path": "src/main/resources/acceleratedrendering.feature.items.mixins.json",
    "content": "{\n  \"required\": true,\n  \"minVersion\": \"0.8\",\n  \"package\": \"com.github.argon4w.acceleratedrendering.features.items.mixins\",\n  \"compatibilityLevel\": \"JAVA_21\",\n  \"client\": [\n    \"accessors.BlockColorsAccessor\",\n    \"accessors.ItemColorsAccessor\",\n    \"compatibility.ClientHooksMixin\",\n    \"compatibility.GuiLayerManagerMixin\",\n    \"gui.AbstractContainerScreenMixin\",\n    \"gui.FontMixin\",\n    \"gui.GuiGraphicsMixin\",\n    \"gui.GuiMixin\",\n    \"models.BakedCompositeModelMixin\",\n    \"models.BakedModelMixin\",\n    \"models.BakedQuadMixin\",\n    \"models.BakedSeparateTransformsModelMixin\",\n    \"models.MultipartBakedModelMixin\",\n    \"models.SimpleBakedModelMixin\",\n    \"models.WeightedBakedModelMixin\",\n    \"ItemRendererMixin\",\n    \"ModelBlockRendererMixin\"\n  ],\n  \"injectors\": {\n    \"defaultRequire\": 1\n  }\n}"
  },
  {
    "path": "src/main/resources/acceleratedrendering.feature.modelparts.mixins.json",
    "content": "{\n  \"required\": true,\n  \"minVersion\": \"0.8\",\n  \"package\": \"com.github.argon4w.acceleratedrendering.features.modelparts.mixins\",\n  \"compatibilityLevel\": \"JAVA_21\",\n  \"client\": [\n    \"ModelPartMixin\"\n  ],\n  \"injectors\": {\n    \"defaultRequire\": 1\n  }\n}"
  },
  {
    "path": "src/main/resources/acceleratedrendering.feature.simplebedrockmodel.mixins.json",
    "content": "{\n  \"required\": true,\n  \"minVersion\": \"0.8\",\n  \"package\": \"com.github.argon4w.acceleratedrendering.features.simplebedrockmodel.mixins\",\n  \"compatibilityLevel\": \"JAVA_21\",\n  \"client\": [\n    \"BedrockPartMixin\"\n  ],\n  \"injectors\": {\n    \"defaultRequire\": 1\n  }\n}"
  },
  {
    "path": "src/main/resources/acceleratedrendering.feature.text.mixins.json",
    "content": "{\n  \"required\": true,\n  \"minVersion\": \"0.8\",\n  \"package\": \"com.github.argon4w.acceleratedrendering.features.text.mixins\",\n  \"compatibilityLevel\": \"JAVA_21\",\n  \"client\": [\n    \"BakedGlyphEffectMixin\",\n    \"BakedGlyphMixin\"\n  ],\n  \"injectors\": {\n    \"defaultRequire\": 1\n  }\n}"
  },
  {
    "path": "src/main/resources/acceleratedrendering.feature.touhoulittlemaid.mixins.json",
    "content": "{\n  \"required\": true,\n  \"minVersion\": \"0.8\",\n  \"package\": \"com.github.argon4w.acceleratedrendering.features.touhoulittlemaid.mixins\",\n  \"compatibilityLevel\": \"JAVA_21\",\n  \"client\": [\n    \"GeoBoneMixin\",\n    \"IGeoRendererMixin\"\n  ],\n  \"injectors\": {\n    \"defaultRequire\": 1\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/lang/en_us.json",
    "content": "{\n  \"acceleratedrendering.configuration.title\": \"Accelerated Rendering Configurations\",\n  \"acceleratedrendering.configuration.section.acceleratedrendering.client.toml.title\": \"Accelerated Rendering Client Configurations\",\n  \"acceleratedrendering.configuration.section.acceleratedrendering.client.toml\": \"Configurations of features provided by Accelerated Rendering\",\n  \"acceleratedrendering.configuration.core_settings\": \"Core Settings\",\n  \"acceleratedrendering.configuration.core_settings.tooltip\": \"Core Settings allows you to change setting that are related to all rendering features.\",\n  \"acceleratedrendering.configuration.core_settings.pooled_ring_buffer_size\": \"Maximum Pooled Ring Buffer Size\",\n  \"acceleratedrendering.configuration.core_settings.pooled_ring_buffer_size.tooltip\": \"Changing this value may affects your FPS. Smaller value means less in-flight frames, while larger values means more in-flight frames. More in-flight frames means more FPS but more VRAM.\",\n  \"acceleratedrendering.configuration.core_settings.pooled_batching_size\": \"Maximum Pooled Batching Size\",\n  \"acceleratedrendering.configuration.core_settings.pooled_batching_size.tooltip\": \"Changing this value may affects your FPS. Smaller value means less batches allowed in a draw call, while larger values means more batches. More batches means more FPS but more VRAM and more CPU pressure on handling RenderTypes.\",\n  \"acceleratedrendering.configuration.core_settings.cached_image_size\": \"Maximum Cached Image Size\",\n  \"acceleratedrendering.configuration.core_settings.cached_image_size.tooltip\": \"Changing this value may affects your FPS. Smaller value means less images allowed to be cached, while larger means more cached images. More cached images means more FPS but more RAM pressure.\",\n  \"acceleratedrendering.configuration.core_settings.dynamic_uv_resolution\": \"Dynamic Render Type Cache UV Resolution\",\n  \"acceleratedrendering.configuration.core_settings.dynamic_uv_resolution.tooltip\": \"Changing this value may affects your visual effects and VRAM usage. Smaller value means lower resolution in UV scrolling and less cached render types, while larger means higher resolution and more cached render types. Higher resolution means smoother animations on charged creepers and breezes but more VRAM usage.\",\n  \"acceleratedrendering.configuration.core_settings.debug_context\": \"Enable Debug Context\",\n  \"acceleratedrendering.configuration.core_settings.debug_context.tooltip\": \"- DISABLED: Debug context will be disabled, which may cause significant rendering glitches on some NVIDIA cards because of the \\\"theaded optimization\\\".\\n- ENABLED: Debug context will be enabled, which can prevent NVIDIA driver from applying the \\\"threaded optimization\\\" that causes the glitches.\",\n  \"acceleratedrendering.configuration.core_settings.force_translucent_acceleration\": \"Enable Force Translucent Acceleration\",\n  \"acceleratedrendering.configuration.core_settings.force_translucent_acceleration.tooltip\": \"- DISABLED: Translucent RenderType will fallback to vanilla rendering pipeline if the accelerated pipeline does not support translucent sorting unless mods explicitly enable force translucent acceleration temporarily when rendering their own faces.\\n- ENABLED: Translucent RenderType will still be rendered in accelerated pipeline even if the pipeline does not support translucent sorting unless mods explicitly disable force translucent acceleration temporarily when rendering their own faces.\",\n  \"acceleratedrendering.configuration.core_settings.cache_identical_pose\": \"Enable Cache Identical Pose\",\n  \"acceleratedrendering.configuration.core_settings.cache_identical_pose.tooltip\": \"- DISABLED: Poses with identical transform matrix and normal matrix that used to transform vertices will not be cached in buffer which slightly decreases CPU pressure but increase VRAM usage unless mods explicitly disable it when rendering.\\n- ENABLED: Poses with identical transform matrix and normal matrix that used to transform vertices will be cached in buffer which save VRAM but slightly increase CPU pressure unless mods explicitly disable it when rendering.\",\n  \"acceleratedrendering.configuration.core_settings.mesh_info_cache_type\": \"Mesh Instance Info Cache Type\",\n  \"acceleratedrendering.configuration.core_settings.mesh_info_cache_type.tooltip\": \"- SIMPLE: The most basic implementation of cache. Usually used for testing if other cache types are working correctly.\\n- HANDLE: Faster implementation of cache using VarHandle and flatten values to improve performance on read/write operations.\\n- UNSAFE: Fastest implementation of cache using unsafe memory operations that skip multiple safety checks to read/write.\",\n  \"acceleratedrendering.configuration.core_settings.layer_storage_type\": \"Batching Layer Storage Type\",\n  \"acceleratedrendering.configuration.core_settings.layer_storage_type.tooltip\": \"- SORTED: The basic implementation of batching layer storage that renders opaque and translucent geometries together in a single stage with better performance but slight visual glitches on translucent geometries.\\n- SEPARATED: The visually-precise implementation of batching layer storage that separates opaque and translucent geometries into two rendering stages to prevent visual glitches, slightly slower than basic implementation.\",\n  \"acceleratedrendering.configuration.core_settings.mesh_merge_type\": \"Mesh Merge Type\",\n  \"acceleratedrendering.configuration.core_settings.mesh_merge_type.tooltip\": \"- IGNORED: Meshes with identical vertices will not be merged, which will use less RAM but more VRAM in storing duplicated meshes.\\n- MERGED: Meshes with identical vertices will be merged together, which will use less VRAM more RAM in storing the data of meshes used in merging.\",\n  \"acceleratedrendering.configuration.core_settings.upload_mesh_immediately\": \"Enable Uploading Mesh Immediately\",\n  \"acceleratedrendering.configuration.core_settings.upload_mesh_immediately.tooltip\": \"- DISABLED: Meshes that is going to be accelerated will be collected and uploaded together at the end for choosing better uploading method and increasing memory access efficiency to reach the best performance. Also this method allows mesh cache with bigger capacity (up to VRAM limit), but it may not follow the correct draw order.\\n- ENABLED: Meshes that is going to be accelerated will be uploaded immediately after the draw command. It is less efficient and only have about 2GB mesh cache (generally enough) but will follow the original draw order to get the most compatibility.\",\n  \"acceleratedrendering.configuration.core_settings.cache_dynamic_render_type\": \"Enable Cache Dynamic Render Type\",\n  \"acceleratedrendering.configuration.core_settings.cache_dynamic_render_type.tooltip\": \"- DISABLED: Dynamic render types like lightning on charged creepers and winds on breezes will not be accelerated for less VRAM usage and smoother animations, but may exceptionally skip acceleration in modded geometries using these render types.\\n- ENABLED: Dynamic render types like lightning on charged creepers and winds on breezes will be accelerated to accelerate modded geometries using these render types, but may have more VRAM usage and less smooth animations based on resolution settings.\",\n  \"acceleratedrendering.configuration.core_settings.viewport_binding_state\": \"Viewport Restoring Type\",\n  \"acceleratedrendering.configuration.core_settings.viewport_binding_state.tooltip\": \"- IGNORED: Viewport settings that will be modified by other mods will not be restored after the acceleration, which is faster but reduces compatibility with them.\\n- MOJANG: Viewport settings that will be modified by other mods will be recorded and restored using Mojang's GLStateManager to work correctly with them.\\n- OPENGL: Viewport settings that will be modified by other mods will be recorded and restored using OpenGL to work correctly with them even if they don't set viewport using Mojang's GLStateManager, which is slower but has most compatibility.\",\n  \"acceleratedrendering.configuration.core_settings.scissor_binding_state\": \"Scissor Restoring Type\",\n  \"acceleratedrendering.configuration.core_settings.scissor_binding_state.tooltip\": \"- IGNORED: Scissor settings that will be modified by other mods will not be restored after the acceleration, which is faster but reduces compatibility with them.\\n- MOJANG: Scissor settings that will be modified by other mods will be recorded and restored using Mojang's GuiGraphics to work correctly with them.\\n- OPENGL: Scissor settings that will be modified by other mods will be recorded and restored using OpenGL to work correctly with them even if they don't set viewport using Mojang's GuiGraphics, which is slower but has most compatibility.\",\n  \"acceleratedrendering.configuration.core_settings.button\": \"Configure\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring\": \"Block Buffer Restoring Settings\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.tooltip\": \"A few mods and shader packs will use their on block buffers when rendering, which may introduce conflicts when working with Accelerated Rendering that also uses block buffers.\\nBlock Buffer Restoring can record the binding of block buffers before the acceleration and restore them after the acceleration to work correctly with them.\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.feature_status\": \"Enable Block Buffer Restoring\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.feature_status.tooltip\": \"- DISABLED: Disable block buffer restoring, which is faster but may cause visual glitches with mods and shaders that uses block buffers.\\n- ENABLED: Enable block buffer restoring, which may be slower due to recording and restoring block buffer bindings that ensures working correctly with mods and shaders that use block buffers.\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.binding_cache_type\": \"Block Buffer Binding Cache Type\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.binding_cache_type.tooltip\": \"- SIMPLE: The most basic implementation of cache. Usually used for testing if other cache types are working properly.\\n- HANDLE: Faster implementation of cache using VarHandle and flatten values to improve performance on read/write operations.\\n- UNSAFE: Fastest implementation of cache using unsafe memory operations that skip multiple safety checks to read/write.\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.shader_storage_type\": \"Shader Storage Buffer Restoring Type\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.shader_storage_type.tooltip\": \"- IGNORED: Shader storage buffers will not be restored which improves FPS but reduces compatibility with mods and shaders that ues shader storage buffers.\\n- RESTORED: Shader storage buffers will be restored, which is slight slower but has better compatibility with mods and shaders that ues shader storage buffers.\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.atomic_counter_type\": \"Atomic Counter Buffer Restoring Type\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.atomic_counter_type.tooltip\": \"- IGNORED: Atomic counter buffers will not be restored which improves FPS but reduces compatibility with mods and shaders that ues atomic counter buffers.\\n- RESTORED: Atomic counter buffers will be restored, which is slight slower but has better compatibility with mods and shaders that ues atomic counter buffers.\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.shader_storage_range\": \"Shader Storage Buffer Restoring Range\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.shader_storage_range.tooltip\": \"Range of shader storage buffer bindings that will be restored.\\nChanging this value may affects your FPS. Smaller value means less shader storage buffer restored but less compatibility, while larger values means more shader storage buffer restored and better compatibility. More shader storage buffers means less FPS.\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.atomic_counter_range\": \"Atomic Counter Buffer Restoring Range\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.atomic_counter_range.tooltip\": \"Range of atomic counter buffer bindings that will be restored.\\nChanging this value may affects your FPS. Smaller value means less atomic counter buffer restored but less compatibility, while larger values means more atomic counter buffer restored and better compatibility. More atomic counter buffers means less FPS.\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.button\": \"Configure\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering\": \"Accelerated Entity Rendering Settings\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.tooltip\": \"Accelerated Entity Rendering uses GPU to cache and transform vertices whiling rendering entities, instead of generating and transforming vertices every time the entities are rendered in CPU.\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.feature_status\": \"Enable Accelerated Entity Rendering\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.feature_status.tooltip\": \"- DISABLED: Disable accelerated entity rendering.\\n- ENABLED: Enable accelerated entity rendering.\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.default_pipeline\": \"Default Rendering Pipeline\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.default_pipeline.tooltip\": \"- VANILLA: Entities will not be rendered into the accelerated pipeline unless mods explicitly enable it temporarily when rendering their own entities.\\n- ACCELERATED: All entities will be rendered in the accelerated pipeline unless mods explicitly disable it temporarily when rendering their own entities.\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.mesh_type\": \"Cached Mesh Type\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.mesh_type.tooltip\": \"- CLIENT: Cached mesh will be stored on the client side (CPU), which will use less VRAM but take more time to upload to the server side (GPU) during rendering.\\n- SERVER: Cached mesh will be stored on the server side (GPU), which may speed up rendering but will use more VRAM to store the mesh.\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.gui_acceleration\": \"Enable GUI Acceleration\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.gui_acceleration.tooltip\": \"- DISABLED: Accelerated Rendering will not accelerate entities when rendering it in a GUI unless mods explicitly enable it temporarily when rendering their own entities.\\n- ENABLED: Accelerated Rendering will still accelerate entities when rendering it in a GUI unless mods explicitly disable it temporarily when rendering their own entities.\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.button\": \"Configure\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering\": \"Accelerated Item Rendering Settings\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.tooltip\": \"Accelerated Item Rendering uses GPU to cache and transform vertices while rendering item models, instead of generating and transforming vertices every time the item models are rendered in CPU.\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.feature_status\": \"Enable Accelerated Item Rendering\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.feature_status.tooltip\": \"- DISABLED: Disable accelerated item rendering.\\n- ENABLED: Enable accelerated item rendering.\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.bake_mesh_for_quads\": \"Bake Mesh For Quads\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.bake_mesh_for_quads.tooltip\": \"- DISABLED: Accelerated Rendering will not bake mesh for quads provided by dynamic item models (something that is not SimpleBakedModel) unless mods explicitly enable it temporarily when rendering their own item models.\\n- ENABLED: Accelerated Rendering will bake mesh for all quads provided by dynamic item models (something that is not SimpleBakedModel) unless mods explicitly disable it temporarily when rendering their own item models, which will accelerate the rendering of these models but will crash if they keep allocating new quad data. (but who will?)\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.default_pipeline\": \"Default Rendering Pipeline\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.default_pipeline.tooltip\": \"- VANILLA: Item models will not be rendered into the accelerated pipeline unless mods explicitly enable it temporarily when rendering their own item models.\\n- ACCELERATED: All item models will be rendered in the accelerated pipeline unless mods explicitly disable it temporarily when rendering their own item models.\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.mesh_type\": \"Cached Mesh Type\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.mesh_type.tooltip\": \"- CLIENT: Cached mesh will be stored on the client side (CPU), which will use less VRAM but take more time to upload to the server side (GPU) during rendering.\\n- SERVER: Cached mesh will be stored on the server side (GPU), which may speed up rendering but will use more VRAM to store the mesh.\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.hand_acceleration\": \"Enable Hand Acceleration\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.hand_acceleration.tooltip\": \"- DISABLED: Accelerated Rendering will not accelerate item models that are marked as \\\"too small to make up the cost of acceleration\\\" when rendering it in hand unless mods explicitly enable it temporarily when rendering their own item models.\\n- ENABLED: Accelerated Rendering will still accelerate item models that are marked as \\\"too small to make up the cost of acceleration\\\" when rendering it in hand unless mods explicitly disable it temporarily when rendering their own item models, which may slightly reduce the FPS but accelerate vanilla-like modded item models with large amount of vertices.\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.gui_acceleration\": \"Enable GUI Acceleration\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.gui_acceleration.tooltip\": \"- DISABLED: Accelerated Rendering will not accelerate item models that are marked as \\\"too small to make up the cost of acceleration\\\" when rendering it in a container GUI unless mods explicitly enable it temporarily when rendering their own item models.\\n- ENABLED: Accelerated Rendering will still accelerate item models that are marked as \\\"too small to make up the cost of acceleration\\\" when rendering it in a container GUI unless mods explicitly disable it temporarily when rendering their own item models, which may slightly reduce the FPS but accelerate vanilla-like modded item models with large amount of vertices.\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.gui_item_batching\": \"Enable GUI Item Batching\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.gui_item_batching.tooltip\": \"- DISABLED: Items in the container GUI will be rendered as per item per batch if the GUI Acceleration is enabled, which is inefficient and may cause reduction in FPS, but it has better compatibility in modded container GUI.\\n- ENABLED: Items in the container GUI will be rendered together in a single batch if the GUI Acceleration is enabled, which is much more efficient but has little compatibility in modded container GUI.\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.merge_gui_item_batching\": \"Enable Merge GUI Item Batches\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.merge_gui_item_batching.tooltip\": \"- DISABLED: Items rendered in background and slots will be separated into two batches when accelerate container GUI, which is inefficient any may cause slight reduction in FPS, but it has better compatibility in modded container GUI.\\n- ENABLED: Items rendered in background and slots will be merged into a single batch when accelerate container GUI, which is much more efficient but has less compatibility in modded container GUI.\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.button\": \"Configure\",\n  \"acceleratedrendering.configuration.accelerated_text_rendering\": \"Accelerated Text Rendering Settings\",\n  \"acceleratedrendering.configuration.accelerated_text_rendering.tooltip\": \"Accelerated Text Rendering uses GPU to cache and transform vertices whiling rendering text through BakedGlyph, instead of generating and transforming vertices every time the text are rendered in CPU.\",\n  \"acceleratedrendering.configuration.accelerated_text_rendering.feature_status\": \"Enable Accelerated Text Rendering\",\n  \"acceleratedrendering.configuration.accelerated_text_rendering.feature_status.tooltip\": \"- DISABLED: Disable accelerated text rendering.\\n- ENABLED: Enable accelerated text rendering.\",\n  \"acceleratedrendering.configuration.accelerated_text_rendering.default_pipeline\": \"Default Rendering Pipeline\",\n  \"acceleratedrendering.configuration.accelerated_text_rendering.default_pipeline.tooltip\": \"- VANILLA: Text will not be rendered into the accelerated pipeline unless mods explicitly enable it temporarily when rendering their own text.\\n- ACCELERATED: All text will be rendered in the accelerated pipeline unless mods explicitly disable it temporarily when rendering their own text.\",\n  \"acceleratedrendering.configuration.accelerated_text_rendering.mesh_type\": \"Cached Mesh Type\",\n  \"acceleratedrendering.configuration.accelerated_text_rendering.mesh_type.tooltip\": \"- CLIENT: Cached mesh will be stored on the client side (CPU), which will use less VRAM but take more time to upload to the server side (GPU) during rendering.\\n- SERVER: Cached mesh will be stored on the server side (GPU), which may speed up rendering but will use more VRAM to store the mesh.\",\n  \"acceleratedrendering.configuration.accelerated_text_rendering.button\": \"Configure\",\n  \"acceleratedrendering.configuration.orientation_culling\": \"Simple Orientation Face Culling Settings\",\n  \"acceleratedrendering.configuration.orientation_culling.tooltip\": \"Simple orientation face culling uses an compute shader before the draw call to discard faces that is not visible on screen by checking if it is facing to the screen using a determinant of 3 * 3 matrix.\",\n  \"acceleratedrendering.configuration.orientation_culling.feature_status\": \"Enable Simple Orientation Face Culling\",\n  \"acceleratedrendering.configuration.orientation_culling.feature_status.tooltip\": \"- DISABLED: Disable simple orientation face culling.\\n- ENABLED: Enable simple orientation face culling.\",\n  \"acceleratedrendering.configuration.orientation_culling.default_culling\": \"Default Culling Setting\",\n  \"acceleratedrendering.configuration.orientation_culling.default_culling.tooltip\": \"- DISABLED: Faces will not be culled unless mods explicitly enable it temporarily when rendering their own faces.\\n- ENABLED: All faces will be culled unless mods explicitly disable it temporarily when rendering their own faces.\",\n  \"acceleratedrendering.configuration.orientation_culling.ignore_cull_state\": \"Ignore Cull State\",\n  \"acceleratedrendering.configuration.orientation_culling.ignore_cull_state.tooltip\": \"- DISABLED: Simple orientation face culling will not cull entities that are not declared as \\\"cullable\\\".\\n- ENABLED: Simple orientation face culling will cull all entities even if they are not declared as \\\"cullable\\\", which may cause slightly visual differences.\",\n  \"acceleratedrendering.configuration.orientation_culling.button\": \"Configure\",\n  \"acceleratedrendering.configuration.filter\": \"Filters Settings\",\n  \"acceleratedrendering.configuration.filter.tooltip\": \"Filters allows you to prevent specific entities/block entities/items from being accelerated when rendering for better compatibility.\",\n  \"acceleratedrendering.configuration.filter.feature_status\": \"Enable Filters\",\n  \"acceleratedrendering.configuration.filter.feature_status.tooltip\": \"- DISABLED: Filters will be disabled and all entities, block entities and items will be accelerated when rendering.\\n- ENABLED: Filters will test if the entities, block entities and items should be accelerated when rendering based on the filter values and the filter type.\",\n  \"acceleratedrendering.configuration.filter.menu_filter\": \"Enable Menu Filter\",\n  \"acceleratedrendering.configuration.filter.menu_filter.tooltip\": \"- DISABLED: Menu filter will be disabled and geometries in all container GUI will be accelerated.\\n- ENABLED: Menu filter will test if geometries in specific container GUI should be accelerated when rendering based on the filter values and the filter type.\",\n  \"acceleratedrendering.configuration.filter.entity_filter\": \"Enable Entity Filter\",\n  \"acceleratedrendering.configuration.filter.entity_filter.tooltip\": \"- DISABLED: Entity filter will be disabled and all entities will be accelerated.\\n- ENABLED: Entity filter will test if the entities should be accelerated when rendering based on the filter values and the filter type.\",\n  \"acceleratedrendering.configuration.filter.block_entity_filter\": \"Enable Block Entity Filter\",\n  \"acceleratedrendering.configuration.filter.block_entity_filter.tooltip\": \"- DISABLED: Block entity filter will be disabled and all block entities will be accelerated.\\n- ENABLED: Block entity filter will test if the block entities should be accelerated when rendering based on the filter values and the filter type.\",\n  \"acceleratedrendering.configuration.filter.item_filter\": \"Enable Item Filter\",\n  \"acceleratedrendering.configuration.filter.item_filter.tooltip\": \"- DISABLED: Item filter will be disabled and all items will be accelerated.\\n- ENABLED: Item filter will test if the items should be accelerated when rendering based on the filter values and the filter type.\",\n  \"acceleratedrendering.configuration.filter.stage_filter\": \"Enable Custom Rendering Stage Filter\",\n  \"acceleratedrendering.configuration.filter.stage_filter.tooltip\": \"- DISABLED: Custom rendering stage filter will be disabled and geometries in all custom rendering stages will be accelerated.\\n- ENABLED: Custom rendering stage filter will test if geometries in specific custom rendering stage should be accelerated when rendering based on the filter values and the filter type.\",\n  \"acceleratedrendering.configuration.filter.menu_filter_type\": \"Menu Filter Type\",\n  \"acceleratedrendering.configuration.filter.menu_filter_type.tooltip\": \"- BLACKLIST: Container GUIs that are not in the filter values can pass the filter and be accelerated when rendering.\\n- WHITELIST: Container GUIs that are in the filter values can pass the filter and be accelerated when rendering.\",\n  \"acceleratedrendering.configuration.filter.entity_filter_type\": \"Entity Filter Type\",\n  \"acceleratedrendering.configuration.filter.entity_filter_type.tooltip\": \"- BLACKLIST: Entities that are not in the filter values can pass the filter and be accelerated when rendering.\\n- WHITELIST: Entities that are in the filter values can pass the filter and be accelerated when rendering.\",\n  \"acceleratedrendering.configuration.filter.block_entity_filter_type\": \"Block Entity Filter Type\",\n  \"acceleratedrendering.configuration.filter.block_entity_filter_type.tooltip\": \"- BLACKLIST: Block entities that are not in the filter values can pass the filter and be accelerated when rendering.\\n- WHITELIST: Block entities that are in the filter values can pass the filter and be accelerated when rendering.\",\n  \"acceleratedrendering.configuration.filter.item_filter_type\": \"Item Filter Type\",\n  \"acceleratedrendering.configuration.filter.item_filter_type.tooltip\": \"- BLACKLIST: Items that are not in the filter values can pass the filter and be accelerated when rendering.\\n- WHITELIST: Items that are in the filter values can pass the filter and be accelerated when rendering.\",\n  \"acceleratedrendering.configuration.filter.stage_filter_type\": \"Custom Rendering Stage Filter Type\",\n  \"acceleratedrendering.configuration.filter.stage_filter_type.tooltip\": \"- BLACKLIST: Custom rendering stages that are not in the filter values can pass the filter and be accelerated when rendering.\\n- WHITELIST: Custom rendering stages that are in the filter values can pass the filter and be accelerated when rendering.\",\n  \"acceleratedrendering.configuration.filter.menu_filter_values\": \"Menu Filter Values\",\n  \"acceleratedrendering.configuration.filter.menu_filter_values.tooltip\": \"You can configure the menu filter by this list.\\nMenu filter will use this list and the filter type to determine if a container GUI can pass the filter.\",\n  \"acceleratedrendering.configuration.filter.entity_filter_values\": \"Entity Filter Values\",\n  \"acceleratedrendering.configuration.filter.entity_filter_values.tooltip\": \"You can configure the entity filter by this list.\\nEntity filter will use this list and the filter type to determine if an entity can pass the filter.\",\n  \"acceleratedrendering.configuration.filter.block_entity_filter_values\": \"Block Entity Filter Values\",\n  \"acceleratedrendering.configuration.filter.block_entity_filter_values.tooltip\": \"You can configure the block entity filter by this list.\\nBlock entity filter will use this list and the filter type to determine if a block entity can pass the filter.\",\n  \"acceleratedrendering.configuration.filter.item_filter_values\": \"Item Filter Values\",\n  \"acceleratedrendering.configuration.filter.item_filter_values.tooltip\": \"You can configure the item filter by this list.\\nItem filter will use this list and the filter type to determine if an item can pass the filter.\",\n  \"acceleratedrendering.configuration.filter.stage_filter_values\": \"Custom Rendering Stage Filter Values\",\n  \"acceleratedrendering.configuration.filter.stage_filter_values.tooltip\": \"You can configure the custom rendering stage filter by this list.\\nCustom rendering stage filter will use this list and the filter type to determine if a custom rendering stage can pass the filter.\\nIt's not recommend to modify this list unless other mods adds their own custom rendering stages.\",\n  \"acceleratedrendering.configuration.filter.menu_filter_values.button\": \"Configure\",\n  \"acceleratedrendering.configuration.filter.entity_filter_values.button\": \"Configure\",\n  \"acceleratedrendering.configuration.filter.block_entity_filter_values.button\": \"Configure\",\n  \"acceleratedrendering.configuration.filter.item_filter_values.button\": \"Configure\",\n  \"acceleratedrendering.configuration.filter.stage_filter_values.button\": \"Configure\",\n  \"acceleratedrendering.configuration.filter.button\": \"Configure\",\n  \"acceleratedrendering.configuration.iris_compatibility\": \"Iris Compatibility Settings\",\n  \"acceleratedrendering.configuration.iris_compatibility.tooltip\": \"Iris Compatibility Settings allows Accelerated Rendering to work correctly with Iris.\",\n  \"acceleratedrendering.configuration.iris_compatibility.feature_status\": \"Enable Iris Compatibility\",\n  \"acceleratedrendering.configuration.iris_compatibility.feature_status.tooltip\": \"- DISABLED: Accelerated Rendering will be incompatible with Iris and cause visual glitches when working with Iris.\\n- ENABLED: Accelerated Rendering will use compute shaders that fits Iris's vertex formats, which make it compatible with Iris.\",\n  \"acceleratedrendering.configuration.iris_compatibility.orientation_culling_compatibility\": \"Enable Simple Orientation Culling Compatibility\",\n  \"acceleratedrendering.configuration.iris_compatibility.orientation_culling_compatibility.tooltip\": \"- DISABLED: Simple orientation face culling will not work with Iris because the culling shader is for vanilla's vertex formats.\\n- ENABLED: Simple orientation face culling will use another culling shader that fits iris's vertex format, which make it compatible with Iris.\",\n  \"acceleratedrendering.configuration.iris_compatibility.shadow_culling\": \"Enable Shadow Culling\",\n  \"acceleratedrendering.configuration.iris_compatibility.shadow_culling.tooltip\": \"- DISABLED: Entities will not be culled when they are rendered as shadows unless mods explicitly enable it temporarily when rendering their own shadows. Which reduce FPS due to redundant faces.\\n- ENABLED: Entities will be culled when they are rendered as shadows unless mods explicitly disable it temporarily when rendering their own shadows. Redundant faces will be culled and improve FPS, but it may cause incorrect shadows.\",\n  \"acceleratedrendering.configuration.iris_compatibility.polygon_processing\": \"Enable Polygon Processing\",\n  \"acceleratedrendering.configuration.iris_compatibility.polygon_processing.tooltip\": \"- DISABLED: Extra information in vertices provided by Iris will not be included or calculated in the accelerated pipeline unless mods explicitly enable it temporarily when rendering their own faces, which may cause visual glitches or incorrect rendering.\\n- ENABLED: Extra information in vertices provided by Iris will be included and calculated in the accelerated pipeline by a compute shader unless mods explicitly disable it temporarily when rendering their own faces.\",\n  \"acceleratedrendering.configuration.iris_compatibility.button\": \"Configure\",\n  \"acceleratedrendering.configuration.curios_compatibility\": \"Curios Compatibility Settings\",\n  \"acceleratedrendering.configuration.curios_compatibility.tooltip\": \"Curios Compatibility Settings allows Accelerated Rendering to work correctly with Curios.\",\n  \"acceleratedrendering.configuration.curios_compatibility.feature_status\": \"Enable Curios Compatibility\",\n  \"acceleratedrendering.configuration.curios_compatibility.feature_status.tooltip\": \"- DISABLED: Accelerated Rendering will not interrupt the acceleration of the Curios layer on entities.\\n- ENABLED: Accelerated Rendering will interrupt the acceleration of Curios layer on entities to prevent some mods using extremely bad rendering code that breaks the caching of Accelerated Rendering.\",\n  \"acceleratedrendering.configuration.curios_compatibility.layer_acceleration\": \"Enable Curios Layer Acceleration\",\n  \"acceleratedrendering.configuration.curios_compatibility.layer_acceleration.tooltip\": \"- DISABLED: Curios layer will not be accelerated by default to prevent some mods using extremely bad rendering code that breaks the caching of Accelerated Rendering unless mods explicitly enable the acceleration when rendering their accessories or equipments.\\n- ENABLED: Curios layer will be accelerated by default unless mods explicitly enable the acceleration when rendering their accessories or equipments.\",\n  \"acceleratedrendering.configuration.curios_compatibility.item_filter\": \"Enable Curios Item Filter\",\n  \"acceleratedrendering.configuration.curios_compatibility.item_filter.tooltip\": \"- DISABLED: Curios item filter will be disabled and acceleration of the rendering of all curios accessories/equipments will be determined by the \\\"layer acceleration\\\" option.\\n- ENABLED: Curios item filter will test if the acceleration of the curios accessories/equipments should be prevented based on the filter values and the filter type.\",\n  \"acceleratedrendering.configuration.curios_compatibility.item_filter_type\": \"Curios Item Filter Type\",\n  \"acceleratedrendering.configuration.curios_compatibility.item_filter_type.tooltip\": \"- BLACKLIST: Curios items that are not in the filter values can pass the filter and not being prevented to be accelerated.\\\"\\n- WHITELIST: Curios items that are in the filter values can pass the filter and not being prevented to be accelerated.\\\"\",\n  \"acceleratedrendering.configuration.curios_compatibility.item_filter_values\": \"Curios Item Filter Values\",\n  \"acceleratedrendering.configuration.curios_compatibility.item_filter_values.tooltip\": \"You can configure the curios item filter by this list.\\nCurios item filter will use this list and the filter type to determine if a curios item can pass the filter.\",\n  \"acceleratedrendering.configuration.curios_compatibility.item_filter_values.button\": \"Configure\",\n  \"acceleratedrendering.configuration.curios_compatibility.button\": \"Configure\"\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/lang/zh_cn.json",
    "content": "{\n  \"acceleratedrendering.configuration.title\": \"加速渲染配置项\",\n  \"acceleratedrendering.configuration.section.acceleratedrendering.client.toml.title\": \"加速渲染客户端配置项\",\n  \"acceleratedrendering.configuration.section.acceleratedrendering.client.toml\": \"用于配置由加速渲染提供的优化特性的配置项目录\",\n  \"acceleratedrendering.configuration.core_settings\": \"核心配置\",\n  \"acceleratedrendering.configuration.core_settings.tooltip\": \"核心配置包含了能影响所有渲染特性的配置\",\n  \"acceleratedrendering.configuration.core_settings.pooled_ring_buffer_size\": \"环形缓存池最大数量\",\n  \"acceleratedrendering.configuration.core_settings.pooled_ring_buffer_size.tooltip\": \"修改此项数值可能会影响FPS, 越高的值代表允许越多\\\"in-flight frames\\\", 反之亦然. 允许的\\\"in-flight frames\\\"越多, 提升的FPS越多, 但占用的显存也越多.\",\n  \"acceleratedrendering.configuration.core_settings.pooled_batching_size\": \"单次绘制最大允许合批数量\",\n  \"acceleratedrendering.configuration.core_settings.pooled_batching_size.tooltip\": \"修改此项数值可能会影响FPS, 越高的值代表允许越多RenderType合并在一次绘制中, 反之亦然, 允许的数量越多, 提升的FPS越多, 但是占用的显存越多, 并且消耗更多CPU资源处理合批.\",\n  \"acceleratedrendering.configuration.core_settings.cached_image_size\": \"缓存贴图最大数量\",\n  \"acceleratedrendering.configuration.core_settings.cached_image_size.tooltip\": \"修改此项数值可能会影响FPS, 越高的值代表允许越多缓存贴图, 反之亦然, 允许的数量越多, 提升的FPS越多, 但是占用的内存越多.\",\n  \"acceleratedrendering.configuration.core_settings.dynamic_uv_resolution\": \"动态RenderType缓存UV分辨率\",\n  \"acceleratedrendering.configuration.core_settings.dynamic_uv_resolution.tooltip\": \"修改此项数值可能会影响和显存占用. 越小的值代表越低的UV滚动分辨率和越少的被缓存的RenderType, 反之亦然. 分辨率越高, 闪电苦力怕和旋风人的动画越流畅, 但是占用的显存越多.\",\n  \"acceleratedrendering.configuration.core_settings.debug_context\": \"启用调试上下文\",\n  \"acceleratedrendering.configuration.core_settings.debug_context.tooltip\": \"- DISABLED: 调试上下文将会被禁用, 可能会在部分启用\\\"theaded optimization\\\"的NVIDIA显卡上有严重视觉错误.\\n- ENABLED: 调试上下文将会被启用, 以阻止会NVIDIA显卡驱动应用会导致严重视觉错误的\\\"threaded optimization\\\".\",\n  \"acceleratedrendering.configuration.core_settings.force_translucent_acceleration\": \"启用强制加速半透明\",\n  \"acceleratedrendering.configuration.core_settings.force_translucent_acceleration.tooltip\": \"- DISABLED: 除非其他MOD在渲染其面片时显示声明加速半透明, 否则被标记为半透明的RenderType将会在加速管线不支持半透明排序时使用原版渲染管线.\\n- ENABLED: 除非其他MOD在渲染其面片时显式声明关闭强制半透明加速, 否则即使加速管线不支持半透明排序, 被标记为半透明的RenderType依然会使用加速管线进行渲染.\",\n  \"acceleratedrendering.configuration.core_settings.cache_identical_pose\": \"启用相同变换缓存\",\n  \"acceleratedrendering.configuration.core_settings.cache_identical_pose.tooltip\": \"- DISABLED: 除非其他MOD在渲染其面片时显示声明开启相同变换缓存, 否则具有相同变换矩阵和法线矩阵的变化将不会缓存, 部分降低CPU计算压力但是占用更多显存.\\n- ENABLED: 除非其他MOD在渲染其面片时显式声明关闭相同变换缓存, 否则具有相同变换矩阵和法线矩阵的变化将会使用缓存中已有的数据, 小幅提升CPU计算压力但是占用更少显存.\",\n  \"acceleratedrendering.configuration.core_settings.mesh_info_cache_type\": \"模型实例缓存类型\",\n  \"acceleratedrendering.configuration.core_settings.mesh_info_cache_type.tooltip\": \"- SIMPLE: 最基础的缓存实现, 通常用来检测其他缓存类型是否正常工作.\\n- HANDLE: 更快的缓存实现, 使用VarHandle和扁平化数据来提高读写性能.\\n- UNSAFE: 最快的缓存实现, 使用了不安全的内存操作来跳过多项检查进行读写.\",\n  \"acceleratedrendering.configuration.core_settings.layer_storage_type\": \"合批层储存类型\",\n  \"acceleratedrendering.configuration.core_settings.layer_storage_type.tooltip\": \"- SORTED: 最基础的实现, 将不透明与半透明模型一同在一个单独的阶段中进行渲染, 性能更好但可能造成半透明模型的视觉错误.\\n- SEPARATED: 视觉上更精确的实现, 将不透明与半透明模型分至两个单独的阶段渲染以防止视觉错误, 略慢于基础实现.\",\n  \"acceleratedrendering.configuration.core_settings.mesh_merge_type\": \"模型合并类型\",\n  \"acceleratedrendering.configuration.core_settings.mesh_merge_type.tooltip\": \"- IGNORED: 拥有完全一致顶点的模型将不会被合并, 占用的内存更少但是为储存重复模型占用的显存更多.\\n- MERGED: 拥有完全一致顶点的模型将会被合并, 占用的显存更少但为储存合并所需要的信息所占用的内存更多.\",\n  \"acceleratedrendering.configuration.core_settings.upload_mesh_immediately\": \"启用立即上传模型\",\n  \"acceleratedrendering.configuration.core_settings.upload_mesh_immediately.tooltip\": \"- DISABLED: 将要被加速的模型将会被统计收集并在最后统一上传以选择更好的上传方法和更好的内存访问效率, 同时这个方法允许更多(2GB以上直到显存限制)的模型缓存容量, 但这个方式可能不会按照正常渲染顺序并造成部分渲染异常.\\n- ENABLED: 将要被加速的模型将会在绘制指令后立即上传, 这样相对更低效, 且只有通常2GB左右的模型缓存(大多数情况下足够了), 但是能保证绘制顺序一致以提供最好的兼容性.\",\n  \"acceleratedrendering.configuration.core_settings.cache_dynamic_render_type\": \"启用缓存动态RenderType\",\n  \"acceleratedrendering.configuration.core_settings.cache_dynamic_render_type.tooltip\": \"- DISABLED: 诸如闪电苦力怕的闪电和旋风人的风所使用的动态RenderType将不会被加速, 占用更少显存的同时动画更流畅, 但可能意外跳过其他MOD使用这些动态RenderType进行渲染的模型的加速.\\n- ENABLED: 诸如闪电苦力怕的闪电和旋风人的风所使用的动态RenderType将会被加速以加速其他MOD使用这些动态RenderType进行渲染的模型, 但是占用更多显存, 以及基于分辨率设置可能导致的不太流畅的动画.\",\n  \"acceleratedrendering.configuration.core_settings.viewport_binding_state\": \"可视区域还原类型\",\n  \"acceleratedrendering.configuration.core_settings.viewport_binding_state.tooltip\": \"- IGNORED: 禁用可视区域还原, 更快, 但可能降低了对修改了可视区域的MOD兼容性.\\n- MOJANG: 使用Mojang提供的GLStateManager对可能被其他MOD修改的可视区域进行记录和还原, 以改善兼容性.\\n- OPENGL: 使用OpenGL对可能被其他MOD修改的可视区域进行记录和还原, 以在即使MOD不使用Mojang提供的GLStateManager的情况下改善兼容性, 略慢但能保证最佳兼容性.\",\n  \"acceleratedrendering.configuration.core_settings.scissor_binding_state\": \"裁切区域还原类型\",\n  \"acceleratedrendering.configuration.core_settings.scissor_binding_state.tooltip\": \"- IGNORED: 禁用裁切区域还原, 更快, 但可能降低了对修改了裁切区域的MOD兼容性.\\n- MOJANG: 使用Mojang提供的GuiGraphics对可能被其他MOD修改的裁切区域进行记录和还原, 以改善兼容性.\\n- OPENGL: 使用OpenGL对可能被其他MOD修改的裁切区域进行记录和还原, 以在即使MOD不使用Mojang提供的GuiGraphics的情况下改善兼容性, 略慢但能保证最佳兼容性.\",\n  \"acceleratedrendering.configuration.core_settings.button\": \"配置\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring\": \"块缓冲还原配置\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.tooltip\": \"部分MOD和光影会使用块缓冲进行渲染, 可能会与同样使用块缓冲的加速渲染造成冲突.\\n块缓冲还原可以在加速前记录块缓冲绑定, 在加速后还原成加速前的块缓冲绑定以实现更好的兼容性\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.feature_status\": \"启用块缓冲还原\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.feature_status.tooltip\": \"- DISABLED: 禁用块缓冲还原, 速度更快但可能与使用块缓冲的MOD和光影冲突.\\n- ENABLED: 启用块缓冲还原, 速度可能由于需要记录和还原块缓冲绑定而略慢, 但能确保在使用了块缓冲的MOD和光影的环境中正常工作.\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.binding_cache_type\": \"块缓冲绑定缓存类型\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.binding_cache_type.tooltip\": \"- SIMPLE: 最基础的缓存实现, 通常用来检测其他缓存类型是否正常工作.\\n- HANDLE: 更快的缓存实现, 使用VarHandle和扁平化数据来提高读写性能.\\n- UNSAFE: 最快的缓存实现, 使用了不安全的内存操作来跳过多项检查进行读写.\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.shader_storage_type\": \"着色器储存缓冲还原类型\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.shader_storage_type.tooltip\": \"- IGNORED: 着色器储存缓冲的还原将被忽略, 可以改善FPS但可能降低与使用了着色器储存缓冲的MOD和光影的兼容性.\\n- RESTORED: 着色器储存缓冲将被记录和还原, 可能略微降低FPS但与使用了着色器储存缓冲的MOD和光影有更好的兼容性.\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.atomic_counter_type\": \"原子计数器缓冲还原类型\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.atomic_counter_type.tooltip\": \"- IGNORED: 原子计数器缓冲的还原将被忽略, 可以改善FPS但可能降低与使用了原子计数器缓冲的MOD和光影的兼容性.\\n- RESTORED: 原子计数器缓冲将被记录和还原, 可能略微降低FPS但与使用了原子计数器缓冲的MOD和光影有更好的兼容性.\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.shader_storage_range\": \"着色器储存缓冲还原范围\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.shader_storage_range.tooltip\": \"将要被记录和还原的着色器储存缓冲绑定点范围.\\n修改此项数值可能会影响FPS. 越高的值代表越大的着色器储存缓冲还原范围和更好的兼容性, 越小的值代表越少的着色器储存缓冲还原范围但更差的兼容性, 还原范围越大, 开销造成的FPS降低越大.\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.atomic_counter_range\": \"原子计数器缓冲还原范围\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.atomic_counter_range.tooltip\": \"将要被记录和还原的原子计数器缓冲绑定点范围.\\n修改此项数值可能会影响FPS. 越高的值代表越大的原子计数器缓冲还原范围和更好的兼容性, 越小的值代表越少的原子计数器缓冲还原范围但更差的兼容性, 还原范围越大, 开销造成的FPS降低越大.\",\n  \"acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.button\": \"配置\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering\": \"加速实体渲染配置\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.tooltip\": \"加速实体渲染使用GPU对ModelPart进行缓存和顶点变换, 而非原版在CPU每次渲染时重建和变换顶点.\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.feature_status\": \"启用加速实体渲染\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.feature_status.tooltip\": \"- DISABLED: 禁用加速实体渲染.\\n- ENABLED: 启用加速实体渲染.\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.default_pipeline\": \"默认渲染管线\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.default_pipeline.tooltip\": \"- VANILLA: 除非其他MOD在渲染其实体时显式声明临时开启加速渲染, 否则实体将不会通过加速管线渲染.\\n- ACCELERATED: 除非其他MOD在渲染其实体时时显式声明临时关闭加速渲染, 否则实体将始终通过加速管线渲染.\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.mesh_type\": \"模型缓存类型\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.mesh_type.tooltip\": \"- CLIENT: 模型将缓存在客户端(CPU)侧, 占用更少显存, 但渲染时可能会耗费额外时间上传至服务端侧(GPU).\\n- SERVER: 模型将缓存在服务端(GPU)侧, 获得更好的渲染性能, 但会占用更多显存.\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.gui_acceleration\": \"启用GUI实体加速\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.gui_acceleration.tooltip\": \"- DISABLED: 除非其他MOD在渲染其实体时显式声明临时开启GUI实体加速, 实体将不会在GUI绘制中被加速渲染.\\n- ENABLED: 除非其他MOD在渲染其实体时显式声明临时关闭GUI实体加速, 实体将始终会在GUI绘制中被加速渲染.\",\n  \"acceleratedrendering.configuration.accelerated_entity_rendering.button\": \"配置\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering\": \"加速物品渲染配置\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.tooltip\": \"加速物品渲染使用GPU对物品模型进行缓存和顶点变换, 而非原版在CPU每次渲染时重建和变换顶点.\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.feature_status\": \"启用加速物品渲染\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.feature_status.tooltip\": \"- DISABLED: 禁用加速物品渲染.\\n- ENABLED: 启用加速物品渲染.\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.bake_mesh_for_quads\": \"为动态面缓存\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.bake_mesh_for_quads.tooltip\": \"- DISABLED: 除非MOD在渲染其物品模型时显式声明开启动态面缓存, 否则加速渲染将不会为动态物品模型(不属于SimpleBakedModel的模型)提供的面进行模型缓存.\\n- ENABLED: 除非MOD在渲染其物品模型时显式声明临时关闭动态面缓存, 否则加速渲染将会为所有动态物品模型(不属于SimpleBakedModel的模型)提供的面进行模型缓存, 加速动态物品模型的渲染, 但如果动态物品模型一直分配新的面数据则有可能崩溃. (没人这么干, 就算这么干了, 那也是他们的错)\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.default_pipeline\": \"默认渲染管线\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.default_pipeline.tooltip\": \"- VANILLA: 除非其他MOD在渲染其物品模型时显式声明临时开启加速渲染, 否则物品模型将不会通过加速管线渲染.\\n- ACCELERATED: 除非其他MOD在渲染其物品模型时时显式声明临时关闭加速渲染, 否则物品模型将始终通过加速管线渲染.\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.mesh_type\": \"模型缓存类型\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.mesh_type.tooltip\": \"- CLIENT: 模型将缓存在客户端(CPU)侧, 占用更少显存, 但渲染时可能会耗费额外时间上传至服务端侧(GPU).\\n- SERVER: 模型将缓存在服务端(GPU)侧, 获得更好的渲染性能, 但会占用更多显存.\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.hand_acceleration\": \"启用手中物品加速\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.hand_acceleration.tooltip\": \"- DISABLED: 除非其他MOD在渲染其物品模型时显式声明临时开启手中物品加速, 否则加速渲染将不会在渲染手中物品时加速那些被标记为\\\"太过简单加速后无法弥补加速带来的开销\\\"的模型.\\n- ENABLED: 除非其他MOD在渲染其物品模型时显式声明临时关闭手中物品加速, 否则加速渲染将仍然会在渲染手中物品时加速那些被标记为\\\"太过简单加速后无法弥补加速带来的开销\\\"的模型, 这可能会造成额外开销轻微降低FPS, 但是允许加速那些拥有大量顶点的类原版MOD物品模型.\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.gui_acceleration\": \"启用GUI物品加速\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.gui_acceleration.tooltip\": \"- DISABLED: 除非其他MOD在渲染其物品模型时显式声明临时开启GUI物品加速, 否则加速渲染将不会在渲染容器GUI时加速那些被标记为\\\"太过简单加速后无法弥补加速带来的开销\\\"的模型.\\n- ENABLED: 除非其他MOD在渲染其物品模型时显式声明临时关闭GUI物品加速, 否则加速渲染将仍然会在渲染容器GUI时加速那些被标记为\\\"太过简单加速后无法弥补加速带来的开销\\\"的模型, 这可能会造成额外开销轻微降低FPS, 但是允许加速那些拥有大量顶点的类原版MOD物品模型.\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.gui_item_batching\": \"启用GUI物品合批\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.gui_item_batching.tooltip\": \"- DISABLED: 当GUI物品加速开启时, 在容器GUI中被渲染的物品将以每渲染一次物品就执行一次绘制的方式进行渲染, 这样比较低效并对FPS造成较大影响, 但拥有更好的MOD兼容性.\\n- ENABLED: 当GUI物品加速开启时, 在容器GUI中被渲染的物品将会统一收集至一次合批中绘制, 这样极大提升了渲染效率但是对MOD的容器GUI兼容性较差.\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.merge_gui_item_batching\": \"启用合并GUI物品批次\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.merge_gui_item_batching.tooltip\": \"- DISABLED: 当GUI物品合批时, 背景和物品栏渲染的物品将独立分为两个批次进行绘制, 这样比较低效并对FPS有轻微影响, 但拥有更好的MOD兼容性.\\n- ENABLED: 当GUI物品合批时, 背景和物品栏渲染的物品将合并为一个单独的批次进行绘制, 这样提升了渲染效率但是对MOD的容器GUI兼容性较差.\",\n  \"acceleratedrendering.configuration.accelerated_item_rendering.button\": \"配置\",\n  \"acceleratedrendering.configuration.accelerated_text_rendering\": \"加速文字渲染配置\",\n  \"acceleratedrendering.configuration.accelerated_text_rendering.tooltip\": \"加速文字渲染使用GPU对BakedGlyph进行缓存和顶点变换, 而非原版在CPU每次渲染时重建和变换顶点.\",\n  \"acceleratedrendering.configuration.accelerated_text_rendering.feature_status\": \"启用加速文字渲染\",\n  \"acceleratedrendering.configuration.accelerated_text_rendering.feature_status.tooltip\": \"- DISABLED: 禁用加速文字渲染.\\n- ENABLED: 启用加速文字渲染.\",\n  \"acceleratedrendering.configuration.accelerated_text_rendering.default_pipeline\": \"默认渲染管线\",\n  \"acceleratedrendering.configuration.accelerated_text_rendering.default_pipeline.tooltip\": \"- VANILLA: 除非其他MOD在渲染其文字时显式声明临时开启加速渲染, 否则文字将不会通过加速管线渲染.\\n- ACCELERATED: 除非其他MOD在渲染其文字时时显式声明临时关闭加速渲染, 否则文字将始终通过加速管线渲染.\",\n  \"acceleratedrendering.configuration.accelerated_text_rendering.mesh_type\": \"模型缓存类型\",\n  \"acceleratedrendering.configuration.accelerated_text_rendering.mesh_type.tooltip\": \"- CLIENT: 模型将缓存在客户端(CPU)侧, 占用更少显存, 但渲染时可能会耗费额外时间上传至服务端侧(GPU).\\n- SERVER: 模型将缓存在服务端(GPU)侧, 获得更好的渲染性能, 但会占用更多显存.\",\n  \"acceleratedrendering.configuration.accelerated_text_rendering.button\": \"配置\",\n  \"acceleratedrendering.configuration.orientation_culling\": \"简单朝向面剔除配置\",\n  \"acceleratedrendering.configuration.orientation_culling.tooltip\": \"简单朝向面剔除在绘制调用前使用一个根据3x3矩阵行列式来判断面是否朝向屏幕的ComputeShader(计算着色器)来剔除在屏幕上不可见的面, 减少需要绘制的面数.\",\n  \"acceleratedrendering.configuration.orientation_culling.feature_status\": \"启用简单朝向面剔除\",\n  \"acceleratedrendering.configuration.orientation_culling.feature_status.tooltip\": \"- DISABLED: 禁用简单朝向面剔除.\\n- ENABLED: 启用简单朝向面剔除.\",\n  \"acceleratedrendering.configuration.orientation_culling.default_culling\": \"默认剔除设置\",\n  \"acceleratedrendering.configuration.orientation_culling.default_culling.tooltip\": \"- DISABLED: 除非其他MOD在渲染其面片时显式声明临时开启简单朝向面剔除, 否则面片将不会被剔除\\n- ENABLED: 除非其他MOD在渲染其面片时显式声明临时关闭简单朝向面剔除, 否则面片将始终被剔除.\",\n  \"acceleratedrendering.configuration.orientation_culling.ignore_cull_state\": \"强制剔除\",\n  \"acceleratedrendering.configuration.orientation_culling.ignore_cull_state.tooltip\": \"- DISABLED: 简单朝向面剔除将不会剔除被声明为不可剔除的实体\\n- ENABLED: 简单朝向面剔除将会对所有实体进行强制剔除, 即使其被声明为不可剔除, 可能会造成轻微渲染差异.\",\n  \"acceleratedrendering.configuration.orientation_culling.button\": \"配置\",\n  \"acceleratedrendering.configuration.filter\": \"过滤器配置\",\n  \"acceleratedrendering.configuration.filter.tooltip\": \"过滤器允许为了兼容性手动配置阻止部分实体/方块/物品在渲染时被加速\",\n  \"acceleratedrendering.configuration.filter.feature_status\": \"启用过滤器\",\n  \"acceleratedrendering.configuration.filter.feature_status.tooltip\": \"- DISABLED: 过滤器将被禁用, 所有的实体/方块实体/物品都将在渲染时被加速.\\n- ENABLED: 过滤器将在渲染实体/方块实体/物品时根据过滤器所配置的列表和过滤器类型判断是否为该实体/方块实体进行加速.\",\n  \"acceleratedrendering.configuration.filter.menu_filter\": \"启用容器GUI过滤器\",\n  \"acceleratedrendering.configuration.filter.menu_filter.tooltip\": \"- DISABLED: 容器GUI过滤器将被禁用, 所有容器GUI中的模型都将被加速.\\n- ENABLED: 容器GUI过滤器将在渲染对容器GUI中的模型时时根据过滤器所配置的列表和过滤器类型判断是否为该模型进行加速.\",\n  \"acceleratedrendering.configuration.filter.entity_filter\": \"启用实体过滤器\",\n  \"acceleratedrendering.configuration.filter.entity_filter.tooltip\": \"- DISABLED: 实体过滤器将被禁用, 所有的实体都将在渲染时被加速.\\n- ENABLED: 实体过滤器将在渲染实体时根据过滤器所配置的列表和过滤器类型判断是否为该实体进行加速.\",\n  \"acceleratedrendering.configuration.filter.block_entity_filter\": \"启用方块实体过滤器\",\n  \"acceleratedrendering.configuration.filter.block_entity_filter.tooltip\": \"- DISABLED: 方块实体过滤器将被禁用, 所有的方块实体都将在渲染时被加速.\\n- ENABLED: 方块实体过滤器将在渲染实体时根据过滤器所配置的列表和过滤器类型判断是否为该方块实体进行加速.\",\n  \"acceleratedrendering.configuration.filter.item_filter\": \"启用物品过滤器\",\n  \"acceleratedrendering.configuration.filter.item_filter.tooltip\": \"- DISABLED: 物品过滤器将被禁用, 所有的物品都将在渲染时被加速.\\n- ENABLED: 物品过滤器将在渲染实体时根据过滤器所配置的列表和过滤器类型判断是否为该物品进行加速.\",\n  \"acceleratedrendering.configuration.filter.stage_filter\": \"启用自定义渲染阶段过滤器\",\n  \"acceleratedrendering.configuration.filter.stage_filter.tooltip\": \"- DISABLED: 自定义渲染阶段过滤器将被禁用, 所有自定义渲染阶段中的模型都将被加速.\\n- ENABLED: 自定义渲染阶段过滤器将在渲染对应自定义渲染阶段中的模型时时根据过滤器所配置的列表和过滤器类型判断是否为该模型进行加速.\",\n  \"acceleratedrendering.configuration.filter.menu_filter_type\": \"容器GUI过滤器类型\",\n  \"acceleratedrendering.configuration.filter.menu_filter_type.tooltip\": \"- BLACKLIST: 不在容器GUI过滤器列表中的容器GUI将通过过滤器并在渲染时加速 (即黑名单).\\n- WHITELIST: 只有在容器GUI过滤器列表中的容器GUI才能通过过滤器并在渲染时加速 (即白名单).\",\n  \"acceleratedrendering.configuration.filter.entity_filter_type\": \"实体过滤器类型\",\n  \"acceleratedrendering.configuration.filter.entity_filter_type.tooltip\": \"- BLACKLIST: 不在实体过滤器列表中的实体类型将通过过滤器并在渲染时加速 (即黑名单).\\n- WHITELIST: 只有在实体过滤器列表中的实体类型才能通过过滤器并在渲染时加速 (即白名单).\",\n  \"acceleratedrendering.configuration.filter.block_entity_filter_type\": \"方块实体过滤器类型\",\n  \"acceleratedrendering.configuration.filter.block_entity_filter_type.tooltip\": \"- BLACKLIST: 不在方块实体过滤器列表中的方块实体类型将通过过滤器并在渲染时加速 (即黑名单).\\n- WHITELIST: 只有在方块实体过滤器列表中的方块实体类型才能通过过滤器并在渲染时加速 (即白名单).\",\n  \"acceleratedrendering.configuration.filter.item_filter_type\": \"物品过滤器类型\",\n  \"acceleratedrendering.configuration.filter.item_filter_type.tooltip\": \" BLACKLIST: 不在物品过滤器列表中的物品将通过过滤器并在渲染时加速 (即黑名单).\\n- WHITELIST: 只有在物品过滤器列表中的物品才能通过过滤器并在渲染时加速 (即白名单).\",\n  \"acceleratedrendering.configuration.filter.stage_filter_type\": \"自定义渲染阶段过滤器类型\",\n  \"acceleratedrendering.configuration.filter.stage_filter_type.tooltip\": \"- BLACKLIST: 不在自定义渲染阶段过滤器列表中的自定义渲染通道将通过过滤器并在渲染时加速 (即黑名单).\\n- WHITELIST: 只有在自定义渲染阶段过滤器列表中的自定义渲染阶段才能通过过滤器并在渲染时加速 (即白名单).\",\n  \"acceleratedrendering.configuration.filter.menu_filter_values\": \"容器GUI过滤器列表\",\n  \"acceleratedrendering.configuration.filter.menu_filter_values.tooltip\": \"你可以通过这个列表配置容器GUI过滤器.\\n容器GUI过滤器将根据这个列表和过滤器类型来判断对应容器GUI能否通过过滤器.\",\n  \"acceleratedrendering.configuration.filter.entity_filter_values\": \"实体过滤器列表\",\n  \"acceleratedrendering.configuration.filter.entity_filter_values.tooltip\": \"你可以通过这个列表配置实体过滤器.\\n实体过滤器将根据这个列表和过滤器类型来判断对应实体能否通过过滤器.\",\n  \"acceleratedrendering.configuration.filter.block_entity_filter_values\": \"方块实体过滤器列表\",\n  \"acceleratedrendering.configuration.filter.block_entity_filter_values.tooltip\": \"你可以通过这个列表配置方块实体过滤器.\\n方块实体过滤器将根据这个列表和过滤器类型来判断对应方块实体能否通过过滤器.\",\n  \"acceleratedrendering.configuration.filter.item_filter_values\": \"物品过滤器列表\",\n  \"acceleratedrendering.configuration.filter.item_filter_values.tooltip\": \"你可以通过这个列表配置物品过滤器.\\n物品过滤器将根据这个列表和过滤器类型来判断对应物品能否通过过滤器.\",\n  \"acceleratedrendering.configuration.filter.stage_filter_values\": \"自定义渲染阶段过滤器列表\",\n  \"acceleratedrendering.configuration.filter.stage_filter_values.tooltip\": \"你可以通过这个列表配置自定义渲染阶段过滤器.\\n自定义渲染阶过滤器将根据这个列表和过滤器类型来判断对应自定义渲染阶能否通过过滤器.\\n除非其他MOD添加了新的自定义渲染阶段, 否则不推荐修改次列表.\",\n  \"acceleratedrendering.configuration.filter.menu_filter_values.button\": \"配置列表\",\n  \"acceleratedrendering.configuration.filter.entity_filter_values.button\": \"配置列表\",\n  \"acceleratedrendering.configuration.filter.block_entity_filter_values.button\": \"配置列表\",\n  \"acceleratedrendering.configuration.filter.item_filter_values.button\": \"配置列表\",\n  \"acceleratedrendering.configuration.filter.stage_filter_values.button\": \"配置列表\",\n  \"acceleratedrendering.configuration.filter.button\": \"配置\",\n  \"acceleratedrendering.configuration.iris_compatibility\": \"Iris兼容性配置\",\n  \"acceleratedrendering.configuration.iris_compatibility.tooltip\": \"Iris兼容性配置允许加速渲染在Iris环境下正常工作.\",\n  \"acceleratedrendering.configuration.iris_compatibility.feature_status\": \"启用Iris兼容性\",\n  \"acceleratedrendering.configuration.iris_compatibility.feature_status.tooltip\": \"- DISABLED: 加速渲染将与Iris不兼容, 并在与Iris一同工作时造成视觉错误.\\n- ENABLED: 加速渲染将使用与Iris顶点格式匹配的兼容Shader用于在Iris环境中正常工作并兼容Iris.\",\n  \"acceleratedrendering.configuration.iris_compatibility.orientation_culling_compatibility\": \"启用朝向法线剔除兼容\",\n  \"acceleratedrendering.configuration.iris_compatibility.orientation_culling_compatibility.tooltip\": \"- DISABLED: 在Iris环境下简单朝向面剔除将不可用, 因为其剔除Shader仅为原版顶点格式设计.\\n- ENABLED: 简单朝向面剔除将使用与Iris顶点格式匹配的兼容Shader用于在Iris环境中正常剔除.\",\n  \"acceleratedrendering.configuration.iris_compatibility.shadow_culling\": \"启用阴影剔除\",\n  \"acceleratedrendering.configuration.iris_compatibility.shadow_culling.tooltip\": \"- DISABLED: 除非其他MOD在渲染其阴影时显示声明启用阴影剔除, 否则当实体渲染阴影时, 多余的面将不会被剔除, 这可能导致由多余面造成的FPS下降.\\n- ENABLED: 除非其他MOD在渲染其阴影时显示声明禁用阴影剔除, 否则当实体渲染阴影时, 多余的面将会被剔除以提升FPS, 但这可能会导致不正确的阴影渲染.\",\n  \"acceleratedrendering.configuration.iris_compatibility.polygon_processing\": \"启用多边形额外数据计算\",\n  \"acceleratedrendering.configuration.iris_compatibility.polygon_processing.tooltip\": \"- DISABLED: 除非其他MOD在渲染其面片时显示声明启用额外数据计算, 否则加速渲染管线将不会计算或上传顶点中由Iris提供的额外信息, 可能会造成视觉错误或不正确的渲染结果.\\n- ENABLED: 除非其他MOD在渲染其面片时显示声明禁用额外数据计算, 否则加速渲染管线将会使用ComputeShader(计算着色器)计算并上传顶点中由Iris提供的额外信息.\",\n  \"acceleratedrendering.configuration.iris_compatibility.button\": \"配置\",\n  \"acceleratedrendering.configuration.curios_compatibility\": \"Curios兼容性配置\",\n  \"acceleratedrendering.configuration.curios_compatibility.tooltip\": \"Curios兼容性配置允许加速渲染在Curios环境下正常工作.\",\n  \"acceleratedrendering.configuration.curios_compatibility.feature_status\": \"启用Curios兼容性\",\n  \"acceleratedrendering.configuration.curios_compatibility.feature_status.tooltip\": \"- DISABLED: 加速渲染将不会中断对于实体中Curios层的加速.\\n- ENABLED: 加速渲染将会终止实体中Curios层的加速防止部分MOD因为过于离谱的渲染代码导致损坏加速渲染的缓存机制.\",\n  \"acceleratedrendering.configuration.curios_compatibility.layer_acceleration\": \"启用Curios层加速\",\n  \"acceleratedrendering.configuration.curios_compatibility.layer_acceleration.tooltip\": \"- DISABLED: 除非其他MOD在渲染其饰品或装备时显式声明启用Curios层加速, 否则加速渲染将不会对Curios层进行加速, 以此确保加速渲染不会因为部分MOD过于离谱的渲染代码导致崩溃.\\n- ENABLED: 除非其他MOD在渲染其饰品或装备时显式声明关闭Curios层加速, 否则加速渲染将会默认开启Curios层加速.\",\n  \"acceleratedrendering.configuration.curios_compatibility.item_filter\": \"启用Curios物品过滤器\",\n  \"acceleratedrendering.configuration.curios_compatibility.item_filter.tooltip\": \"- DISABLED: Curios物品过滤器将被禁用, 所有Curios饰品或装备是否加速都由\\\"启用Curios层加速\\\" (Enable Curios Layer Acceleration) 这个选项控制.\\n- ENABLED: Curios物品过滤器将在渲染Curios饰品或装备时根据过滤器所配置的列表和过滤器类型判断是否阻止没通过过滤器的饰品或装备的加速.\",\n  \"acceleratedrendering.configuration.curios_compatibility.item_filter_type\": \"Curios物品过滤器类型\",\n  \"acceleratedrendering.configuration.curios_compatibility.item_filter_type.tooltip\": \"- BLACKLIST: 不在Curios物品过滤器列表中的Curios物品将通过过滤器 (即黑名单).\\n- WHITELIST: 只有在Curios物品过滤器列表中的Curios物品才能通过过滤器 (即白名单).\",\n  \"acceleratedrendering.configuration.curios_compatibility.item_filter_values\": \"Curios物品过滤器列表\",\n  \"acceleratedrendering.configuration.curios_compatibility.item_filter_values.tooltip\": \"你可以通过这个列表配置Curios物品过滤器.\\nCurios物品过滤器将根据这个列表和过滤器类型来判断对应Curios物品能否通过过滤器.\",\n  \"acceleratedrendering.configuration.curios_compatibility.item_filter_values.button\": \"配置列表\",\n  \"acceleratedrendering.configuration.curios_compatibility.button\": \"配置\"\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/compat/culling/iris_block_quad_culling_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    uint    uv2;\n    uint    normal;\n    uint    iris_entity;\n    uint    iris_data_0;\n    uint    iris_data_1;\n    uint    iris_data_2;\n    uint    iris_data_3;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct Polygon {\n    uint    vertex1;\n    uint    vertex2;\n    uint    vertex3;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict readonly buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4, std430) restrict readonly buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=6, std430) restrict writeonly buffer PolygonsOut {\n    Polygon polygonsOut[];\n};\n\nlayout(binding=0, offset=0) uniform atomic_uint indexCounter;\n\nlayout(location=0) uniform mat4 viewMatrix;\nlayout(location=1) uniform mat4 projectMatrix;\nlayout(location=2) uniform uint polygonCount;\nlayout(location=3) uniform uint vertexOffset;\nlayout(location=4) uniform uint varyingOffset;\n\nvoid main() {\n    uint    index   = gl_GlobalInvocationID.x;\n    uint    base    = index * 4u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint    index0  = varyingOffset + base + 0u;\n    uint    index1  = vertexOffset  + base + 0u;\n    uint    index2  = vertexOffset  + base + 1u;\n    uint    index3  = vertexOffset  + base + 2u;\n    uint    index4  = vertexOffset  + base + 3u;\n    uint    noCull  = varyings[index0 - varyings[index0].offset].noCull;\n\n    Vertex  vertex1 = vertices[index1];\n    Vertex  vertex2 = vertices[index2];\n    Vertex  vertex3 = vertices[index3];\n    Vertex  vertex4 = vertices[index4];\n\n    mat4    matrix  = projectMatrix * viewMatrix;\n    vec4    pos1    = matrix        * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0);\n    vec4    pos2    = matrix        * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0);\n    vec4    pos3    = matrix        * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0);\n    vec4    pos4    = matrix        * vec4(vertex4.x, vertex4.y, vertex4.z, 1.0);\n\n    float   det1    = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw));\n    float   det2    = determinant(mat3(pos3.xyw, pos4.xyw, pos1.xyw));\n\n    if (noCull > 0u || det1 > 0.0 || det2 > 0.0) {\n        uint indexOut                       = atomicCounterAdd(indexCounter, 6u) / 3u;\n\n        polygonsOut[indexOut + 0].vertex1   = index1;\n        polygonsOut[indexOut + 0].vertex2   = index2;\n        polygonsOut[indexOut + 0].vertex3   = index3;\n\n        polygonsOut[indexOut + 1].vertex1   = index3;\n        polygonsOut[indexOut + 1].vertex2   = index4;\n        polygonsOut[indexOut + 1].vertex3   = index1;\n    }\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/compat/culling/iris_block_triangle_culling_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    uint    uv2;\n    uint    normal;\n    uint    iris_entity;\n    uint    iris_data_0;\n    uint    iris_data_1;\n    uint    iris_data_2;\n    uint    iris_data_3;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct Polygon {\n    uint    vertex1;\n    uint    vertex2;\n    uint    vertex3;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict readonly buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4, std430) restrict readonly buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=6, std430) restrict writeonly buffer PolygonsOut {\n    Polygon polygonsOut[];\n};\n\nlayout(binding=0, offset=0) uniform atomic_uint indexCounter;\n\nlayout(location=0) uniform mat4 viewMatrix;\nlayout(location=1) uniform mat4 projectMatrix;\nlayout(location=2) uniform uint polygonCount;\nlayout(location=3) uniform uint vertexOffset;\nlayout(location=4) uniform uint varyingOffset;\n\nvoid main() {\n    uint    index   = gl_GlobalInvocationID.x;\n    uint    base    = index * 3u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint    index0  = varyingOffset + base + 0u;\n    uint    index1  = vertexOffset  + base + 0u;\n    uint    index2  = vertexOffset  + base + 1u;\n    uint    index3  = vertexOffset  + base + 2u;\n    uint    noCull  = varyings[index0 - varyings[index0].offset].noCull;\n\n    Vertex  vertex1 = vertices[index1];\n    Vertex  vertex2 = vertices[index2];\n    Vertex  vertex3 = vertices[index3];\n\n    mat4    matrix  = projectMatrix * viewMatrix;\n    vec4    pos1    = matrix        * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0);\n    vec4    pos2    = matrix        * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0);\n    vec4    pos3    = matrix        * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0);\n\n    float   det     = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw));\n\n    if (noCull > 0u || det > 0.0) {\n        uint indexOut                       = atomicCounterAdd(indexCounter, 3u) / 3u;\n\n        polygonsOut[indexOut + 0].vertex1   = index1;\n        polygonsOut[indexOut + 0].vertex2   = index2;\n        polygonsOut[indexOut + 0].vertex3   = index3;\n    }\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/compat/culling/iris_entity_quad_culling_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    int     uv1;\n    int     uv2;\n    uint    normal;\n    uint    iris_data_0;\n    uint    iris_data_1;\n    uint    iris_data_2;\n    uint    iris_data_3;\n    uint    iris_data_4;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct Polygon {\n    uint    vertex1;\n    uint    vertex2;\n    uint    vertex3;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict readonly buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4, std430) restrict readonly buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=6, std430) restrict writeonly buffer PolygonsOut {\n    Polygon polygonsOut[];\n};\n\nlayout(binding=0, offset=0) uniform atomic_uint indexCounter;\n\nlayout(location=0) uniform mat4 viewMatrix;\nlayout(location=1) uniform mat4 projectMatrix;\nlayout(location=2) uniform uint polygonCount;\nlayout(location=3) uniform uint vertexOffset;\nlayout(location=4) uniform uint varyingOffset;\n\nvoid main() {\n    uint    index   = gl_GlobalInvocationID.x;\n    uint    base    = index * 4u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint    index0  = varyingOffset + base + 0u;\n    uint    index1  = vertexOffset  + base + 0u;\n    uint    index2  = vertexOffset  + base + 1u;\n    uint    index3  = vertexOffset  + base + 2u;\n    uint    index4  = vertexOffset  + base + 3u;\n    uint    noCull  = varyings[index0 - varyings[index0].offset].noCull;\n\n    Vertex  vertex1 = vertices[index1];\n    Vertex  vertex2 = vertices[index2];\n    Vertex  vertex3 = vertices[index3];\n    Vertex  vertex4 = vertices[index4];\n\n    mat4    matrix  = projectMatrix * viewMatrix;\n    vec4    pos1    = matrix        * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0);\n    vec4    pos2    = matrix        * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0);\n    vec4    pos3    = matrix        * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0);\n    vec4    pos4    = matrix        * vec4(vertex4.x, vertex4.y, vertex4.z, 1.0);\n\n    float   det1    = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw));\n    float   det2    = determinant(mat3(pos3.xyw, pos4.xyw, pos1.xyw));\n\n    if (noCull > 0u || det1 > 0.0 || det2 > 0.0) {\n        uint indexOut                       = atomicCounterAdd(indexCounter, 6u) / 3u;\n\n        polygonsOut[indexOut + 0].vertex1   = index1;\n        polygonsOut[indexOut + 0].vertex2   = index2;\n        polygonsOut[indexOut + 0].vertex3   = index3;\n\n        polygonsOut[indexOut + 1].vertex1   = index3;\n        polygonsOut[indexOut + 1].vertex2   = index4;\n        polygonsOut[indexOut + 1].vertex3   = index1;\n    }\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/compat/culling/iris_entity_triangle_culling_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    int     uv1;\n    int     uv2;\n    uint    normal;\n    uint    iris_data_0;\n    uint    iris_data_1;\n    uint    iris_data_2;\n    uint    iris_data_3;\n    uint    iris_data_4;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct Polygon {\n    uint    vertex1;\n    uint    vertex2;\n    uint    vertex3;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict readonly buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4, std430) restrict readonly buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=6, std430) restrict writeonly buffer PolygonsOut {\n    Polygon polygonsOut[];\n};\n\nlayout(binding=0, offset=0) uniform atomic_uint indexCounter;\n\nlayout(location=0) uniform mat4 viewMatrix;\nlayout(location=1) uniform mat4 projectMatrix;\nlayout(location=2) uniform uint polygonCount;\nlayout(location=3) uniform uint vertexOffset;\nlayout(location=4) uniform uint varyingOffset;\n\nvoid main() {\n    uint    index   = gl_GlobalInvocationID.x;\n    uint    base    = index * 3u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint    index0  = varyingOffset + base + 0u;\n    uint    index1  = vertexOffset  + base + 0u;\n    uint    index2  = vertexOffset  + base + 1u;\n    uint    index3  = vertexOffset  + base + 2u;\n    uint    noCull  = varyings[index0 - varyings[index0].offset].noCull;\n\n    Vertex  vertex1 = vertices[index1];\n    Vertex  vertex2 = vertices[index2];\n    Vertex  vertex3 = vertices[index3];\n\n    mat4    matrix  = projectMatrix * viewMatrix;\n    vec4    pos1    = matrix        * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0);\n    vec4    pos2    = matrix        * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0);\n    vec4    pos3    = matrix        * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0);\n\n    float   det     = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw));\n\n    if (noCull > 0u || det > 0.0) {\n        uint indexOut                       = atomicCounterAdd(indexCounter, 3u) / 3u;\n\n        polygonsOut[indexOut + 0].vertex1   = index1;\n        polygonsOut[indexOut + 0].vertex2   = index2;\n        polygonsOut[indexOut + 0].vertex3   = index3;\n    }\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/compat/processing/iris_block_quad_processing_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    int     uv2;\n    uint    normal;\n    uint    iris_entity;\n    float   iris_midcoord_u;\n    float   iris_midcoord_v;\n    uint    iris_at_tangent;\n    uint    iris_mid_block;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(location=0) uniform uint polygonCount;\nlayout(location=1) uniform uint vertexOffset;\n\nvoid main() {\n    uint    index           = gl_GlobalInvocationID.x;\n    uint    base            = index * 4u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint    index1          = vertexOffset + base + 0u;\n    uint    index2          = vertexOffset + base + 1u;\n    uint    index3          = vertexOffset + base + 2u;\n    uint    index4          = vertexOffset + base + 3u;\n\n    Vertex  vertex1         = vertices[index1];\n    Vertex  vertex2         = vertices[index2];\n    Vertex  vertex3         = vertices[index3];\n    Vertex  vertex4         = vertices[index4];\n\n    vec3    pos1            = vec3(vertex1.x, vertex1.y, vertex1.z);\n    vec3    pos2            = vec3(vertex2.x, vertex2.y, vertex2.z);\n    vec3    pos3            = vec3(vertex3.x, vertex3.y, vertex3.z);\n    vec3    pos4            = vec3(vertex4.x, vertex4.y, vertex4.z);\n\n    vec3    midBlock1       = (vec3(0.5) - pos1) * 64.0;\n    vec3    midBlock2       = (vec3(0.5) - pos2) * 64.0;\n    vec3    midBlock3       = (vec3(0.5) - pos3) * 64.0;\n    vec3    midBlock4       = (vec3(0.5) - pos4) * 64.0;\n\n    vec2    uv1             = vec2(vertex1.u0, vertex1.v0);\n    vec2    uv2             = vec2(vertex2.u0, vertex2.v0);\n    vec2    uv3             = vec2(vertex3.u0, vertex3.v0);\n    vec2    uv4             = vec2(vertex4.u0, vertex4.v0);\n\n    vec2    midUV           = (uv1 + uv2 + uv3 + uv4) / 4;\n    vec3    normal          = unpackSnorm4x8(vertex1.normal).xyz;\n\n    vec3    edge1           = pos2 - pos1;\n    vec3    edge2           = pos3 - pos1;\n\n    vec2    dUV1            = uv2 - uv1;\n    vec2    dUV2            = uv3 - uv1;\n\n    float   fdenom          = dUV1.x * dUV2.y - dUV2.x * dUV1.y;\n    float   f               = fdenom == 0.0 ? 1.0 : 1.0 / fdenom;\n\n    vec3    tangent         = normalize(f * (dUV2.y * edge1 - dUV1.y * edge2));\n    vec3    aBitangent      = normalize(f * (-dUV2.x * edge1 + dUV1.x * edge2));\n    vec3    pBitangent      = cross(tangent, normal);\n    vec4    tangent4        = vec4(tangent, dot(aBitangent, pBitangent) < 0.0 ? -1.0 : 1.0);\n    uint    packedTangent   = packSnorm4x8(tangent4);\n\n    vertices[index1].iris_mid_block     = packSnorm4x8(vec4(midBlock1, -1.0));\n    vertices[index2].iris_mid_block     = packSnorm4x8(vec4(midBlock2, -1.0));\n    vertices[index3].iris_mid_block     = packSnorm4x8(vec4(midBlock3, -1.0));\n    vertices[index4].iris_mid_block     = packSnorm4x8(vec4(midBlock4, -1.0));\n\n    vertices[index1].iris_at_tangent    = packedTangent;\n    vertices[index2].iris_at_tangent    = packedTangent;\n    vertices[index3].iris_at_tangent    = packedTangent;\n    vertices[index4].iris_at_tangent    = packedTangent;\n\n    vertices[index1].iris_midcoord_u    = midUV.x;\n    vertices[index2].iris_midcoord_u    = midUV.x;\n    vertices[index3].iris_midcoord_u    = midUV.x;\n    vertices[index4].iris_midcoord_u    = midUV.x;\n\n    vertices[index1].iris_midcoord_v    = midUV.y;\n    vertices[index2].iris_midcoord_v    = midUV.y;\n    vertices[index3].iris_midcoord_v    = midUV.y;\n    vertices[index4].iris_midcoord_v    = midUV.y;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/compat/processing/iris_block_triangle_processing_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    int     uv2;\n    uint    normal;\n    uint    iris_entity;\n    float   iris_midcoord_u;\n    float   iris_midcoord_v;\n    uint    iris_at_tangent;\n    uint    iris_mid_block;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(location=0) uniform uint polygonCount;\nlayout(location=1) uniform uint vertexOffset;\n\nuint computeTangentSmooth(vec3 pos1, vec3 pos2, vec3 pos3, vec2 uv1, vec2 uv2, vec2 uv3, vec3 normal);\n\nvoid main() {\n    uint    index       = gl_GlobalInvocationID.x;\n    uint    base        = index * 3u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint    index1      = vertexOffset + base + 0u;\n    uint    index2      = vertexOffset + base + 1u;\n    uint    index3      = vertexOffset + base + 2u;\n\n    Vertex  vertex1     = vertices[index1];\n    Vertex  vertex2     = vertices[index2];\n    Vertex  vertex3     = vertices[index3];\n\n    vec3    pos1        = vec3(vertex1.x, vertex1.y, vertex1.z);\n    vec3    pos2        = vec3(vertex2.x, vertex2.y, vertex2.z);\n    vec3    pos3        = vec3(vertex3.x, vertex3.y, vertex3.z);\n\n    vec3    midBlock1   = (vec3(0.5) - pos1) * 64.0;\n    vec3    midBlock2   = (vec3(0.5) - pos2) * 64.0;\n    vec3    midBlock3   = (vec3(0.5) - pos3) * 64.0;\n\n    vec2    uv1         = vec2(vertex1.u0, vertex1.v0);\n    vec2    uv2         = vec2(vertex2.u0, vertex2.v0);\n    vec2    uv3         = vec2(vertex3.u0, vertex3.v0);\n    vec2    midUV       = (uv1 + uv2 + uv3) / 3;\n\n    vec3    normal1     = unpackSnorm4x8(vertex1.normal).xyz;\n    vec3    normal2     = unpackSnorm4x8(vertex2.normal).xyz;\n    vec3    normal3     = unpackSnorm4x8(vertex3.normal).xyz;\n\n    vertices[index1].iris_mid_block = packSnorm4x8          (vec4(midBlock1, -1.0));\n    vertices[index2].iris_mid_block = packSnorm4x8          (vec4(midBlock2, -1.0));\n    vertices[index3].iris_mid_block = packSnorm4x8          (vec4(midBlock3, -1.0));\n\n    vertices[index1].iris_at_tangent = computeTangentSmooth (pos1, pos2, pos3, uv1, uv2, uv3, normal1);\n    vertices[index2].iris_at_tangent = computeTangentSmooth (pos1, pos2, pos3, uv1, uv2, uv3, normal2);\n    vertices[index3].iris_at_tangent = computeTangentSmooth (pos1, pos2, pos3, uv1, uv2, uv3, normal3);\n\n    vertices[index1].iris_midcoord_u = midUV.x;\n    vertices[index2].iris_midcoord_u = midUV.x;\n    vertices[index3].iris_midcoord_u = midUV.x;\n\n    vertices[index1].iris_midcoord_v = midUV.y;\n    vertices[index2].iris_midcoord_v = midUV.y;\n    vertices[index3].iris_midcoord_v = midUV.y;\n}\n\nuint computeTangentSmooth(vec3 pos1, vec3 pos2, vec3 pos3, vec2 uv1, vec2 uv2, vec2 uv3, vec3 normal) {\n    float dot1          =   dot(pos1, normal);\n    float dot2          =   dot(pos2, normal);\n    float dot3          =   dot(pos3, normal);\n\n    pos1                -=  dot1 * normal;\n    pos2                -=  dot2 * normal;\n    pos3                -=  dot3 * normal;\n\n    vec3 edge1          =   pos2 - pos1;\n    vec3 edge2          =   pos3 - pos1;\n\n    vec2 dUV1           =   uv2 - uv1;\n    vec2 dUV2           =   uv3 - uv1;\n\n    float fdenom        =   dUV1.x * dUV2.y - dUV2.x * dUV1.y;\n    float f             =   fdenom == 0.0 ? 1.0 : 1.0 / fdenom;\n\n    vec3 tangent        =   normalize   (f * (dUV2.y * edge1 - dUV1.y * edge2));\n    vec3 aBitangent     =   normalize   (f * (-dUV2.x * edge1 + dUV1.x * edge2));\n    vec3 pBitangent     =   cross       (tangent, normal);\n    vec4 tangent4       =   vec4        (tangent, dot(aBitangent, pBitangent) < 0.0 ? -1.0 : 1.0);\n\n    return packSnorm4x8(tangent4);\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/compat/processing/iris_entity_quad_processing_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    int     uv1;\n    int     uv2;\n    uint    normal;\n    uint    iris_entity_0;\n    uint    iris_entity_1;\n    float   iris_midcoord_u;\n    float   iris_midcoord_v;\n    uint    iris_at_tangent;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(location=0) uniform uint polygonCount;\nlayout(location=1) uniform uint vertexOffset;\n\nvoid main() {\n    uint    index           = gl_GlobalInvocationID.x;\n    uint    base            = index * 4u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint    index1          = vertexOffset + base + 0u;\n    uint    index2          = vertexOffset + base + 1u;\n    uint    index3          = vertexOffset + base + 2u;\n    uint    index4          = vertexOffset + base + 3u;\n\n    Vertex  vertex1         = vertices[index1];\n    Vertex  vertex2         = vertices[index2];\n    Vertex  vertex3         = vertices[index3];\n    Vertex  vertex4         = vertices[index4];\n\n    vec3    pos1            = vec3(vertex1.x, vertex1.y, vertex1.z);\n    vec3    pos2            = vec3(vertex2.x, vertex2.y, vertex2.z);\n    vec3    pos3            = vec3(vertex3.x, vertex3.y, vertex3.z);\n    vec3    pos4            = vec3(vertex4.x, vertex4.y, vertex4.z);\n\n    vec2    uv1             = vec2(vertex1.u0, vertex1.v0);\n    vec2    uv2             = vec2(vertex2.u0, vertex2.v0);\n    vec2    uv3             = vec2(vertex3.u0, vertex3.v0);\n    vec2    uv4             = vec2(vertex4.u0, vertex4.v0);\n\n    vec2    midUV           = (uv1 + uv2 + uv3 + uv4) / 4;\n    vec3    normal          = unpackSnorm4x8(vertex1.normal).xyz;\n\n    vec3    edge1           = pos2 - pos1;\n    vec3    edge2           = pos3 - pos1;\n\n    vec2    dUV1            = uv2 - uv1;\n    vec2    dUV2            = uv3 - uv1;\n\n    float   fdenom          = dUV1.x * dUV2.y - dUV2.x * dUV1.y;\n    float   f               = fdenom == 0.0 ? 1.0 : 1.0 / fdenom;\n\n    vec3    tangent         = normalize(f * (dUV2.y * edge1 - dUV1.y * edge2));\n    vec3    aBitangent      = normalize(f * (-dUV2.x * edge1 + dUV1.x * edge2));\n    vec3    pBitangent      = cross(tangent, normal);\n    vec4    tangent4        = vec4(tangent, dot(aBitangent, pBitangent) < 0.0 ? -1.0 : 1.0);\n    uint    packedTangent   = packSnorm4x8(tangent4);\n\n    vertices[index1].iris_at_tangent    = packedTangent;\n    vertices[index2].iris_at_tangent    = packedTangent;\n    vertices[index3].iris_at_tangent    = packedTangent;\n    vertices[index4].iris_at_tangent    = packedTangent;\n\n    vertices[index1].iris_midcoord_u    = midUV.x;\n    vertices[index2].iris_midcoord_u    = midUV.x;\n    vertices[index3].iris_midcoord_u    = midUV.x;\n    vertices[index4].iris_midcoord_u    = midUV.x;\n\n    vertices[index1].iris_midcoord_v    = midUV.y;\n    vertices[index2].iris_midcoord_v    = midUV.y;\n    vertices[index3].iris_midcoord_v    = midUV.y;\n    vertices[index4].iris_midcoord_v    = midUV.y;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/compat/processing/iris_entity_triangle_processing_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    int     uv1;\n    int     uv2;\n    uint    normal;\n    uint    iris_entity_0;\n    uint    iris_entity_1;\n    float   iris_midcoord_u;\n    float   iris_midcoord_v;\n    uint    iris_at_tangent;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(location=0) uniform uint polygonCount;\nlayout(location=1) uniform uint vertexOffset;\n\nuint computeTangentSmooth(vec3 pos1, vec3 pos2, vec3 pos3, vec2 uv1, vec2 uv2, vec2 uv3, vec3 normal);\n\nvoid main() {\n    uint    index       = gl_GlobalInvocationID.x;\n    uint    base        = index * 3u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint    index1      = vertexOffset + base + 0u;\n    uint    index2      = vertexOffset + base + 1u;\n    uint    index3      = vertexOffset + base + 2u;\n\n    Vertex  vertex1     = vertices[index1];\n    Vertex  vertex2     = vertices[index2];\n    Vertex  vertex3     = vertices[index3];\n\n    vec3    pos1        = vec3(vertex1.x, vertex1.y, vertex1.z);\n    vec3    pos2        = vec3(vertex2.x, vertex2.y, vertex2.z);\n    vec3    pos3        = vec3(vertex3.x, vertex3.y, vertex3.z);\n\n    vec2    uv1         = vec2(vertex1.u0, vertex1.v0);\n    vec2    uv2         = vec2(vertex2.u0, vertex2.v0);\n    vec2    uv3         = vec2(vertex3.u0, vertex3.v0);\n    vec2    midUV       = (uv1 + uv2 + uv3) / 3;\n\n    vec3    normal1     = unpackSnorm4x8(vertex1.normal).xyz;\n    vec3    normal2     = unpackSnorm4x8(vertex2.normal).xyz;\n    vec3    normal3     = unpackSnorm4x8(vertex3.normal).xyz;\n\n    vertices[index1].iris_at_tangent = computeTangentSmooth(pos1, pos2, pos3, uv1, uv2, uv3, normal1);\n    vertices[index2].iris_at_tangent = computeTangentSmooth(pos1, pos2, pos3, uv1, uv2, uv3, normal2);\n    vertices[index3].iris_at_tangent = computeTangentSmooth(pos1, pos2, pos3, uv1, uv2, uv3, normal3);\n\n    vertices[index1].iris_midcoord_u = midUV.x;\n    vertices[index2].iris_midcoord_u = midUV.x;\n    vertices[index3].iris_midcoord_u = midUV.x;\n\n    vertices[index1].iris_midcoord_v = midUV.y;\n    vertices[index2].iris_midcoord_v = midUV.y;\n    vertices[index3].iris_midcoord_v = midUV.y;\n}\n\nuint computeTangentSmooth(vec3 pos1, vec3 pos2, vec3 pos3, vec2 uv1, vec2 uv2, vec2 uv3, vec3 normal) {\n    float dot1          =   dot(pos1, normal);\n    float dot2          =   dot(pos2, normal);\n    float dot3          =   dot(pos3, normal);\n\n    pos1                -=  dot1 * normal;\n    pos2                -=  dot2 * normal;\n    pos3                -=  dot3 * normal;\n\n    vec3 edge1          =   pos2 - pos1;\n    vec3 edge2          =   pos3 - pos1;\n\n    vec2 dUV1           =   uv2 - uv1;\n    vec2 dUV2           =   uv3 - uv1;\n\n    float fdenom        =   dUV1.x * dUV2.y - dUV2.x * dUV1.y;\n    float f             =   fdenom == 0.0 ? 1.0 : 1.0 / fdenom;\n\n    vec3 tangent        =   normalize   (f * (dUV2.y * edge1 - dUV1.y * edge2));\n    vec3 aBitangent     =   normalize   (f * (-dUV2.x * edge1 + dUV1.x * edge2));\n    vec3 pBitangent     =   cross       (tangent, normal);\n    vec4 tangent4       =   vec4        (tangent, dot(aBitangent, pBitangent) < 0.0 ? -1.0 : 1.0);\n\n    return packSnorm4x8(tangent4);\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/compat/processing/iris_glyph_quad_processing_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    int     uv2;\n    uint    normal;\n    uint    iris_entity_0;\n    uint    iris_entity_1;\n    float   iris_midcoord_u;\n    float   iris_midcoord_v;\n    uint    iris_at_tangent;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(location=0) uniform uint polygonCount;\nlayout(location=1) uniform uint vertexOffset;\n\nvoid main() {\n    uint    index           = gl_GlobalInvocationID.x;\n    uint    base            = index * 4u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint    index1          = vertexOffset + base + 0u;\n    uint    index2          = vertexOffset + base + 1u;\n    uint    index3          = vertexOffset + base + 2u;\n    uint    index4          = vertexOffset + base + 3u;\n\n    Vertex  vertex1         = vertices[index1];\n    Vertex  vertex2         = vertices[index2];\n    Vertex  vertex3         = vertices[index3];\n    Vertex  vertex4         = vertices[index4];\n\n    vec3    pos1            = vec3(vertex1.x, vertex1.y, vertex1.z);\n    vec3    pos2            = vec3(vertex2.x, vertex2.y, vertex2.z);\n    vec3    pos3            = vec3(vertex3.x, vertex3.y, vertex3.z);\n\n    vec2    uv1             = vec2(vertex1.u0, vertex1.v0);\n    vec2    uv2             = vec2(vertex2.u0, vertex2.v0);\n    vec2    uv3             = vec2(vertex3.u0, vertex3.v0);\n    vec2    uv4             = vec2(vertex4.u0, vertex4.v0);\n    vec2    midUV           = (uv1 + uv2 + uv3 + uv4) / 4;\n\n    vec3    normal          = normalize(cross(pos2 - pos1, pos3 - pos1));\n    uint    packedNormal    = packSnorm4x8(vec4(normal, 0.0));\n\n    vec3    edge1           = pos2 - pos1;\n    vec3    edge2           = pos3 - pos1;\n\n    vec2    dUV1            = uv2 - uv1;\n    vec2    dUV2            = uv3 - uv1;\n\n    float   fdenom          = dUV1.x * dUV2.y - dUV2.x * dUV1.y;\n    float   f               = fdenom == 0.0 ? 1.0 : 1.0 / fdenom;\n\n    vec3    tangent         = normalize(f * (dUV2.y * edge1 - dUV1.y * edge2));\n    vec3    aBitangent      = normalize(f * (-dUV2.x * edge1 + dUV1.x * edge2));\n    vec3    pBitangent      = cross(tangent, normal);\n    vec4    tangent4        = vec4(tangent, dot(aBitangent, pBitangent) < 0.0 ? -1.0 : 1.0);\n    uint    packedTangent   = packSnorm4x8(tangent4);\n\n    vertices[index1].normal             = packedNormal;\n    vertices[index2].normal             = packedNormal;\n    vertices[index3].normal             = packedNormal;\n    vertices[index4].normal             = packedNormal;\n\n    vertices[index1].iris_at_tangent    = packedTangent;\n    vertices[index2].iris_at_tangent    = packedTangent;\n    vertices[index3].iris_at_tangent    = packedTangent;\n    vertices[index4].iris_at_tangent    = packedTangent;\n\n    vertices[index1].iris_midcoord_u    = midUV.x;\n    vertices[index2].iris_midcoord_u    = midUV.x;\n    vertices[index3].iris_midcoord_u    = midUV.x;\n    vertices[index4].iris_midcoord_u    = midUV.x;\n\n    vertices[index1].iris_midcoord_v    = midUV.y;\n    vertices[index2].iris_midcoord_v    = midUV.y;\n    vertices[index3].iris_midcoord_v    = midUV.y;\n    vertices[index4].iris_midcoord_v    = midUV.y;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/compat/processing/iris_glyph_triangle_processing_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    int     uv2;\n    uint    normal;\n    uint    iris_entity_0;\n    uint    iris_entity_1;\n    float   iris_midcoord_u;\n    float   iris_midcoord_v;\n    uint    iris_at_tangent;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(location=0) uniform uint polygonCount;\nlayout(location=1) uniform uint vertexOffset;\n\nuint computeTangentSmooth(vec3 pos1, vec3 pos2, vec3 pos3, vec2 uv1, vec2 uv2, vec2 uv3, vec3 normal);\n\nvoid main() {\n    uint    index       = gl_GlobalInvocationID.x;\n    uint    base        = index * 3u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint    index1          = vertexOffset + base + 0u;\n    uint    index2          = vertexOffset + base + 1u;\n    uint    index3          = vertexOffset + base + 2u;\n\n    Vertex  vertex1         = vertices[index1];\n    Vertex  vertex2         = vertices[index2];\n    Vertex  vertex3         = vertices[index3];\n\n    vec3    pos1            = vec3(vertex1.x, vertex1.y, vertex1.z);\n    vec3    pos2            = vec3(vertex2.x, vertex2.y, vertex2.z);\n    vec3    pos3            = vec3(vertex3.x, vertex3.y, vertex3.z);\n\n    vec2    uv1             = vec2(vertex1.u0, vertex1.v0);\n    vec2    uv2             = vec2(vertex2.u0, vertex2.v0);\n    vec2    uv3             = vec2(vertex3.u0, vertex3.v0);\n    vec2    midUV           = (uv1 + uv2 + uv3) / 3;\n\n    vec3    normal          = normalize(cross(pos2 - pos1, pos3 - pos1));\n    uint    packedNormal    = packSnorm4x8(vec4(normal, 0.0));\n\n    vertices[index1].normal         = packedNormal;\n    vertices[index2].normal         = packedNormal;\n    vertices[index3].normal         = packedNormal;\n\n    vertices[index1].iris_at_tangent = computeTangentSmooth(pos1, pos2, pos3, uv1, uv2, uv3, normal);\n    vertices[index2].iris_at_tangent = computeTangentSmooth(pos1, pos2, pos3, uv1, uv2, uv3, normal);\n    vertices[index3].iris_at_tangent = computeTangentSmooth(pos1, pos2, pos3, uv1, uv2, uv3, normal);\n\n    vertices[index1].iris_midcoord_u = midUV.x;\n    vertices[index2].iris_midcoord_u = midUV.x;\n    vertices[index3].iris_midcoord_u = midUV.x;\n\n    vertices[index1].iris_midcoord_v = midUV.y;\n    vertices[index2].iris_midcoord_v = midUV.y;\n    vertices[index3].iris_midcoord_v = midUV.y;\n}\n\nuint computeTangentSmooth(vec3 pos1, vec3 pos2, vec3 pos3, vec2 uv1, vec2 uv2, vec2 uv3, vec3 normal) {\n    float dot1          =   dot(pos1, normal);\n    float dot2          =   dot(pos2, normal);\n    float dot3          =   dot(pos3, normal);\n\n    pos1                -=  dot1 * normal;\n    pos2                -=  dot2 * normal;\n    pos3                -=  dot3 * normal;\n\n    vec3 edge1          =   pos2 - pos1;\n    vec3 edge2          =   pos3 - pos1;\n\n    vec2 dUV1           =   uv2 - uv1;\n    vec2 dUV2           =   uv3 - uv1;\n\n    float fdenom        =   dUV1.x * dUV2.y - dUV2.x * dUV1.y;\n    float f             =   fdenom == 0.0 ? 1.0 : 1.0 / fdenom;\n\n    vec3 tangent        =   normalize   (f * (dUV2.y * edge1 - dUV1.y * edge2));\n    vec3 aBitangent     =   normalize   (f * (-dUV2.x * edge1 + dUV1.x * edge2));\n    vec3 pBitangent     =   cross       (tangent, normal);\n    vec4 tangent4       =   vec4        (tangent, dot(aBitangent, pBitangent) < 0.0 ? -1.0 : 1.0);\n\n    return packSnorm4x8(tangent4);\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/compat/transform/iris_block_vertex_transform_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    uint    uv2;\n    uint    normal;\n    uint    iris_entity;\n    uint    iris_data_0;\n    uint    iris_data_1;\n    uint    iris_data_2;\n    uint    iris_data_3;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=0, std430) restrict readonly buffer VerticesIn {\n    Vertex verticesIn[];\n};\n\nlayout(binding=1, std430) restrict writeonly buffer VerticesOut {\n    Vertex verticesOut[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=3, std430) restrict readonly buffer VaryingsIn {\n    VaryingData varyingsIn[];\n};\n\nlayout(binding=4, std430) restrict writeonly buffer VaryingsOut {\n    VaryingData varyingsOut[];\n};\n\nlayout(binding=5, std430) restrict readonly buffer Meshes {\n    Vertex meshVertices[];\n};\n\nlayout(location=0) uniform uint vertexCount;\nlayout(location=1) uniform uint vertexOffset;\nlayout(location=2) uniform uint varyingOffset;\n\nvoid main() {\n    uint    indexIn     = gl_GlobalInvocationID.x;\n    uint    vertexOut   = indexIn + vertexOffset;\n    uint    varyingOut  = indexIn + varyingOffset;\n\n    if (indexIn >= vertexCount) {\n        return;\n    }\n\n    int     offset      = varyingsIn[indexIn]   .offset;\n    uint    reference   = indexIn - offset;\n    int     sharing     = varyingsIn[reference] .sharing;\n    int     mesh        = varyingsIn[reference] .mesh;\n\n    mat4    transformMatrix;\n    mat3    normalMatrix;\n\n    if (sharing != -1) {\n        transformMatrix = sharings[sharing].transform;\n        normalMatrix    = sharings[sharing].normal;\n    } else {\n        transformMatrix = mat4(1.0);\n        normalMatrix    = mat3(1.0);\n    }\n\n    Vertex  vertexIn;\n    vec4    colorMesh;\n    uvec2   uv2Mesh;\n\n    if (mesh != -1) {\n        vertexIn    = meshVertices[mesh + offset];\n        colorMesh   = unpackUnorm4x8    (                   vertexIn.color);\n        uv2Mesh     = floatBitsToUint   (unpackSnorm2x16(   vertexIn.uv2));\n\n    } else {\n        vertexIn    = verticesIn[indexIn];\n        colorMesh   = vec4  (1.0);\n        uv2Mesh     = uvec2 (0u);\n    }\n\n    vec4    colorIn = unpackUnorm4x8    (                   verticesIn[reference].color);\n    uvec2   uv2In   = floatBitsToUint   (unpackSnorm2x16(   verticesIn[reference].uv2));\n\n    vec4    posOut      = transformMatrix   * vec4          (vertexIn.x, vertexIn.y, vertexIn.z, 1.0);\n    vec3    normalOut   = normalMatrix      * unpackSnorm4x8(vertexIn.normal).xyz;\n    vec4    colorOut    = colorMesh         * colorIn;\n    uvec2   uv2Out      = max                               (uv2In, uv2Mesh);\n\n    verticesOut[vertexOut].x            = posOut.x;\n    verticesOut[vertexOut].y            = posOut.y;\n    verticesOut[vertexOut].z            = posOut.z;\n\n    verticesOut[vertexOut].u0           = vertexIn.u0;\n    verticesOut[vertexOut].v0           = vertexIn.v0;\n\n    verticesOut[vertexOut].color        = packUnorm4x8  (colorOut);\n    // verticesOut[vertexOut].uv1          = verticesIn[reference].uv1;\n    verticesOut[vertexOut].uv2          = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    verticesOut[vertexOut].normal       = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n    verticesOut[vertexOut].iris_entity  = -1;\n\n    varyingsOut[varyingOut].offset      = offset;\n    varyingsOut[varyingOut].noCull      = varyingsIn[reference].noCull;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/compat/transform/iris_entity_vertex_transform_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    uint    uv1;\n    uint    uv2;\n    uint    normal;\n    uint    iris_entity_0;\n    uint    iris_entity_1;\n    uint    iris_data_2;\n    uint    iris_data_3;\n    uint    iris_data_4;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=0, std430) restrict readonly buffer VerticesIn {\n    Vertex verticesIn[];\n};\n\nlayout(binding=1, std430) restrict writeonly buffer VerticesOut {\n    Vertex verticesOut[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=3, std430) restrict readonly buffer VaryingsIn {\n    VaryingData varyingsIn[];\n};\n\nlayout(binding=4, std430) restrict writeonly buffer VaryingsOut {\n    VaryingData varyingsOut[];\n};\n\nlayout(binding=5, std430) restrict readonly buffer Meshes {\n    Vertex meshVertices[];\n};\n\nlayout(location=0) uniform uint vertexCount;\nlayout(location=1) uniform uint vertexOffset;\nlayout(location=2) uniform uint varyingOffset;\n\nvoid main() {\n    uint    indexIn     = gl_GlobalInvocationID.x;\n    uint    vertexOut   = indexIn + vertexOffset;\n    uint    varyingOut  = indexIn + varyingOffset;\n\n    if (indexIn >= vertexCount) {\n        return;\n    }\n\n    int     offset      = varyingsIn[indexIn]   .offset;\n    uint    reference   = indexIn - offset;\n    int     sharing     = varyingsIn[reference] .sharing;\n    int     mesh        = varyingsIn[reference] .mesh;\n\n    mat4    transformMatrix;\n    mat3    normalMatrix;\n\n    if (sharing != -1) {\n        transformMatrix = sharings[sharing].transform;\n        normalMatrix    = sharings[sharing].normal;\n    } else {\n        transformMatrix = mat4(1.0);\n        normalMatrix    = mat3(1.0);\n    }\n\n    Vertex  vertexIn;\n    vec4    colorMesh;\n    uvec2   uv2Mesh;\n\n    if (mesh != -1) {\n        vertexIn    = meshVertices[mesh + offset];\n        colorMesh   = unpackUnorm4x8    (                   vertexIn.color);\n        uv2Mesh     = floatBitsToUint   (unpackSnorm2x16(   vertexIn.uv2));\n\n    } else {\n        vertexIn    = verticesIn[indexIn];\n        colorMesh   = vec4  (1.0);\n        uv2Mesh     = uvec2 (0u);\n    }\n\n    vec4    colorIn = unpackUnorm4x8    (                   verticesIn[reference].color);\n    uvec2   uv2In   = floatBitsToUint   (unpackSnorm2x16(   verticesIn[reference].uv2));\n\n    vec4    posOut      = transformMatrix   * vec4          (vertexIn.x, vertexIn.y, vertexIn.z, 1.0);\n    vec3    normalOut   = normalMatrix      * unpackSnorm4x8(vertexIn.normal).xyz;\n    vec4    colorOut    = colorMesh         * colorIn;\n    uvec2   uv2Out      = max                               (uv2In, uv2Mesh);\n\n    verticesOut[vertexOut].x                = posOut.x;\n    verticesOut[vertexOut].y                = posOut.y;\n    verticesOut[vertexOut].z                = posOut.z;\n\n    verticesOut[vertexOut].u0               = vertexIn.u0;\n    verticesOut[vertexOut].v0               = vertexIn.v0;\n\n    verticesOut[vertexOut].color            = packUnorm4x8  (colorOut);\n    verticesOut[vertexOut].uv1              = verticesIn[reference].uv1;\n    verticesOut[vertexOut].uv2              = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    verticesOut[vertexOut].normal           = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n    verticesOut[vertexOut].iris_entity_0    = verticesIn[reference].iris_entity_0;\n    verticesOut[vertexOut].iris_entity_1    = verticesIn[reference].iris_entity_1;\n\n    varyingsOut[varyingOut].offset          = offset;\n    varyingsOut[varyingOut].noCull          = varyingsIn[reference].noCull;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/compat/transform/iris_glyph_vertex_transform_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    uint    uv2;\n    uint    normal;\n    uint    iris_entity_0;\n    uint    iris_entity_1;\n    uint    iris_data_2;\n    uint    iris_data_3;\n    uint    iris_data_4;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=0, std430) restrict readonly buffer VerticesIn {\n    Vertex verticesIn[];\n};\n\nlayout(binding=1, std430) restrict writeonly buffer VerticesOut {\n    Vertex verticesOut[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=3, std430) restrict readonly buffer VaryingsIn {\n    VaryingData varyingsIn[];\n};\n\nlayout(binding=4, std430) restrict writeonly buffer VaryingsOut {\n    VaryingData varyingsOut[];\n};\n\nlayout(binding=5, std430) restrict readonly buffer Meshes {\n    Vertex meshVertices[];\n};\n\nlayout(location=0) uniform uint vertexCount;\nlayout(location=1) uniform uint vertexOffset;\nlayout(location=2) uniform uint varyingOffset;\n\nvoid main() {\n    uint    indexIn     = gl_GlobalInvocationID.x;\n    uint    vertexOut   = indexIn + vertexOffset;\n    uint    varyingOut  = indexIn + varyingOffset;\n\n    if (indexIn >= vertexCount) {\n        return;\n    }\n\n    int     offset      = varyingsIn[indexIn]   .offset;\n    uint    reference   = indexIn - offset;\n    int     sharing     = varyingsIn[reference] .sharing;\n    int     mesh        = varyingsIn[reference] .mesh;\n\n    mat4    transformMatrix;\n    // mat3    normalMatrix;\n\n    if (sharing != -1) {\n        transformMatrix = sharings[sharing].transform;\n        // normalMatrix    = sharings[sharing].normal;\n    } else {\n        transformMatrix = mat4(1.0);\n        // normalMatrix    = mat3(1.0);\n    }\n\n    Vertex  vertexIn;\n    vec4    colorMesh;\n    uvec2   uv2Mesh;\n\n    if (mesh != -1) {\n        vertexIn    = meshVertices[mesh + offset];\n        colorMesh   = unpackUnorm4x8    (                   vertexIn.color);\n        uv2Mesh     = floatBitsToUint   (unpackSnorm2x16(   vertexIn.uv2));\n\n    } else {\n        vertexIn    = verticesIn[indexIn];\n        colorMesh   = vec4  (1.0);\n        uv2Mesh     = uvec2 (0u);\n    }\n\n    vec4    colorIn = unpackUnorm4x8    (                   verticesIn[reference].color);\n    uvec2   uv2In   = floatBitsToUint   (unpackSnorm2x16(   verticesIn[reference].uv2));\n\n    vec4    posOut      = transformMatrix   * vec4          (vertexIn.x, vertexIn.y, vertexIn.z, 1.0);\n    // vec3    normalOut   = normalMatrix      * unpackSnorm4x8(vertexIn.normal).xyz;\n    vec4    colorOut    = colorMesh         * colorIn;\n    uvec2   uv2Out      = max                               (uv2In, uv2Mesh);\n\n    verticesOut[vertexOut].x                = posOut.x;\n    verticesOut[vertexOut].y                = posOut.y;\n    verticesOut[vertexOut].z                = posOut.z;\n\n    verticesOut[vertexOut].u0               = vertexIn.u0;\n    verticesOut[vertexOut].v0               = vertexIn.v0;\n\n    verticesOut[vertexOut].color            = packUnorm4x8  (colorOut);\n    // verticesOut[vertexOut].uv1              = verticesIn[reference].uv1;\n    verticesOut[vertexOut].uv2              = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    // verticesOut[vertexOut].normal           = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n    verticesOut[vertexOut].iris_entity_0    = verticesIn[reference].iris_entity_0;\n    verticesOut[vertexOut].iris_entity_1    = verticesIn[reference].iris_entity_1;\n\n    varyingsOut[varyingOut].offset          = offset;\n    varyingsOut[varyingOut].noCull          = varyingsIn[reference].noCull;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/compat/uploading/iris_block_mesh_uploading_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    uint    uv2;\n    uint    normal;\n    uint    iris_entity;\n    uint    iris_data_0;\n    uint    iris_data_1;\n    uint    iris_data_2;\n    uint    iris_data_3;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct MeshInfo {\n    int     sharing;\n    int     noCull;\n    uint    color;\n    uint    uv1;\n    uint    uv2;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1,   std430) writeonly   buffer Vertices {\n    Vertex      vertices[];\n};\n\nlayout(binding=2,   std430) readonly    buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4,   std430) writeonly   buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=7,   std430) readonly    buffer Meshes {\n    Vertex      meshVertices[];\n};\n\nlayout(binding=8,   std430) readonly    buffer MeshInfos {\n    MeshInfo    meshInfos[];\n};\n\nlayout(location=0) uniform uint meshCount;\nlayout(location=1) uniform uint meshSize;\nlayout(location=2) uniform uint vertexOffset;\nlayout(location=3) uniform uint varyingOffset;\nlayout(location=4) uniform uint meshOffset;\n\nvoid main() {\n    uint        indexIn         = gl_GlobalInvocationID.x;\n    uint        meshIndex       = indexIn / meshSize;\n    uint        index           = indexIn % meshSize;\n\n    if (meshIndex >= meshCount) {\n        return;\n    }\n\n    Vertex      vertex          = meshVertices  [meshOffset + index];\n    MeshInfo    meshInfo        = meshInfos     [meshIndex];\n    SharingData sharingData     = sharings      [meshInfo.sharing];\n    uint        vertexIndex     = index + meshIndex * meshSize + vertexOffset;\n    uint        varyingIndex    = index + meshIndex * meshSize + varyingOffset;\n\n    vec4        colorIn         = unpackUnorm4x8    (meshInfo   .color);\n    vec4        colorMesh       = unpackUnorm4x8    (vertex     .color);\n    uvec2       uv2In           = floatBitsToUint   (unpackSnorm2x16(meshInfo   .uv2));\n    uvec2       uv2Mesh         = floatBitsToUint   (unpackSnorm2x16(vertex     .uv2));\n\n    vec4        colorOut        = colorIn * colorMesh;\n    uvec2       uv2Out          = max(uv2In, uv2Mesh);\n\n    vec4        posOut          = sharingData.transform * vec4          (vertex.x, vertex.y, vertex.z, 1.0);\n    vec3        normalOut       = sharingData.normal    * unpackSnorm4x8(vertex.normal).xyz;\n\n    vertices[vertexIndex].x             = posOut.x;\n    vertices[vertexIndex].y             = posOut.y;\n    vertices[vertexIndex].z             = posOut.z;\n\n    vertices[vertexIndex].color         = packUnorm4x8(colorOut);\n\n    vertices[vertexIndex].u0            = vertex.u0;\n    vertices[vertexIndex].v0            = vertex.v0;\n\n    // vertices[vertexIndex].uv1           = meshInfo.uv1;\n    vertices[vertexIndex].uv2           = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    vertices[vertexIndex].normal        = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n\n    // vertices[vertexIndex].iris_entity_0 = vertex.iris_entity_0;\n    // vertices[vertexIndex].iris_entity_1 = vertex.iris_entity_1;\n    vertices[vertexIndex].iris_entity   = -1;\n\n    varyings[varyingIndex].offset       = 0;\n    varyings[varyingIndex].sharing      = meshInfo.sharing;\n    varyings[varyingIndex].noCull       = meshInfo.noCull;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/compat/uploading/iris_entity_mesh_uploading_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    uint    uv1;\n    uint    uv2;\n    uint    normal;\n    uint    iris_entity_0;\n    uint    iris_entity_1;\n    uint    iris_data_2;\n    uint    iris_data_3;\n    uint    iris_data_4;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct MeshInfo {\n    int     sharing;\n    int     noCull;\n    uint    color;\n    uint    uv1;\n    uint    uv2;\n    uint    iris_entity_0;\n    uint    iris_entity_1;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1,   std430) writeonly   buffer Vertices {\n    Vertex      vertices[];\n};\n\nlayout(binding=2,   std430) readonly    buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4,   std430) writeonly   buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=7,   std430) readonly    buffer Meshes {\n    Vertex      meshVertices[];\n};\n\nlayout(binding=8,   std430) readonly    buffer MeshInfos {\n    MeshInfo    meshInfos[];\n};\n\nlayout(location=0) uniform uint meshCount;\nlayout(location=1) uniform uint meshSize;\nlayout(location=2) uniform uint vertexOffset;\nlayout(location=3) uniform uint varyingOffset;\nlayout(location=4) uniform uint meshOffset;\n\nvoid main() {\n    uint        indexIn         = gl_GlobalInvocationID.x;\n    uint        meshIndex       = indexIn / meshSize;\n    uint        index           = indexIn % meshSize;\n\n    if (meshIndex >= meshCount) {\n        return;\n    }\n\n    Vertex      vertex          = meshVertices  [meshOffset + index];\n    MeshInfo    meshInfo        = meshInfos     [meshIndex];\n    SharingData sharingData     = sharings      [meshInfo.sharing];\n    uint        vertexIndex     = index + meshIndex * meshSize + vertexOffset;\n    uint        varyingIndex    = index + meshIndex * meshSize + varyingOffset;\n\n    vec4        colorIn         = unpackUnorm4x8    (meshInfo   .color);\n    vec4        colorMesh       = unpackUnorm4x8    (vertex     .color);\n    uvec2       uv2In           = floatBitsToUint   (unpackSnorm2x16(meshInfo   .uv2));\n    uvec2       uv2Mesh         = floatBitsToUint   (unpackSnorm2x16(vertex     .uv2));\n\n    vec4        colorOut        = colorIn * colorMesh;\n    uvec2       uv2Out          = max(uv2In, uv2Mesh);\n\n    vec4        posOut          = sharingData.transform * vec4          (vertex.x, vertex.y, vertex.z, 1.0);\n    vec3        normalOut       = sharingData.normal    * unpackSnorm4x8(vertex.normal).xyz;\n\n    vertices[vertexIndex].x             = posOut.x;\n    vertices[vertexIndex].y             = posOut.y;\n    vertices[vertexIndex].z             = posOut.z;\n\n    vertices[vertexIndex].color         = packUnorm4x8(colorOut);\n\n    vertices[vertexIndex].u0            = vertex.u0;\n    vertices[vertexIndex].v0            = vertex.v0;\n\n    vertices[vertexIndex].uv1           = meshInfo.uv1;\n    vertices[vertexIndex].uv2           = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    vertices[vertexIndex].normal        = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n\n    vertices[vertexIndex].iris_entity_0 = meshInfo.iris_entity_0;\n    vertices[vertexIndex].iris_entity_1 = meshInfo.iris_entity_1;\n\n    varyings[varyingIndex].offset       = 0;\n    varyings[varyingIndex].sharing      = meshInfo.sharing;\n    varyings[varyingIndex].noCull       = meshInfo.noCull;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/compat/uploading/iris_glyph_mesh_uploading_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    uint    uv2;\n    uint    normal;\n    uint    iris_entity_0;\n    uint    iris_entity_1;\n    uint    iris_data_2;\n    uint    iris_data_3;\n    uint    iris_data_4;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct MeshInfo {\n    int     sharing;\n    int     noCull;\n    uint    color;\n    uint    uv1;\n    uint    uv2;\n    uint    iris_entity_0;\n    uint    iris_entity_1;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1,   std430) writeonly   buffer Vertices {\n    Vertex      vertices[];\n};\n\nlayout(binding=2,   std430) readonly    buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4,   std430) writeonly   buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=7,   std430) readonly    buffer Meshes {\n    Vertex      meshVertices[];\n};\n\nlayout(binding=8,   std430) readonly    buffer MeshInfos {\n    MeshInfo    meshInfos[];\n};\n\nlayout(location=0) uniform uint meshCount;\nlayout(location=1) uniform uint meshSize;\nlayout(location=2) uniform uint vertexOffset;\nlayout(location=3) uniform uint varyingOffset;\nlayout(location=4) uniform uint meshOffset;\n\nvoid main() {\n    uint        indexIn         = gl_GlobalInvocationID.x;\n    uint        meshIndex       = indexIn / meshSize;\n    uint        index           = indexIn % meshSize;\n\n    if (meshIndex >= meshCount) {\n        return;\n    }\n\n    Vertex      vertex          = meshVertices  [meshOffset + index];\n    MeshInfo    meshInfo        = meshInfos     [meshIndex];\n    SharingData sharingData     = sharings      [meshInfo.sharing];\n    uint        vertexIndex     = index + meshIndex * meshSize + vertexOffset;\n    uint        varyingIndex    = index + meshIndex * meshSize + varyingOffset;\n\n    vec4        colorIn         = unpackUnorm4x8    (meshInfo   .color);\n    vec4        colorMesh       = unpackUnorm4x8    (vertex     .color);\n    uvec2       uv2In           = floatBitsToUint   (unpackSnorm2x16(meshInfo   .uv2));\n    uvec2       uv2Mesh         = floatBitsToUint   (unpackSnorm2x16(vertex     .uv2));\n\n    vec4        colorOut        = colorIn * colorMesh;\n    uvec2       uv2Out          = max(uv2In, uv2Mesh);\n\n    vec4        posOut          = sharingData.transform * vec4          (vertex.x, vertex.y, vertex.z, 1.0);\n    // vec3        normalOut       = sharingData.normal    * unpackSnorm4x8(vertex.normal).xyz;\n\n    vertices[vertexIndex].x             = posOut.x;\n    vertices[vertexIndex].y             = posOut.y;\n    vertices[vertexIndex].z             = posOut.z;\n\n    vertices[vertexIndex].color         = packUnorm4x8(colorOut);\n\n    vertices[vertexIndex].u0            = vertex.u0;\n    vertices[vertexIndex].v0            = vertex.v0;\n\n    // vertices[vertexIndex].uv1           = meshInfo.uv1;\n    vertices[vertexIndex].uv2           = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    // vertices[vertexIndex].normal        = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n\n    vertices[vertexIndex].iris_entity_0 = meshInfo.iris_entity_0;\n    vertices[vertexIndex].iris_entity_1 = meshInfo.iris_entity_1;\n\n    varyings[varyingIndex].offset       = 0;\n    varyings[varyingIndex].sharing      = meshInfo.sharing;\n    varyings[varyingIndex].noCull       = meshInfo.noCull;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/culling/block_quad_culling_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    int     uv2;\n    uint    normal;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct Polygon {\n    uint    vertex1;\n    uint    vertex2;\n    uint    vertex3;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict readonly buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4, std430) restrict readonly buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=6, std430) restrict writeonly buffer PolygonsOut {\n    Polygon polygonsOut[];\n};\n\nlayout(binding=0, offset=0) uniform atomic_uint indexCounter;\n\nlayout(location=0) uniform mat4 viewMatrix;\nlayout(location=1) uniform mat4 projectMatrix;\nlayout(location=2) uniform uint polygonCount;\nlayout(location=3) uniform uint vertexOffset;\nlayout(location=4) uniform uint varyingOffset;\n\nvoid main() {\n    uint    index   = gl_GlobalInvocationID.x;\n    uint    base    = index * 4u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint    index0  = varyingOffset + base + 0u;\n    uint    index1  = vertexOffset  + base + 0u;\n    uint    index2  = vertexOffset  + base + 1u;\n    uint    index3  = vertexOffset  + base + 2u;\n    uint    index4  = vertexOffset  + base + 3u;\n    uint    noCull  = varyings[index0 - varyings[index0].offset].noCull;\n\n    Vertex  vertex1 = vertices[index1];\n    Vertex  vertex2 = vertices[index2];\n    Vertex  vertex3 = vertices[index3];\n    Vertex  vertex4 = vertices[index4];\n\n    mat4    matrix  = projectMatrix * viewMatrix;\n    vec4    pos1    = matrix        * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0);\n    vec4    pos2    = matrix        * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0);\n    vec4    pos3    = matrix        * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0);\n    vec4    pos4    = matrix        * vec4(vertex4.x, vertex4.y, vertex4.z, 1.0);\n\n    float   det1    = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw));\n    float   det2    = determinant(mat3(pos3.xyw, pos4.xyw, pos1.xyw));\n\n    if (noCull > 0u || det1 > 0.0 || det2 > 0.0) {\n        uint indexOut                       = atomicCounterAdd(indexCounter, 6u) / 3u;\n\n        polygonsOut[indexOut + 0].vertex1   = index1;\n        polygonsOut[indexOut + 0].vertex2   = index2;\n        polygonsOut[indexOut + 0].vertex3   = index3;\n\n        polygonsOut[indexOut + 1].vertex1   = index3;\n        polygonsOut[indexOut + 1].vertex2   = index4;\n        polygonsOut[indexOut + 1].vertex3   = index1;\n    }\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/culling/block_triangle_culling_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    int     uv2;\n    uint    normal;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct Polygon {\n    uint    vertex1;\n    uint    vertex2;\n    uint    vertex3;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict readonly buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4, std430) restrict readonly buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=6, std430) restrict writeonly buffer PolygonsOut {\n    Polygon polygonsOut[];\n};\n\nlayout(binding=0, offset=0) uniform atomic_uint indexCounter;\n\nlayout(location=0) uniform mat4 viewMatrix;\nlayout(location=1) uniform mat4 projectMatrix;\nlayout(location=2) uniform uint polygonCount;\nlayout(location=3) uniform uint vertexOffset;\nlayout(location=4) uniform uint varyingOffset;\n\nvoid main() {\n    uint    index   = gl_GlobalInvocationID.x;\n    uint    base    = index * 3u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint    index0  = varyingOffset + base + 0u;\n    uint    index1  = vertexOffset  + base + 0u;\n    uint    index2  = vertexOffset  + base + 1u;\n    uint    index3  = vertexOffset  + base + 2u;\n    uint    noCull  = varyings[index0 - varyings[index0].offset].noCull;\n\n    Vertex  vertex1 = vertices[index1];\n    Vertex  vertex2 = vertices[index2];\n    Vertex  vertex3 = vertices[index3];\n\n    mat4    matrix  = projectMatrix * viewMatrix;\n    vec4    pos1    = matrix        * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0);\n    vec4    pos2    = matrix        * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0);\n    vec4    pos3    = matrix        * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0);\n\n    float   det     = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw));\n\n    if (noCull > 0u || det > 0.0) {\n        uint indexOut                       = atomicCounterAdd(indexCounter, 3u) / 3u;\n\n        polygonsOut[indexOut + 0].vertex1   = index1;\n        polygonsOut[indexOut + 0].vertex2   = index2;\n        polygonsOut[indexOut + 0].vertex3   = index3;\n    }\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/culling/entity_quad_culling_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    int     uv1;\n    int     uv2;\n    uint    normal;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct Polygon {\n    uint    vertex1;\n    uint    vertex2;\n    uint    vertex3;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict readonly buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4, std430) restrict readonly buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=6, std430) restrict writeonly buffer PolygonsOut {\n    Polygon polygonsOut[];\n};\n\nlayout(binding=0, offset=0) uniform atomic_uint indexCounter;\n\nlayout(location=0) uniform mat4 viewMatrix;\nlayout(location=1) uniform mat4 projectMatrix;\nlayout(location=2) uniform uint polygonCount;\nlayout(location=3) uniform uint vertexOffset;\nlayout(location=4) uniform uint varyingOffset;\n\nvoid main() {\n    uint    index   = gl_GlobalInvocationID.x;\n    uint    base    = index * 4u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint    index0  = varyingOffset + base + 0u;\n    uint    index1  = vertexOffset  + base + 0u;\n    uint    index2  = vertexOffset  + base + 1u;\n    uint    index3  = vertexOffset  + base + 2u;\n    uint    index4  = vertexOffset  + base + 3u;\n    uint    noCull  = varyings[index0 - varyings[index0].offset].noCull;\n\n    Vertex  vertex1 = vertices[index1];\n    Vertex  vertex2 = vertices[index2];\n    Vertex  vertex3 = vertices[index3];\n    Vertex  vertex4 = vertices[index4];\n\n    mat4    matrix  = projectMatrix * viewMatrix;\n    vec4    pos1    = matrix        * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0);\n    vec4    pos2    = matrix        * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0);\n    vec4    pos3    = matrix        * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0);\n    vec4    pos4    = matrix        * vec4(vertex4.x, vertex4.y, vertex4.z, 1.0);\n\n    float   det1    = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw));\n    float   det2    = determinant(mat3(pos3.xyw, pos4.xyw, pos1.xyw));\n\n    if (noCull > 0u || det1 > 0.0 || det2 > 0.0) {\n        uint indexOut                       = atomicCounterAdd(indexCounter, 6u) / 3u;\n\n        polygonsOut[indexOut + 0].vertex1   = index1;\n        polygonsOut[indexOut + 0].vertex2   = index2;\n        polygonsOut[indexOut + 0].vertex3   = index3;\n\n        polygonsOut[indexOut + 1].vertex1   = index3;\n        polygonsOut[indexOut + 1].vertex2   = index4;\n        polygonsOut[indexOut + 1].vertex3   = index1;\n    }\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/culling/entity_triangle_culling_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    int     uv1;\n    int     uv2;\n    uint    normal;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct Polygon {\n    uint    vertex1;\n    uint    vertex2;\n    uint    vertex3;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict readonly buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4, std430) restrict readonly buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=6, std430) restrict writeonly buffer PolygonsOut {\n    Polygon polygonsOut[];\n};\n\nlayout(binding=0, offset=0) uniform atomic_uint indexCounter;\n\nlayout(location=0) uniform mat4 viewMatrix;\nlayout(location=1) uniform mat4 projectMatrix;\nlayout(location=2) uniform uint polygonCount;\nlayout(location=3) uniform uint vertexOffset;\nlayout(location=4) uniform uint varyingOffset;\n\nvoid main() {\n    uint    index   = gl_GlobalInvocationID.x;\n    uint    base    = index * 3u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint    index0  = varyingOffset + base + 0u;\n    uint    index1  = vertexOffset  + base + 0u;\n    uint    index2  = vertexOffset  + base + 1u;\n    uint    index3  = vertexOffset  + base + 2u;\n    uint    noCull  = varyings[index0 - varyings[index0].offset].noCull;\n\n    Vertex  vertex1 = vertices[index1];\n    Vertex  vertex2 = vertices[index2];\n    Vertex  vertex3 = vertices[index3];\n\n    mat4    matrix  = projectMatrix * viewMatrix;\n    vec4    pos1    = matrix        * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0);\n    vec4    pos2    = matrix        * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0);\n    vec4    pos3    = matrix        * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0);\n\n    float   det     = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw));\n\n    if (noCull > 0u || det > 0.0) {\n        uint indexOut                       = atomicCounterAdd(indexCounter, 3u) / 3u;\n\n        polygonsOut[indexOut + 0].vertex1   = index1;\n        polygonsOut[indexOut + 0].vertex2   = index2;\n        polygonsOut[indexOut + 0].vertex3   = index3;\n    }\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/culling/pass_through_quad_culling_shader.compute",
    "content": "#version 460 core\n\nstruct Polygon {\n    uint vertex1;\n    uint vertex2;\n    uint vertex3;\n    uint vertex4;\n    uint vertex5;\n    uint vertex6;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=6, std430) restrict writeonly buffer PolygonsOut {\n    Polygon polygonsOut[];\n};\n\nlayout(binding=0, offset=0) uniform atomic_uint indexCounter;\n\nlayout(location=0) uniform uint polygonCount;\nlayout(location=1) uniform uint vertexOffset;\n\nvoid main() {\n    uint index      = gl_GlobalInvocationID.x;\n    uint base       = index * 4u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint index1     = vertexOffset + base + 0u;\n    uint index2     = vertexOffset + base + 1u;\n    uint index3     = vertexOffset + base + 2u;\n    uint index4     = vertexOffset + base + 3u;\n\n    atomicCounterAdd(indexCounter, 6u);\n\n    polygonsOut[index].vertex1 = index1;\n    polygonsOut[index].vertex2 = index2;\n    polygonsOut[index].vertex3 = index3;\n\n    polygonsOut[index].vertex4 = index3;\n    polygonsOut[index].vertex5 = index4;\n    polygonsOut[index].vertex6 = index1;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/culling/pass_through_triangle_culling_shader.compute",
    "content": "#version 460 core\n\nstruct Polygon {\n    uint vertex1;\n    uint vertex2;\n    uint vertex3;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=6, std430) restrict writeonly buffer PolygonsOut {\n    Polygon polygonsOut[];\n};\n\nlayout(binding=0, offset=0) uniform atomic_uint indexCounter;\n\nlayout(location=0) uniform uint polygonCount;\nlayout(location=1) uniform uint vertexOffset;\n\nvoid main() {\n    uint index      = gl_GlobalInvocationID.x;\n    uint base       = index * 3u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint index1     = vertexOffset + base + 0u;\n    uint index2     = vertexOffset + base + 1u;\n    uint index3     = vertexOffset + base + 2u;\n\n    atomicCounterAdd(indexCounter, 3u);\n\n    polygonsOut[index].vertex1 = index1;\n    polygonsOut[index].vertex2 = index2;\n    polygonsOut[index].vertex3 = index3;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/culling/pos_tex_color_quad_culling_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    float   u0;\n    float   v0;\n    uint    color;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct Polygon {\n    uint    vertex1;\n    uint    vertex2;\n    uint    vertex3;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict readonly buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4, std430) restrict readonly buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=6, std430) restrict writeonly buffer PolygonsOut {\n    Polygon polygonsOut[];\n};\n\nlayout(binding=0, offset=0) uniform atomic_uint indexCounter;\n\nlayout(location=0) uniform mat4 viewMatrix;\nlayout(location=1) uniform mat4 projectMatrix;\nlayout(location=2) uniform uint polygonCount;\nlayout(location=3) uniform uint vertexOffset;\nlayout(location=4) uniform uint varyingOffset;\n\nvoid main() {\n    uint    index   = gl_GlobalInvocationID.x;\n    uint    base    = index * 4u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint    index0  = varyingOffset + base + 0u;\n    uint    index1  = vertexOffset  + base + 0u;\n    uint    index2  = vertexOffset  + base + 1u;\n    uint    index3  = vertexOffset  + base + 2u;\n    uint    index4  = vertexOffset  + base + 3u;\n    uint    noCull  = varyings[index0 - varyings[index0].offset].noCull;\n\n    Vertex  vertex1 = vertices[index1];\n    Vertex  vertex2 = vertices[index2];\n    Vertex  vertex3 = vertices[index3];\n    Vertex  vertex4 = vertices[index4];\n\n    mat4    matrix  = projectMatrix * viewMatrix;\n    vec4    pos1    = matrix        * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0);\n    vec4    pos2    = matrix        * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0);\n    vec4    pos3    = matrix        * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0);\n    vec4    pos4    = matrix        * vec4(vertex4.x, vertex4.y, vertex4.z, 1.0);\n\n    float   det1    = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw));\n    float   det2    = determinant(mat3(pos3.xyw, pos4.xyw, pos1.xyw));\n\n    if (noCull > 0u || det1 > 0.0 || det2 > 0.0) {\n        uint indexOut                       = atomicCounterAdd(indexCounter, 6u) / 3u;\n\n        polygonsOut[indexOut + 0].vertex1   = index1;\n        polygonsOut[indexOut + 0].vertex2   = index2;\n        polygonsOut[indexOut + 0].vertex3   = index3;\n\n        polygonsOut[indexOut + 1].vertex1   = index3;\n        polygonsOut[indexOut + 1].vertex2   = index4;\n        polygonsOut[indexOut + 1].vertex3   = index1;\n    }\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/culling/pos_tex_color_triangle_culling_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    float   u0;\n    float   v0;\n    uint    color;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct Polygon {\n    uint    vertex1;\n    uint    vertex2;\n    uint    vertex3;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict readonly buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4, std430) restrict readonly buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=6, std430) restrict writeonly buffer PolygonsOut {\n    Polygon polygonsOut[];\n};\n\nlayout(binding=0, offset=0) uniform atomic_uint indexCounter;\n\nlayout(location=0) uniform mat4 viewMatrix;\nlayout(location=1) uniform mat4 projectMatrix;\nlayout(location=2) uniform uint polygonCount;\nlayout(location=3) uniform uint vertexOffset;\nlayout(location=4) uniform uint varyingOffset;\n\nvoid main() {\n    uint    index   = gl_GlobalInvocationID.x;\n    uint    base    = index * 3u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint    index0  = varyingOffset + base + 0u;\n    uint    index1  = vertexOffset  + base + 0u;\n    uint    index2  = vertexOffset  + base + 1u;\n    uint    index3  = vertexOffset  + base + 2u;\n    uint    noCull  = varyings[index0 - varyings[index0].offset].noCull;\n\n    Vertex  vertex1 = vertices[index1];\n    Vertex  vertex2 = vertices[index2];\n    Vertex  vertex3 = vertices[index3];\n\n    mat4    matrix  = projectMatrix * viewMatrix;\n    vec4    pos1    = matrix        * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0);\n    vec4    pos2    = matrix        * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0);\n    vec4    pos3    = matrix        * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0);\n\n    float   det     = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw));\n\n    if (noCull > 0u || det > 0.0) {\n        uint indexOut                       = atomicCounterAdd(indexCounter, 3u) / 3u;\n\n        polygonsOut[indexOut + 0].vertex1   = index1;\n        polygonsOut[indexOut + 0].vertex2   = index2;\n        polygonsOut[indexOut + 0].vertex3   = index3;\n    }\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/culling/pos_tex_quad_culling_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    float   u0;\n    float   v0;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct Polygon {\n    uint    vertex1;\n    uint    vertex2;\n    uint    vertex3;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict readonly buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4, std430) restrict readonly buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=6, std430) restrict writeonly buffer PolygonsOut {\n    Polygon polygonsOut[];\n};\n\nlayout(binding=0, offset=0) uniform atomic_uint indexCounter;\n\nlayout(location=0) uniform mat4 viewMatrix;\nlayout(location=1) uniform mat4 projectMatrix;\nlayout(location=2) uniform uint polygonCount;\nlayout(location=3) uniform uint vertexOffset;\nlayout(location=4) uniform uint varyingOffset;\n\nvoid main() {\n    uint    index   = gl_GlobalInvocationID.x;\n    uint    base    = index * 4u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint    index0  = varyingOffset + base + 0u;\n    uint    index1  = vertexOffset  + base + 0u;\n    uint    index2  = vertexOffset  + base + 1u;\n    uint    index3  = vertexOffset  + base + 2u;\n    uint    index4  = vertexOffset  + base + 3u;\n    uint    noCull  = varyings[index0 - varyings[index0].offset].noCull;\n\n    Vertex  vertex1 = vertices[index1];\n    Vertex  vertex2 = vertices[index2];\n    Vertex  vertex3 = vertices[index3];\n    Vertex  vertex4 = vertices[index4];\n\n    mat4    matrix  = projectMatrix * viewMatrix;\n    vec4    pos1    = matrix        * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0);\n    vec4    pos2    = matrix        * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0);\n    vec4    pos3    = matrix        * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0);\n    vec4    pos4    = matrix        * vec4(vertex4.x, vertex4.y, vertex4.z, 1.0);\n\n    float   det1    = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw));\n    float   det2    = determinant(mat3(pos3.xyw, pos4.xyw, pos1.xyw));\n\n    if (noCull > 0u || det1 > 0.0 || det2 > 0.0) {\n        uint indexOut                       = atomicCounterAdd(indexCounter, 6u) / 3u;\n\n        polygonsOut[indexOut + 0].vertex1   = index1;\n        polygonsOut[indexOut + 0].vertex2   = index2;\n        polygonsOut[indexOut + 0].vertex3   = index3;\n\n        polygonsOut[indexOut + 1].vertex1   = index3;\n        polygonsOut[indexOut + 1].vertex2   = index4;\n        polygonsOut[indexOut + 1].vertex3   = index1;\n    }\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/culling/pos_tex_triangle_culling_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    float   u0;\n    float   v0;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct Polygon {\n    uint    vertex1;\n    uint    vertex2;\n    uint    vertex3;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict readonly buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4, std430) restrict readonly buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=6, std430) restrict writeonly buffer PolygonsOut {\n    Polygon polygonsOut[];\n};\n\nlayout(binding=0, offset=0) uniform atomic_uint indexCounter;\n\nlayout(location=0) uniform mat4 viewMatrix;\nlayout(location=1) uniform mat4 projectMatrix;\nlayout(location=2) uniform uint polygonCount;\nlayout(location=3) uniform uint vertexOffset;\nlayout(location=4) uniform uint varyingOffset;\n\nvoid main() {\n    uint    index   = gl_GlobalInvocationID.x;\n    uint    base    = index * 3u;\n\n    if (index >= polygonCount) {\n        return;\n    }\n\n    uint    index0  = varyingOffset + base + 0u;\n    uint    index1  = vertexOffset  + base + 0u;\n    uint    index2  = vertexOffset  + base + 1u;\n    uint    index3  = vertexOffset  + base + 2u;\n    uint    noCull  = varyings[index0 - varyings[index0].offset].noCull;\n\n    Vertex  vertex1 = vertices[index1];\n    Vertex  vertex2 = vertices[index2];\n    Vertex  vertex3 = vertices[index3];\n\n    mat4    matrix  = projectMatrix * viewMatrix;\n    vec4    pos1    = matrix        * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0);\n    vec4    pos2    = matrix        * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0);\n    vec4    pos3    = matrix        * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0);\n\n    float   det     = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw));\n\n    if (noCull > 0u || det > 0.0) {\n        uint indexOut                       = atomicCounterAdd(indexCounter, 3u) / 3u;\n\n        polygonsOut[indexOut + 0].vertex1   = index1;\n        polygonsOut[indexOut + 0].vertex2   = index2;\n        polygonsOut[indexOut + 0].vertex3   = index3;\n    }\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/transform/block_vertex_transform_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    uint    uv2;\n    uint    normal;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=0, std430) restrict readonly buffer VerticesIn {\n    Vertex verticesIn[];\n};\n\nlayout(binding=1, std430) restrict writeonly buffer VerticesOut {\n    Vertex verticesOut[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=3, std430) restrict readonly buffer VaryingsIn {\n    VaryingData varyingsIn[];\n};\n\nlayout(binding=4, std430) restrict writeonly buffer VaryingsOut {\n    VaryingData varyingsOut[];\n};\n\nlayout(binding=5, std430) restrict readonly buffer Meshes {\n    Vertex meshVertices[];\n};\n\nlayout(location=0) uniform uint vertexCount;\nlayout(location=1) uniform uint vertexOffset;\nlayout(location=2) uniform uint varyingOffset;\n\nvoid main() {\n    uint    indexIn     = gl_GlobalInvocationID.x;\n    uint    vertexOut   = indexIn + vertexOffset;\n    uint    varyingOut  = indexIn + varyingOffset;\n\n    if (indexIn >= vertexCount) {\n        return;\n    }\n\n    int     offset      = varyingsIn[indexIn]   .offset;\n    uint    reference   = indexIn - offset;\n    int     sharing     = varyingsIn[reference] .sharing;\n    int     mesh        = varyingsIn[reference] .mesh;\n\n    mat4    transformMatrix;\n    mat3    normalMatrix;\n\n    if (sharing != -1) {\n        transformMatrix = sharings[sharing].transform;\n        normalMatrix    = sharings[sharing].normal;\n    } else {\n        transformMatrix = mat4(1.0);\n        normalMatrix    = mat3(1.0);\n    }\n\n    Vertex  vertexIn;\n    vec4    colorMesh;\n    uvec2   uv2Mesh;\n\n    if (mesh != -1) {\n        vertexIn    = meshVertices[mesh + offset];\n        colorMesh   = unpackUnorm4x8    (                   vertexIn.color);\n        uv2Mesh     = floatBitsToUint   (unpackSnorm2x16(   vertexIn.uv2));\n\n    } else {\n        vertexIn    = verticesIn[indexIn];\n        colorMesh   = vec4  (1.0);\n        uv2Mesh     = uvec2 (0u);\n    }\n\n    vec4    colorIn = unpackUnorm4x8    (                   verticesIn[reference].color);\n    uvec2   uv2In   = floatBitsToUint   (unpackSnorm2x16(   verticesIn[reference].uv2));\n\n    vec4    posOut      = transformMatrix   * vec4          (vertexIn.x, vertexIn.y, vertexIn.z, 1.0);\n    vec3    normalOut   = normalMatrix      * unpackSnorm4x8(vertexIn.normal).xyz;\n    vec4    colorOut    = colorMesh         * colorIn;\n    uvec2   uv2Out      = max                               (uv2In, uv2Mesh);\n\n    verticesOut[vertexOut].x        = posOut.x;\n    verticesOut[vertexOut].y        = posOut.y;\n    verticesOut[vertexOut].z        = posOut.z;\n\n    verticesOut[vertexOut].u0       = vertexIn.u0;\n    verticesOut[vertexOut].v0       = vertexIn.v0;\n\n    verticesOut[vertexOut].color    = packUnorm4x8  (colorOut);\n    // verticesOut[vertexOut].uv1      = verticesIn[reference].uv1;\n    verticesOut[vertexOut].uv2      = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    verticesOut[vertexOut].normal   = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n\n    varyingsOut[varyingOut].offset  = offset;\n    varyingsOut[varyingOut].noCull  = varyingsIn[reference].noCull;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/transform/entity_vertex_transform_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    uint    uv1;\n    uint    uv2;\n    uint    normal;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=0, std430) restrict readonly buffer VerticesIn {\n    Vertex verticesIn[];\n};\n\nlayout(binding=1, std430) restrict writeonly buffer VerticesOut {\n    Vertex verticesOut[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=3, std430) restrict readonly buffer VaryingsIn {\n    VaryingData varyingsIn[];\n};\n\nlayout(binding=4, std430) restrict writeonly buffer VaryingsOut {\n    VaryingData varyingsOut[];\n};\n\nlayout(binding=5, std430) restrict readonly buffer Meshes {\n    Vertex meshVertices[];\n};\n\nlayout(location=0) uniform uint vertexCount;\nlayout(location=1) uniform uint vertexOffset;\nlayout(location=2) uniform uint varyingOffset;\n\nvoid main() {\n    uint    indexIn     = gl_GlobalInvocationID.x;\n    uint    vertexOut   = indexIn + vertexOffset;\n    uint    varyingOut  = indexIn + varyingOffset;\n\n    if (indexIn >= vertexCount) {\n        return;\n    }\n\n    int     offset      = varyingsIn[indexIn]   .offset;\n    uint    reference   = indexIn - offset;\n    int     sharing     = varyingsIn[reference] .sharing;\n    int     mesh        = varyingsIn[reference] .mesh;\n\n    mat4    transformMatrix;\n    mat3    normalMatrix;\n\n    if (sharing != -1) {\n        transformMatrix = sharings[sharing].transform;\n        normalMatrix    = sharings[sharing].normal;\n    } else {\n        transformMatrix = mat4(1.0);\n        normalMatrix    = mat3(1.0);\n    }\n\n    Vertex  vertexIn;\n    vec4    colorMesh;\n    uvec2   uv2Mesh;\n\n    if (mesh != -1) {\n        vertexIn    = meshVertices[mesh + offset];\n        colorMesh   = unpackUnorm4x8    (                   vertexIn.color);\n        uv2Mesh     = floatBitsToUint   (unpackSnorm2x16(   vertexIn.uv2));\n\n    } else {\n        vertexIn    = verticesIn[indexIn];\n        colorMesh   = vec4  (1.0);\n        uv2Mesh     = uvec2 (0u);\n    }\n\n    vec4    colorIn = unpackUnorm4x8    (                   verticesIn[reference].color);\n    uvec2   uv2In   = floatBitsToUint   (unpackSnorm2x16(   verticesIn[reference].uv2));\n\n    vec4    posOut      = transformMatrix   * vec4          (vertexIn.x, vertexIn.y, vertexIn.z, 1.0);\n    vec3    normalOut   = normalMatrix      * unpackSnorm4x8(vertexIn.normal).xyz;\n    vec4    colorOut    = colorMesh         * colorIn;\n    uvec2   uv2Out      = max                               (uv2In, uv2Mesh);\n\n    verticesOut[vertexOut].x        = posOut.x;\n    verticesOut[vertexOut].y        = posOut.y;\n    verticesOut[vertexOut].z        = posOut.z;\n\n    verticesOut[vertexOut].u0       = vertexIn.u0;\n    verticesOut[vertexOut].v0       = vertexIn.v0;\n\n    verticesOut[vertexOut].color    = packUnorm4x8  (colorOut);\n    verticesOut[vertexOut].uv1      = verticesIn[reference].uv1;\n    verticesOut[vertexOut].uv2      = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    verticesOut[vertexOut].normal   = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n\n    varyingsOut[varyingOut].offset  = offset;\n    varyingsOut[varyingOut].noCull  = varyingsIn[reference].noCull;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/transform/pos_color_tex_light_vertex_transform_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    uint    uv2;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=0, std430) restrict readonly buffer VerticesIn {\n    Vertex verticesIn[];\n};\n\nlayout(binding=1, std430) restrict writeonly buffer VerticesOut {\n    Vertex verticesOut[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=3, std430) restrict readonly buffer VaryingsIn {\n    VaryingData varyingsIn[];\n};\n\nlayout(binding=4, std430) restrict writeonly buffer VaryingsOut {\n    VaryingData varyingsOut[];\n};\n\nlayout(binding=5, std430) restrict readonly buffer Meshes {\n    Vertex meshVertices[];\n};\n\nlayout(location=0) uniform uint vertexCount;\nlayout(location=1) uniform uint vertexOffset;\nlayout(location=2) uniform uint varyingOffset;\n\nvoid main() {\n    uint    indexIn     = gl_GlobalInvocationID.x;\n    uint    vertexOut   = indexIn + vertexOffset;\n    uint    varyingOut  = indexIn + varyingOffset;\n\n    if (indexIn >= vertexCount) {\n        return;\n    }\n\n    int     offset      = varyingsIn[indexIn]   .offset;\n    uint    reference   = indexIn - offset;\n    int     sharing     = varyingsIn[reference] .sharing;\n    int     mesh        = varyingsIn[reference] .mesh;\n\n    mat4    transformMatrix;\n    // mat3    normalMatrix;\n\n    if (sharing != -1) {\n        transformMatrix = sharings[sharing].transform;\n        // normalMatrix    = sharings[sharing].normal;\n    } else {\n        transformMatrix = mat4(1.0);\n        // normalMatrix    = mat3(1.0);\n    }\n\n    Vertex  vertexIn;\n    vec4    colorMesh;\n    uvec2   uv2Mesh;\n\n    if (mesh != -1) {\n        vertexIn    = meshVertices[mesh + offset];\n        colorMesh   = unpackUnorm4x8    (                   vertexIn.color);\n        uv2Mesh     = floatBitsToUint   (unpackSnorm2x16(   vertexIn.uv2));\n\n    } else {\n        vertexIn    = verticesIn[indexIn];\n        colorMesh   = vec4  (1.0);\n        uv2Mesh     = uvec2 (0u);\n    }\n\n    vec4    colorIn = unpackUnorm4x8    (                   verticesIn[reference].color);\n    uvec2   uv2In   = floatBitsToUint   (unpackSnorm2x16(   verticesIn[reference].uv2));\n\n    vec4    posOut      = transformMatrix   * vec4          (vertexIn.x, vertexIn.y, vertexIn.z, 1.0);\n   //  vec3    normalOut   = normalMatrix      * unpackSnorm4x8(vertexIn.normal).xyz;\n    vec4    colorOut    = colorMesh         * colorIn;\n    uvec2   uv2Out      = max                               (uv2In, uv2Mesh);\n\n    verticesOut[vertexOut].x        = posOut.x;\n    verticesOut[vertexOut].y        = posOut.y;\n    verticesOut[vertexOut].z        = posOut.z;\n\n    verticesOut[vertexOut].u0       = vertexIn.u0;\n    verticesOut[vertexOut].v0       = vertexIn.v0;\n\n    verticesOut[vertexOut].color    = packUnorm4x8  (colorOut);\n    // verticesOut[vertexOut].uv1      = verticesIn[reference].uv1;\n    verticesOut[vertexOut].uv2      = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    // verticesOut[vertexOut].normal   = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n\n    varyingsOut[varyingOut].offset  = offset;\n    varyingsOut[varyingOut].noCull  = varyingsIn[reference].noCull;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/transform/pos_color_vertex_transform_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=0, std430) restrict readonly buffer VerticesIn {\n    Vertex verticesIn[];\n};\n\nlayout(binding=1, std430) restrict writeonly buffer VerticesOut {\n    Vertex verticesOut[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=3, std430) restrict readonly buffer VaryingsIn {\n    VaryingData varyingsIn[];\n};\n\nlayout(binding=4, std430) restrict writeonly buffer VaryingsOut {\n    VaryingData varyingsOut[];\n};\n\nlayout(binding=5, std430) restrict readonly buffer Meshes {\n    Vertex meshVertices[];\n};\n\nlayout(location=0) uniform uint vertexCount;\nlayout(location=1) uniform uint vertexOffset;\nlayout(location=2) uniform uint varyingOffset;\n\nvoid main() {\n    uint    indexIn     = gl_GlobalInvocationID.x;\n    uint    vertexOut   = indexIn + vertexOffset;\n    uint    varyingOut  = indexIn + varyingOffset;\n\n    if (indexIn >= vertexCount) {\n        return;\n    }\n\n    int     offset      = varyingsIn[indexIn]   .offset;\n    uint    reference   = indexIn - offset;\n    int     sharing     = varyingsIn[reference] .sharing;\n    int     mesh        = varyingsIn[reference] .mesh;\n\n    mat4    transformMatrix;\n    // mat3    normalMatrix;\n\n    if (sharing != -1) {\n        transformMatrix = sharings[sharing].transform;\n        // normalMatrix    = sharings[sharing].normal;\n    } else {\n        transformMatrix = mat4(1.0);\n        // normalMatrix    = mat3(1.0);\n    }\n\n    Vertex  vertexIn;\n    vec4    colorMesh;\n    // uvec2   uv2Mesh;\n\n    if (mesh != -1) {\n        vertexIn    = meshVertices[mesh + offset];\n        colorMesh   = unpackUnorm4x8    (                   vertexIn.color);\n        // uv2Mesh     = floatBitsToUint   (unpackSnorm2x16(   vertexIn.uv2));\n\n    } else {\n        vertexIn    = verticesIn[indexIn];\n        colorMesh   = vec4  (1.0);\n        // uv2Mesh     = uvec2 (0u);\n    }\n\n    vec4    colorIn = unpackUnorm4x8    (                   verticesIn[reference].color);\n    // uvec2   uv2In   = floatBitsToUint   (unpackSnorm2x16(   verticesIn[reference].uv2));\n\n    vec4    posOut      = transformMatrix   * vec4          (vertexIn.x, vertexIn.y, vertexIn.z, 1.0);\n   //  vec3    normalOut   = normalMatrix      * unpackSnorm4x8(vertexIn.normal).xyz;\n    vec4    colorOut    = colorMesh         * colorIn;\n    // uvec2   uv2Out      = max                               (uv2In, uv2Mesh);\n\n    verticesOut[vertexOut].x        = posOut.x;\n    verticesOut[vertexOut].y        = posOut.y;\n    verticesOut[vertexOut].z        = posOut.z;\n\n    // verticesOut[vertexOut].u0       = vertexIn.u0;\n    // verticesOut[vertexOut].v0       = vertexIn.v0;\n\n    verticesOut[vertexOut].color    = packUnorm4x8  (colorOut);\n    // verticesOut[vertexOut].uv1      = verticesIn[reference].uv1;\n    // verticesOut[vertexOut].uv2      = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    // verticesOut[vertexOut].normal   = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n\n    varyingsOut[varyingOut].offset  = offset;\n    varyingsOut[varyingOut].noCull  = varyingsIn[reference].noCull;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/transform/pos_tex_color_vertex_transform_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    float   u0;\n    float   v0;\n    uint    color;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=0, std430) restrict readonly buffer VerticesIn {\n    Vertex verticesIn[];\n};\n\nlayout(binding=1, std430) restrict writeonly buffer VerticesOut {\n    Vertex verticesOut[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=3, std430) restrict readonly buffer VaryingsIn {\n    VaryingData varyingsIn[];\n};\n\nlayout(binding=4, std430) restrict writeonly buffer VaryingsOut {\n    VaryingData varyingsOut[];\n};\n\nlayout(binding=5, std430) restrict readonly buffer Meshes {\n    Vertex meshVertices[];\n};\n\nlayout(location=0) uniform uint vertexCount;\nlayout(location=1) uniform uint vertexOffset;\nlayout(location=2) uniform uint varyingOffset;\n\nvoid main() {\n    uint    indexIn     = gl_GlobalInvocationID.x;\n    uint    vertexOut   = indexIn + vertexOffset;\n    uint    varyingOut  = indexIn + varyingOffset;\n\n    if (indexIn >= vertexCount) {\n        return;\n    }\n\n    int     offset      = varyingsIn[indexIn]   .offset;\n    uint    reference   = indexIn - offset;\n    int     sharing     = varyingsIn[reference] .sharing;\n    int     mesh        = varyingsIn[reference] .mesh;\n\n    mat4    transformMatrix;\n    // mat3    normalMatrix;\n\n    if (sharing != -1) {\n        transformMatrix = sharings[sharing].transform;\n        // normalMatrix    = sharings[sharing].normal;\n    } else {\n        transformMatrix = mat4(1.0);\n        // normalMatrix    = mat3(1.0);\n    }\n\n    Vertex  vertexIn;\n    vec4    colorMesh;\n    // uvec2   uv2Mesh;\n\n    if (mesh != -1) {\n        vertexIn    = meshVertices[mesh + offset];\n        colorMesh   = unpackUnorm4x8    (                   vertexIn.color);\n        // uv2Mesh     = floatBitsToUint   (unpackSnorm2x16(   vertexIn.uv2));\n\n    } else {\n        vertexIn    = verticesIn[indexIn];\n        colorMesh   = vec4  (1.0);\n        // uv2Mesh     = uvec2 (0u);\n    }\n\n    vec4    colorIn = unpackUnorm4x8    (                   verticesIn[reference].color);\n    // uvec2   uv2In   = floatBitsToUint   (unpackSnorm2x16(   verticesIn[reference].uv2));\n\n    vec4    posOut      = transformMatrix   * vec4          (vertexIn.x, vertexIn.y, vertexIn.z, 1.0);\n    // vec3    normalOut   = normalMatrix      * unpackSnorm4x8(vertexIn.normal).xyz;\n    vec4    colorOut    = colorMesh         * colorIn;\n    // uvec2   uv2Out      = max                               (uv2In, uv2Mesh);\n\n    verticesOut[vertexOut].x        = posOut.x;\n    verticesOut[vertexOut].y        = posOut.y;\n    verticesOut[vertexOut].z        = posOut.z;\n\n    verticesOut[vertexOut].u0       = vertexIn.u0;\n    verticesOut[vertexOut].v0       = vertexIn.v0;\n\n    verticesOut[vertexOut].color    = packUnorm4x8  (colorOut);\n    // verticesOut[vertexOut].uv1      = verticesIn[reference].uv1;\n    // verticesOut[vertexOut].uv2      = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    // verticesOut[vertexOut].normal   = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n\n    varyingsOut[varyingOut].offset  = offset;\n    varyingsOut[varyingOut].noCull  = varyingsIn[reference].noCull;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/transform/pos_tex_vertex_transform_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    float   u0;\n    float   v0;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=0, std430) restrict readonly buffer VerticesIn {\n    Vertex verticesIn[];\n};\n\nlayout(binding=1, std430) restrict writeonly buffer VerticesOut {\n    Vertex verticesOut[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=3, std430) restrict readonly buffer VaryingsIn {\n    VaryingData varyingsIn[];\n};\n\nlayout(binding=4, std430) restrict writeonly buffer VaryingsOut {\n    VaryingData varyingsOut[];\n};\n\nlayout(binding=5, std430) restrict readonly buffer Meshes {\n    Vertex meshVertices[];\n};\n\nlayout(location=0) uniform uint vertexCount;\nlayout(location=1) uniform uint vertexOffset;\nlayout(location=2) uniform uint varyingOffset;\n\nvoid main() {\n    uint    indexIn     = gl_GlobalInvocationID.x;\n    uint    vertexOut   = indexIn + vertexOffset;\n    uint    varyingOut  = indexIn + varyingOffset;\n\n    if (indexIn >= vertexCount) {\n        return;\n    }\n\n    int     offset      = varyingsIn[indexIn]   .offset;\n    uint    reference   = indexIn - offset;\n    int     sharing     = varyingsIn[reference] .sharing;\n    int     mesh        = varyingsIn[reference] .mesh;\n\n    mat4    transformMatrix;\n    // mat3    normalMatrix;\n\n    if (sharing != -1) {\n        transformMatrix = sharings[sharing].transform;\n        // normalMatrix    = sharings[sharing].normal;\n    } else {\n        transformMatrix = mat4(1.0);\n        // normalMatrix    = mat3(1.0);\n    }\n\n    Vertex  vertexIn;\n    // vec4    colorMesh;\n    // uvec2   uv2Mesh;\n\n    if (mesh != -1) {\n        vertexIn    = meshVertices[mesh + offset];\n        // colorMesh   = unpackUnorm4x8    (                   vertexIn.color);\n        // uv2Mesh     = floatBitsToUint   (unpackSnorm2x16(   vertexIn.uv2));\n\n    } else {\n        vertexIn    = verticesIn[indexIn];\n        // colorMesh   = vec4  (1.0);\n        // uv2Mesh     = uvec2 (0u);\n    }\n\n    // vec4    colorIn = unpackUnorm4x8    (                   verticesIn[reference].color);\n    // uvec2   uv2In   = floatBitsToUint   (unpackSnorm2x16(   verticesIn[reference].uv2));\n\n    vec4    posOut      = transformMatrix   * vec4          (vertexIn.x, vertexIn.y, vertexIn.z, 1.0);\n    // vec3    normalOut   = normalMatrix      * unpackSnorm4x8(vertexIn.normal).xyz;\n    // vec4    colorOut    = colorMesh         * colorIn;\n    // uvec2   uv2Out      = max                               (uv2In, uv2Mesh);\n\n    verticesOut[vertexOut].x        = posOut.x;\n    verticesOut[vertexOut].y        = posOut.y;\n    verticesOut[vertexOut].z        = posOut.z;\n\n    verticesOut[vertexOut].u0       = vertexIn.u0;\n    verticesOut[vertexOut].v0       = vertexIn.v0;\n\n    // verticesOut[vertexOut].color    = packUnorm4x8  (colorOut);\n    // verticesOut[vertexOut].uv1      = verticesIn[reference].uv1;\n    // verticesOut[vertexOut].uv2      = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    // verticesOut[vertexOut].normal   = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n\n    varyingsOut[varyingOut].offset  = offset;\n    varyingsOut[varyingOut].noCull  = varyingsIn[reference].noCull;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/transform/pos_vertex_transform_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=0, std430) restrict readonly buffer VerticesIn {\n    Vertex verticesIn[];\n};\n\nlayout(binding=1, std430) restrict writeonly buffer VerticesOut {\n    Vertex verticesOut[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=3, std430) restrict readonly buffer VaryingsIn {\n    VaryingData varyingsIn[];\n};\n\nlayout(binding=4, std430) restrict writeonly buffer VaryingsOut {\n    VaryingData varyingsOut[];\n};\n\nlayout(binding=5, std430) restrict readonly buffer Meshes {\n    Vertex meshVertices[];\n};\n\nlayout(location=0) uniform uint vertexCount;\nlayout(location=1) uniform uint vertexOffset;\nlayout(location=2) uniform uint varyingOffset;\n\nvoid main() {\n    uint    indexIn     = gl_GlobalInvocationID.x;\n    uint    vertexOut   = indexIn + vertexOffset;\n    uint    varyingOut  = indexIn + varyingOffset;\n\n    if (indexIn >= vertexCount) {\n        return;\n    }\n\n    int     offset      = varyingsIn[indexIn]   .offset;\n    uint    reference   = indexIn - offset;\n    int     sharing     = varyingsIn[reference] .sharing;\n    int     mesh        = varyingsIn[reference] .mesh;\n\n    mat4    transformMatrix;\n    // mat3    normalMatrix;\n\n    if (sharing != -1) {\n        transformMatrix = sharings[sharing].transform;\n        // normalMatrix    = sharings[sharing].normal;\n    } else {\n        transformMatrix = mat4(1.0);\n        // normalMatrix    = mat3(1.0);\n    }\n\n    Vertex  vertexIn;\n    // vec4    colorMesh;\n    // uvec2   uv2Mesh;\n\n    if (mesh != -1) {\n        vertexIn    = meshVertices[mesh + offset];\n        // colorMesh   = unpackUnorm4x8    (                   vertexIn.color);\n        // uv2Mesh     = floatBitsToUint   (unpackSnorm2x16(   vertexIn.uv2));\n\n    } else {\n        vertexIn    = verticesIn[indexIn];\n        // colorMesh   = vec4  (1.0);\n        // uv2Mesh     = uvec2 (0u);\n    }\n\n    // vec4    colorIn = unpackUnorm4x8    (                   verticesIn[reference].color);\n    // uvec2   uv2In   = floatBitsToUint   (unpackSnorm2x16(   verticesIn[reference].uv2));\n\n    vec4    posOut      = transformMatrix   * vec4          (vertexIn.x, vertexIn.y, vertexIn.z, 1.0);\n    // vec3    normalOut   = normalMatrix      * unpackSnorm4x8(vertexIn.normal).xyz;\n    // vec4    colorOut    = colorMesh         * colorIn;\n    // uvec2   uv2Out      = max                               (uv2In, uv2Mesh);\n\n    verticesOut[vertexOut].x        = posOut.x;\n    verticesOut[vertexOut].y        = posOut.y;\n    verticesOut[vertexOut].z        = posOut.z;\n\n    // verticesOut[vertexOut].u0       = vertexIn.u0;\n    // verticesOut[vertexOut].v0       = vertexIn.v0;\n\n    // verticesOut[vertexOut].color    = packUnorm4x8  (colorOut);\n    // verticesOut[vertexOut].uv1      = verticesIn[reference].uv1;\n    // verticesOut[vertexOut].uv2      = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    // verticesOut[vertexOut].normal   = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n\n    varyingsOut[varyingOut].offset  = offset;\n    varyingsOut[varyingOut].noCull  = varyingsIn[reference].noCull;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/uploading/block_mesh_uploading_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    uint    uv2;\n    uint    normal;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct MeshInfo {\n    int     sharing;\n    int     noCull;\n    uint    color;\n    uint    uv1;\n    uint    uv2;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict writeonly buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4, std430) restrict writeonly buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=7, std430) restrict readonly buffer Meshes {\n    Vertex meshVertices[];\n};\n\nlayout(binding=8, std430) restrict readonly buffer MeshInfos {\n    MeshInfo meshInfos[];\n};\n\nlayout(location=0) uniform uint meshCount;\nlayout(location=1) uniform uint meshSize;\nlayout(location=2) uniform uint vertexOffset;\nlayout(location=3) uniform uint varyingOffset;\nlayout(location=4) uniform uint meshOffset;\n\nvoid main() {\n    uint        indexIn         = gl_GlobalInvocationID.x;\n    uint        meshIndex       = indexIn / meshSize;\n    uint        index           = indexIn % meshSize;\n\n    if (meshIndex >= meshCount) {\n        return;\n    }\n\n    Vertex      vertex          = meshVertices  [meshOffset + index];\n    MeshInfo    meshInfo        = meshInfos     [meshIndex];\n    SharingData sharingData     = sharings      [meshInfo.sharing];\n    uint        vertexIndex     = index + meshIndex * meshSize + vertexOffset;\n    uint        varyingIndex    = index + meshIndex * meshSize + varyingOffset;\n\n    vec4        colorIn         = unpackUnorm4x8    (meshInfo   .color);\n    vec4        colorMesh       = unpackUnorm4x8    (vertex     .color);\n    uvec2       uv2In           = floatBitsToUint   (unpackSnorm2x16(meshInfo   .uv2));\n    uvec2       uv2Mesh         = floatBitsToUint   (unpackSnorm2x16(vertex     .uv2));\n\n    vec4        colorOut        = colorIn * colorMesh;\n    uvec2       uv2Out          = max(uv2In, uv2Mesh);\n\n    vec4        posOut          = sharingData.transform * vec4          (vertex.x, vertex.y, vertex.z, 1.0);\n    vec3        normalOut       = sharingData.normal    * unpackSnorm4x8(vertex.normal).xyz;\n\n    vertices[vertexIndex].x         = posOut.x;\n    vertices[vertexIndex].y         = posOut.y;\n    vertices[vertexIndex].z         = posOut.z;\n\n    vertices[vertexIndex].color     = packUnorm4x8(colorOut);\n\n    vertices[vertexIndex].u0        = vertex.u0;\n    vertices[vertexIndex].v0        = vertex.v0;\n\n    // vertices[vertexIndex].uv1       = meshInfo  .uv1;\n    vertices[vertexIndex].uv2       = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    vertices[vertexIndex].normal    = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n\n    varyings[varyingIndex].offset   = 0;\n    varyings[varyingIndex].sharing  = meshInfo.sharing;\n    varyings[varyingIndex].noCull   = meshInfo.noCull;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/uploading/entity_mesh_uploading_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    uint    uv1;\n    uint    uv2;\n    uint    normal;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct MeshInfo {\n    int     sharing;\n    int     noCull;\n    uint    color;\n    uint    uv1;\n    uint    uv2;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict writeonly buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4, std430) restrict writeonly buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=7, std430) restrict readonly buffer Meshes {\n    Vertex meshVertices[];\n};\n\nlayout(binding=8, std430) restrict readonly buffer MeshInfos {\n    MeshInfo meshInfos[];\n};\n\nlayout(location=0) uniform uint meshCount;\nlayout(location=1) uniform uint meshSize;\nlayout(location=2) uniform uint vertexOffset;\nlayout(location=3) uniform uint varyingOffset;\nlayout(location=4) uniform uint meshOffset;\n\nvoid main() {\n    uint        indexIn         = gl_GlobalInvocationID.x;\n    uint        meshIndex       = indexIn / meshSize;\n    uint        index           = indexIn % meshSize;\n\n    if (meshIndex >= meshCount) {\n        return;\n    }\n\n    Vertex      vertex          = meshVertices  [meshOffset + index];\n    MeshInfo    meshInfo        = meshInfos     [meshIndex];\n    SharingData sharingData     = sharings      [meshInfo.sharing];\n    uint        vertexIndex     = index + meshIndex * meshSize + vertexOffset;\n    uint        varyingIndex    = index + meshIndex * meshSize + varyingOffset;\n\n    vec4        colorIn         = unpackUnorm4x8    (meshInfo   .color);\n    vec4        colorMesh       = unpackUnorm4x8    (vertex     .color);\n    uvec2       uv2In           = floatBitsToUint   (unpackSnorm2x16(meshInfo   .uv2));\n    uvec2       uv2Mesh         = floatBitsToUint   (unpackSnorm2x16(vertex     .uv2));\n\n    vec4        colorOut        = colorIn * colorMesh;\n    uvec2       uv2Out          = max(uv2In, uv2Mesh);\n\n    vec4        posOut          = sharingData.transform * vec4          (vertex.x, vertex.y, vertex.z, 1.0);\n    vec3        normalOut       = sharingData.normal    * unpackSnorm4x8(vertex.normal).xyz;\n\n    vertices[vertexIndex].x         = posOut.x;\n    vertices[vertexIndex].y         = posOut.y;\n    vertices[vertexIndex].z         = posOut.z;\n\n    vertices[vertexIndex].color     = packUnorm4x8(colorOut);\n\n    vertices[vertexIndex].u0        = vertex.u0;\n    vertices[vertexIndex].v0        = vertex.v0;\n\n    vertices[vertexIndex].uv1       = meshInfo.uv1;\n    vertices[vertexIndex].uv2       = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    vertices[vertexIndex].normal    = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n\n    varyings[varyingIndex].offset   = 0;\n    varyings[varyingIndex].sharing  = meshInfo.sharing;\n    varyings[varyingIndex].noCull   = meshInfo.noCull;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/uploading/pos_color_mesh_uploading_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct MeshInfo {\n    int     sharing;\n    int     noCull;\n    uint    color;\n    uint    uv1;\n    uint    uv2;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict writeonly buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4, std430) restrict writeonly buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=7, std430) restrict readonly buffer Meshes {\n    Vertex meshVertices[];\n};\n\nlayout(binding=8, std430) restrict readonly buffer MeshInfos {\n    MeshInfo meshInfos[];\n};\n\nlayout(location=0) uniform uint meshCount;\nlayout(location=1) uniform uint meshSize;\nlayout(location=2) uniform uint vertexOffset;\nlayout(location=3) uniform uint varyingOffset;\nlayout(location=4) uniform uint meshOffset;\n\nvoid main() {\n    uint        indexIn         = gl_GlobalInvocationID.x;\n    uint        meshIndex       = indexIn / meshSize;\n    uint        index           = indexIn % meshSize;\n\n    if (meshIndex >= meshCount) {\n        return;\n    }\n\n    Vertex      vertex          = meshVertices  [meshOffset + index];\n    MeshInfo    meshInfo        = meshInfos     [meshIndex];\n    SharingData sharingData     = sharings      [meshInfo.sharing];\n    uint        vertexIndex     = index + meshIndex * meshSize + vertexOffset;\n    uint        varyingIndex    = index + meshIndex * meshSize + varyingOffset;\n\n    vec4        colorIn         = unpackUnorm4x8    (meshInfo   .color);\n    vec4        colorMesh       = unpackUnorm4x8    (vertex     .color);\n    // uvec2       uv2In           = floatBitsToUint   (unpackSnorm2x16(meshInfo   .uv2));\n    // uvec2       uv2Mesh         = floatBitsToUint   (unpackSnorm2x16(vertex     .uv2));\n\n    vec4        colorOut        = colorIn * colorMesh;\n    // uvec2       uv2Out          = max(uv2In, uv2Mesh);\n\n    vec4        posOut          = sharingData.transform * vec4          (vertex.x, vertex.y, vertex.z, 1.0);\n    // vec3        normalOut       = sharingData.normal    * unpackSnorm4x8(vertex.normal).xyz;\n\n    vertices[vertexIndex].x         = posOut.x;\n    vertices[vertexIndex].y         = posOut.y;\n    vertices[vertexIndex].z         = posOut.z;\n\n    vertices[vertexIndex].color     = packUnorm4x8(colorOut);\n\n    // vertices[vertexIndex].u0        = vertex.u0;\n    // vertices[vertexIndex].v0        = vertex.v0;\n\n    // vertices[vertexIndex].uv1       = meshInfo  .uv1;\n    // vertices[vertexIndex].uv2       = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    // vertices[vertexIndex].normal    = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n\n    varyings[varyingIndex].offset   = 0;\n    varyings[varyingIndex].sharing  = meshInfo.sharing;\n    varyings[varyingIndex].noCull   = meshInfo.noCull;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/uploading/pos_color_tex_light_mesh_uploading_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    uint    color;\n    float   u0;\n    float   v0;\n    uint    uv2;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct MeshInfo {\n    int     sharing;\n    int     noCull;\n    uint    color;\n    uint    uv1;\n    uint    uv2;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict writeonly buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4, std430) restrict writeonly buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=7, std430) restrict readonly buffer Meshes {\n    Vertex meshVertices[];\n};\n\nlayout(binding=8, std430) restrict readonly buffer MeshInfos {\n    MeshInfo meshInfos[];\n};\n\nlayout(location=0) uniform uint meshCount;\nlayout(location=1) uniform uint meshSize;\nlayout(location=2) uniform uint vertexOffset;\nlayout(location=3) uniform uint varyingOffset;\nlayout(location=4) uniform uint meshOffset;\n\nvoid main() {\n    uint        indexIn         = gl_GlobalInvocationID.x;\n    uint        meshIndex       = indexIn / meshSize;\n    uint        index           = indexIn % meshSize;\n\n    if (meshIndex >= meshCount) {\n        return;\n    }\n\n    Vertex      vertex          = meshVertices  [meshOffset + index];\n    MeshInfo    meshInfo        = meshInfos     [meshIndex];\n    SharingData sharingData     = sharings      [meshInfo.sharing];\n    uint        vertexIndex     = index + meshIndex * meshSize + vertexOffset;\n    uint        varyingIndex    = index + meshIndex * meshSize + varyingOffset;\n\n    vec4        colorIn         = unpackUnorm4x8    (meshInfo   .color);\n    vec4        colorMesh       = unpackUnorm4x8    (vertex     .color);\n    uvec2       uv2In           = floatBitsToUint   (unpackSnorm2x16(meshInfo   .uv2));\n    uvec2       uv2Mesh         = floatBitsToUint   (unpackSnorm2x16(vertex     .uv2));\n\n    vec4        colorOut        = colorIn * colorMesh;\n    uvec2       uv2Out          = max(uv2In, uv2Mesh);\n\n    vec4        posOut          = sharingData.transform * vec4          (vertex.x, vertex.y, vertex.z, 1.0);\n    // vec3        normalOut       = sharingData.normal    * unpackSnorm4x8(vertex.normal).xyz;\n\n    vertices[vertexIndex].x         = posOut.x;\n    vertices[vertexIndex].y         = posOut.y;\n    vertices[vertexIndex].z         = posOut.z;\n\n    vertices[vertexIndex].color     = packUnorm4x8(colorOut);\n\n    vertices[vertexIndex].u0        = vertex.u0;\n    vertices[vertexIndex].v0        = vertex.v0;\n\n    // vertices[vertexIndex].uv1       = meshInfo  .uv1;\n    vertices[vertexIndex].uv2       = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    // vertices[vertexIndex].normal    = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n\n    varyings[varyingIndex].offset   = 0;\n    varyings[varyingIndex].sharing  = meshInfo.sharing;\n    varyings[varyingIndex].noCull   = meshInfo.noCull;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/uploading/pos_mesh_uploading_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct MeshInfo {\n    int     sharing;\n    int     noCull;\n    uint    color;\n    uint    uv1;\n    uint    uv2;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict writeonly buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4, std430) restrict writeonly buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=7, std430) restrict readonly buffer Meshes {\n    Vertex meshVertices[];\n};\n\nlayout(binding=8, std430) restrict readonly buffer MeshInfos {\n    MeshInfo meshInfos[];\n};\n\nlayout(location=0) uniform uint meshCount;\nlayout(location=1) uniform uint meshSize;\nlayout(location=2) uniform uint vertexOffset;\nlayout(location=3) uniform uint varyingOffset;\nlayout(location=4) uniform uint meshOffset;\n\nvoid main() {\n    uint        indexIn         = gl_GlobalInvocationID.x;\n    uint        meshIndex       = indexIn / meshSize;\n    uint        index           = indexIn % meshSize;\n\n    if (meshIndex >= meshCount) {\n        return;\n    }\n\n    Vertex      vertex          = meshVertices  [meshOffset + index];\n    MeshInfo    meshInfo        = meshInfos     [meshIndex];\n    SharingData sharingData     = sharings      [meshInfo.sharing];\n    uint        vertexIndex     = index + meshIndex * meshSize + vertexOffset;\n    uint        varyingIndex    = index + meshIndex * meshSize + varyingOffset;\n\n    // vec4        colorIn         = unpackUnorm4x8    (meshInfo   .color);\n    // vec4        colorMesh       = unpackUnorm4x8    (vertex     .color);\n    // uvec2       uv2In           = floatBitsToUint   (unpackSnorm2x16(meshInfo   .uv2));\n    // uvec2       uv2Mesh         = floatBitsToUint   (unpackSnorm2x16(vertex     .uv2));\n\n    // vec4        colorOut        = colorIn * colorMesh;\n    // uvec2       uv2Out          = max(uv2In, uv2Mesh);\n\n    vec4        posOut          = sharingData.transform * vec4          (vertex.x, vertex.y, vertex.z, 1.0);\n    // vec3        normalOut       = sharingData.normal    * unpackSnorm4x8(vertex.normal).xyz;\n\n    vertices[vertexIndex].x         = posOut.x;\n    vertices[vertexIndex].y         = posOut.y;\n    vertices[vertexIndex].z         = posOut.z;\n\n    // vertices[vertexIndex].color     = packUnorm4x8(colorOut);\n\n    // vertices[vertexIndex].u0        = vertex.u0;\n    // vertices[vertexIndex].v0        = vertex.v0;\n\n    // vertices[vertexIndex].uv1       = meshInfo  .uv1;\n    // vertices[vertexIndex].uv2       = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    // vertices[vertexIndex].normal    = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n\n    varyings[varyingIndex].offset   = 0;\n    varyings[varyingIndex].sharing  = meshInfo.sharing;\n    varyings[varyingIndex].noCull   = meshInfo.noCull;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/uploading/pos_tex_color_mesh_uploading_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    float   u0;\n    float   v0;\n    uint    color;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct MeshInfo {\n    int     sharing;\n    int     noCull;\n    uint    color;\n    uint    uv1;\n    uint    uv2;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict writeonly buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4, std430) restrict writeonly buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=7, std430) restrict readonly buffer Meshes {\n    Vertex meshVertices[];\n};\n\nlayout(binding=8, std430) restrict readonly buffer MeshInfos {\n    MeshInfo meshInfos[];\n};\n\nlayout(location=0) uniform uint meshCount;\nlayout(location=1) uniform uint meshSize;\nlayout(location=2) uniform uint vertexOffset;\nlayout(location=3) uniform uint varyingOffset;\nlayout(location=4) uniform uint meshOffset;\n\nvoid main() {\n    uint        indexIn         = gl_GlobalInvocationID.x;\n    uint        meshIndex       = indexIn / meshSize;\n    uint        index           = indexIn % meshSize;\n\n    if (meshIndex >= meshCount) {\n        return;\n    }\n\n    Vertex      vertex          = meshVertices  [meshOffset + index];\n    MeshInfo    meshInfo        = meshInfos     [meshIndex];\n    SharingData sharingData     = sharings      [meshInfo.sharing];\n    uint        vertexIndex     = index + meshIndex * meshSize + vertexOffset;\n    uint        varyingIndex    = index + meshIndex * meshSize + varyingOffset;\n\n    vec4        colorIn         = unpackUnorm4x8    (meshInfo   .color);\n    vec4        colorMesh       = unpackUnorm4x8    (vertex     .color);\n    // uvec2       uv2In           = floatBitsToUint   (unpackSnorm2x16(meshInfo   .uv2));\n    // uvec2       uv2Mesh         = floatBitsToUint   (unpackSnorm2x16(vertex     .uv2));\n\n    vec4        colorOut        = colorIn * colorMesh;\n    // uvec2       uv2Out          = max(uv2In, uv2Mesh);\n\n    vec4        posOut          = sharingData.transform * vec4          (vertex.x, vertex.y, vertex.z, 1.0);\n    // vec3        normalOut       = sharingData.normal    * unpackSnorm4x8(vertex.normal).xyz;\n\n    vertices[vertexIndex].x         = posOut.x;\n    vertices[vertexIndex].y         = posOut.y;\n    vertices[vertexIndex].z         = posOut.z;\n\n    vertices[vertexIndex].color     = packUnorm4x8(colorOut);\n\n    vertices[vertexIndex].u0        = vertex.u0;\n    vertices[vertexIndex].v0        = vertex.v0;\n\n    // vertices[vertexIndex].uv1       = meshInfo  .uv1;\n    // vertices[vertexIndex].uv2       = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    // vertices[vertexIndex].normal    = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n\n    varyings[varyingIndex].offset   = 0;\n    varyings[varyingIndex].sharing  = meshInfo.sharing;\n    varyings[varyingIndex].noCull   = meshInfo.noCull;\n}"
  },
  {
    "path": "src/main/resources/assets/acceleratedrendering/shaders/core/uploading/pos_tex_mesh_uploading_shader.compute",
    "content": "#version 460 core\n\nstruct Vertex {\n    float   x;\n    float   y;\n    float   z;\n    float   u0;\n    float   v0;\n};\n\nstruct VaryingData {\n    int     offset;\n    int     sharing;\n    int     mesh;\n    int     noCull;\n};\n\nstruct SharingData {\n    mat4    transform;\n    mat3    normal;\n};\n\nstruct MeshInfo {\n    int     sharing;\n    int     noCull;\n    uint    color;\n    uint    uv1;\n    uint    uv2;\n};\n\nlayout(local_size_x = 128) in;\n\nlayout(binding=1, std430) restrict writeonly buffer Vertices {\n    Vertex vertices[];\n};\n\nlayout(binding=2, std430) restrict readonly buffer Sharings {\n    SharingData sharings[];\n};\n\nlayout(binding=4, std430) restrict writeonly buffer Varyings {\n    VaryingData varyings[];\n};\n\nlayout(binding=7, std430) restrict readonly buffer Meshes {\n    Vertex meshVertices[];\n};\n\nlayout(binding=8, std430) restrict readonly buffer MeshInfos {\n    MeshInfo meshInfos[];\n};\n\nlayout(location=0) uniform uint meshCount;\nlayout(location=1) uniform uint meshSize;\nlayout(location=2) uniform uint vertexOffset;\nlayout(location=3) uniform uint varyingOffset;\nlayout(location=4) uniform uint meshOffset;\n\nvoid main() {\n    uint        indexIn         = gl_GlobalInvocationID.x;\n    uint        meshIndex       = indexIn / meshSize;\n    uint        index           = indexIn % meshSize;\n\n    if (meshIndex >= meshCount) {\n        return;\n    }\n\n    Vertex      vertex          = meshVertices  [meshOffset + index];\n    MeshInfo    meshInfo        = meshInfos     [meshIndex];\n    SharingData sharingData     = sharings      [meshInfo.sharing];\n    uint        vertexIndex     = index + meshIndex * meshSize + vertexOffset;\n    uint        varyingIndex    = index + meshIndex * meshSize + varyingOffset;\n\n    // vec4        colorIn         = unpackUnorm4x8    (meshInfo   .color);\n    // vec4        colorMesh       = unpackUnorm4x8    (vertex     .color);\n    // uvec2       uv2In           = floatBitsToUint   (unpackSnorm2x16(meshInfo   .uv2));\n    // uvec2       uv2Mesh         = floatBitsToUint   (unpackSnorm2x16(vertex     .uv2));\n\n    // vec4        colorOut        = colorIn * colorMesh;\n    // uvec2       uv2Out          = max(uv2In, uv2Mesh);\n\n    vec4        posOut          = sharingData.transform * vec4          (vertex.x, vertex.y, vertex.z, 1.0);\n    // vec3        normalOut       = sharingData.normal    * unpackSnorm4x8(vertex.normal).xyz;\n\n    vertices[vertexIndex].x         = posOut.x;\n    vertices[vertexIndex].y         = posOut.y;\n    vertices[vertexIndex].z         = posOut.z;\n\n    // vertices[vertexIndex].color     = packUnorm4x8(colorOut);\n\n    vertices[vertexIndex].u0        = vertex.u0;\n    vertices[vertexIndex].v0        = vertex.v0;\n\n    // vertices[vertexIndex].uv1       = meshInfo  .uv1;\n    // vertices[vertexIndex].uv2       = packSnorm2x16 (uintBitsToFloat(uv2Out));\n    // vertices[vertexIndex].normal    = packSnorm4x8  (vec4           (normalize(normalOut), 0.0));\n\n    varyings[varyingIndex].offset   = 0;\n    varyings[varyingIndex].sharing  = meshInfo.sharing;\n    varyings[varyingIndex].noCull   = meshInfo.noCull;\n}"
  }
]