Repository: Argon4W/AcceleratedRendering Branch: main Commit: 2644bed53eb0 Files: 359 Total size: 805.2 KB Directory structure: gitextract_d9366gy4/ ├── .gitattributes ├── .github/ │ └── workflows/ │ └── build.yml ├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── changelogs/ │ ├── changelog-1.0.0.md │ ├── changelog-1.0.1.md │ ├── changelog-1.0.2.md │ ├── changelog-1.0.3.md │ ├── changelog-1.0.4.md │ ├── changelog-1.0.5.1.md │ ├── changelog-1.0.5.md │ ├── changelog-1.0.6.md │ ├── changelog-1.0.7.md │ └── changelog-1.0.8.md ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── images/ │ ├── LOGO.psd │ └── benchmark.psd ├── settings.gradle └── src/ └── main/ ├── java/ │ └── com/ │ └── github/ │ └── argon4w/ │ └── acceleratedrendering/ │ ├── AcceleratedRenderingModEntry.java │ ├── compat/ │ │ ├── AbstractCompatMixinPlugin.java │ │ ├── curios/ │ │ │ ├── CuriosCompatFeature.java │ │ │ └── mixins/ │ │ │ └── CuriosLayerMixin.java │ │ ├── immediatelyfast/ │ │ │ └── mixins/ │ │ │ ├── BatchableBufferSourceMixin.java │ │ │ ├── BatchingBuffersMixin.java │ │ │ └── WrappedRenderLayerMixin.java │ │ └── iris/ │ │ ├── IrisCompatBuffers.java │ │ ├── IrisCompatBuffersProvider.java │ │ ├── IrisCompatFeature.java │ │ ├── environments/ │ │ │ └── IrisBufferEnvironment.java │ │ ├── interfaces/ │ │ │ ├── IIrisAcceleratedBufferBuilder.java │ │ │ ├── IIrisMeshInfo.java │ │ │ └── IIrisMeshInfoCache.java │ │ ├── mixins/ │ │ │ ├── acceleratedrendering/ │ │ │ │ ├── AcceleratedBufferBuilderMixin.java │ │ │ │ ├── AcceleratedBufferSourceMixin.java │ │ │ │ ├── AcceleratedRenderingModEntryMixin.java │ │ │ │ ├── CoreBuffersProviderMixin.java │ │ │ │ ├── FlattenMeshInfoCacheMixin.java │ │ │ │ ├── IBufferEnvironmentPresetsMixin.java │ │ │ │ ├── MeshUploaderMixin.java │ │ │ │ ├── MeshUploadingProgramDispatcherMixin.java │ │ │ │ ├── RenderTypeUtilsMixin.java │ │ │ │ ├── SimpleMeshInfoCacheMixin.java │ │ │ │ ├── SimpleMeshInfoMixin.java │ │ │ │ └── UnsafeMemoryMeshInfoCacheMixin.java │ │ │ ├── iris/ │ │ │ │ ├── FullyBufferedMultiBufferSourceMixin.java │ │ │ │ ├── HandRendererMixin.java │ │ │ │ ├── IrisVertexFormatsMixin.java │ │ │ │ ├── ModelToEntityVertexSerializerMixin.java │ │ │ │ └── ShadowRendererMixin.java │ │ │ ├── plugin/ │ │ │ │ └── IrisCompatMixinPlugin.java │ │ │ └── vanilla/ │ │ │ └── LevelRendererMixin.java │ │ └── programs/ │ │ ├── IrisPrograms.java │ │ ├── culling/ │ │ │ ├── IrisCullingProgramDispatcher.java │ │ │ └── IrisCullingProgramSelector.java │ │ └── processing/ │ │ └── IrisPolygonProcessor.java │ ├── configs/ │ │ ├── FeatureConfig.java │ │ ├── FeatureStatus.java │ │ └── PipelineSetting.java │ ├── core/ │ │ ├── CoreBuffers.java │ │ ├── CoreBuffersProvider.java │ │ ├── CoreFeature.java │ │ ├── CoreStates.java │ │ ├── backends/ │ │ │ ├── DebugOutput.java │ │ │ ├── GLConstants.java │ │ │ ├── Sync.java │ │ │ ├── VertexArray.java │ │ │ ├── buffers/ │ │ │ │ ├── EmptyServerBuffer.java │ │ │ │ ├── IClientBuffer.java │ │ │ │ ├── IServerBuffer.java │ │ │ │ ├── ImmutableBuffer.java │ │ │ │ ├── MappedBuffer.java │ │ │ │ └── MutableBuffer.java │ │ │ ├── programs/ │ │ │ │ ├── BarrierFlags.java │ │ │ │ ├── ComputeProgram.java │ │ │ │ ├── ComputeShader.java │ │ │ │ └── Uniform.java │ │ │ └── states/ │ │ │ ├── EmptyBindingState.java │ │ │ ├── FramebufferBindingState.java │ │ │ ├── IBindingState.java │ │ │ ├── buffers/ │ │ │ │ ├── BlockBufferBindingStateType.java │ │ │ │ ├── BufferBlockType.java │ │ │ │ ├── SimpleBlockBufferBindingState.java │ │ │ │ └── cache/ │ │ │ │ ├── BlockBufferBindingCacheType.java │ │ │ │ ├── FlattenBlockBufferBindingCache.java │ │ │ │ ├── IBlockBufferBindingCache.java │ │ │ │ ├── SimpleBlockBufferBinding.java │ │ │ │ ├── SimpleBlockBufferBindingCache.java │ │ │ │ └── UnsafeMemoryBlockBufferBindingCache.java │ │ │ ├── scissors/ │ │ │ │ ├── MojangScissorBindingState.java │ │ │ │ ├── OpenGLScissorBindingState.java │ │ │ │ └── ScissorBindingStateType.java │ │ │ └── viewports/ │ │ │ ├── MojangViewportBindingState.java │ │ │ ├── OpenGLViewportBindingState.java │ │ │ └── ViewportBindingStateType.java │ │ ├── buffers/ │ │ │ ├── AcceleratedBufferSources.java │ │ │ ├── EmptyAcceleratedBufferSources.java │ │ │ ├── accelerated/ │ │ │ │ ├── AcceleratedBufferSource.java │ │ │ │ ├── AcceleratedRingBuffers.java │ │ │ │ ├── IAcceleratedBufferSource.java │ │ │ │ ├── IAccelerationHolder.java │ │ │ │ ├── builders/ │ │ │ │ │ ├── AcceleratedBufferBuilder.java │ │ │ │ │ ├── AcceleratedEntityOutlineGenerator.java │ │ │ │ │ ├── AcceleratedSheetedDecalTextureGenerator.java │ │ │ │ │ ├── AcceleratedSpriteCoordinateExpander.java │ │ │ │ │ ├── AcceleratedVertexConsumerWrapper.java │ │ │ │ │ ├── BufferSourceExtension.java │ │ │ │ │ ├── IAcceleratableBufferSource.java │ │ │ │ │ ├── IAcceleratedVertexConsumer.java │ │ │ │ │ ├── IBufferGraph.java │ │ │ │ │ └── VertexConsumerExtension.java │ │ │ │ ├── layers/ │ │ │ │ │ ├── LayerDrawType.java │ │ │ │ │ ├── LayerKey.java │ │ │ │ │ ├── functions/ │ │ │ │ │ │ ├── CustomLayerFunction.java │ │ │ │ │ │ ├── EmptyLayerFunction.java │ │ │ │ │ │ └── ILayerFunction.java │ │ │ │ │ └── storage/ │ │ │ │ │ ├── ILayerContexts.java │ │ │ │ │ ├── ILayerStorage.java │ │ │ │ │ ├── LayerStorageType.java │ │ │ │ │ ├── SeparatedLayerStorage.java │ │ │ │ │ ├── SimpleLayerContexts.java │ │ │ │ │ ├── empty/ │ │ │ │ │ │ ├── EmptyLayerContexts.java │ │ │ │ │ │ └── EmptyLayerStorage.java │ │ │ │ │ └── sorted/ │ │ │ │ │ ├── SortedLayerContexts.java │ │ │ │ │ └── SortedLayerStorage.java │ │ │ │ ├── pools/ │ │ │ │ │ ├── DrawContextPool.java │ │ │ │ │ ├── ElementBufferPool.java │ │ │ │ │ ├── StagingBufferPool.java │ │ │ │ │ └── meshes/ │ │ │ │ │ ├── FlattenMeshInfoCache.java │ │ │ │ │ ├── IMeshInfoCache.java │ │ │ │ │ ├── MeshInfoCacheType.java │ │ │ │ │ ├── MeshUploaderPool.java │ │ │ │ │ ├── SimpleMeshInfo.java │ │ │ │ │ ├── SimpleMeshInfoCache.java │ │ │ │ │ └── UnsafeMemoryMeshInfoCache.java │ │ │ │ └── renderers/ │ │ │ │ ├── DecoratedRenderer.java │ │ │ │ ├── IAcceleratedRenderer.java │ │ │ │ ├── IBufferDecorator.java │ │ │ │ └── SheetedDecalTextureRenderer.java │ │ │ ├── environments/ │ │ │ │ ├── IBufferEnvironment.java │ │ │ │ └── VanillaBufferEnvironment.java │ │ │ └── memory/ │ │ │ ├── IMemoryInterface.java │ │ │ ├── IMemoryLayout.java │ │ │ ├── NullMemoryInterface.java │ │ │ ├── SimpleDynamicMemoryInterface.java │ │ │ ├── SimpleMemoryInterface.java │ │ │ └── VertexLayout.java │ │ ├── meshes/ │ │ │ ├── ClientMesh.java │ │ │ ├── EmptyMesh.java │ │ │ ├── IMesh.java │ │ │ ├── MeshType.java │ │ │ ├── ServerMesh.java │ │ │ ├── collectors/ │ │ │ │ ├── CulledMeshCollector.java │ │ │ │ ├── IMeshCollector.java │ │ │ │ └── SimpleMeshCollector.java │ │ │ └── data/ │ │ │ ├── MeshData.java │ │ │ └── cache/ │ │ │ ├── IMeshDataCache.java │ │ │ ├── IgnoreMeshDataCache.java │ │ │ ├── MeshDataCacheType.java │ │ │ ├── MeshDataCaches.java │ │ │ └── SimpleMeshDataCache.java │ │ ├── mixins/ │ │ │ ├── GameRendererMixin.java │ │ │ ├── LevelRendererMixin.java │ │ │ ├── buffers/ │ │ │ │ ├── BufferBuilderMixin.java │ │ │ │ ├── BufferSourceMixin.java │ │ │ │ ├── EntityOutlineGeneratorMixin.java │ │ │ │ ├── MinecraftMixin.java │ │ │ │ ├── OutlineBufferSourceMixin.java │ │ │ │ ├── SheetedDecalTextureGeneratorMixin.java │ │ │ │ ├── SpriteCoordinateExpanderMixin.java │ │ │ │ ├── VertexConsumerMixin.java │ │ │ │ ├── VertexDoubleConsumerMixin.java │ │ │ │ └── VertexMultipleConsumerMixin.java │ │ │ └── compatibility/ │ │ │ ├── MinecraftMixin.java │ │ │ ├── ParticleEngineMixin.java │ │ │ ├── RenderTypeMixin.java │ │ │ └── WindowMixin.java │ │ ├── programs/ │ │ │ ├── ComputeShaderDefinition.java │ │ │ ├── ComputeShaderProgramLoader.java │ │ │ ├── ComputeShaderPrograms.java │ │ │ ├── LoadComputeShaderEvent.java │ │ │ ├── culling/ │ │ │ │ ├── ICullingProgramDispatcher.java │ │ │ │ ├── ICullingProgramSelector.java │ │ │ │ ├── LoadCullingProgramSelectorEvent.java │ │ │ │ ├── PassThroughCullingProgramDispatcher.java │ │ │ │ └── PassThroughCullingProgramSelector.java │ │ │ ├── dispatchers/ │ │ │ │ ├── EmptyProgramDispatcher.java │ │ │ │ ├── FixedPolygonProgramDispatcher.java │ │ │ │ ├── IPolygonProgramDispatcher.java │ │ │ │ ├── MeshUploadingProgramDispatcher.java │ │ │ │ └── TransformProgramDispatcher.java │ │ │ ├── overrides/ │ │ │ │ ├── IShaderProgramOverride.java │ │ │ │ ├── IShaderProgramOverrides.java │ │ │ │ ├── ITransformShaderProgramOverride.java │ │ │ │ ├── IUploadingShaderProgramOverride.java │ │ │ │ ├── LoadShaderProgramOverridesEvent.java │ │ │ │ └── OverrideProgramType.java │ │ │ └── processing/ │ │ │ ├── EmptyPolygonProcessor.java │ │ │ ├── IPolygonProcessor.java │ │ │ └── LoadPolygonProcessorEvent.java │ │ └── utils/ │ │ ├── CullerUtils.java │ │ ├── DirectionUtils.java │ │ ├── EmptyIterator.java │ │ ├── FastColorUtils.java │ │ ├── FuzzyMatrix4f.java │ │ ├── IntArrayHashStrategy.java │ │ ├── LoopResetPool.java │ │ ├── MemUtils.java │ │ ├── MutableSize.java │ │ ├── PackedVector2i.java │ │ ├── PoseStackExtension.java │ │ ├── RegistryFilter.java │ │ ├── RenderTypeUtils.java │ │ ├── ResourceLocationUtils.java │ │ ├── SimpleCachedArray.java │ │ ├── SimpleResetPool.java │ │ ├── SimpleTextureTarget.java │ │ ├── TextureUtils.java │ │ └── Vertex.java │ └── features/ │ ├── culling/ │ │ ├── OrientationCullingFeature.java │ │ ├── OrientationCullingProgramDispatcher.java │ │ ├── OrientationCullingProgramSelector.java │ │ └── OrientationCullingPrograms.java │ ├── emf/ │ │ ├── IEMFModelVariant.java │ │ └── mixins/ │ │ ├── EMFModelPartMixin.java │ │ └── EMFModelPartWithStateMixin.java │ ├── entities/ │ │ ├── AcceleratedEntityRenderingFeature.java │ │ ├── AcceleratedEntityShadowRenderer.java │ │ └── mixins/ │ │ ├── EntityRenderDispatcherMixin.java │ │ └── InventoryScreenMixin.java │ ├── filter/ │ │ ├── FilterFeature.java │ │ ├── FilterType.java │ │ └── mixins/ │ │ ├── AbstractContainerScreenMixin.java │ │ ├── BlockEntityRenderDispatcherMixin.java │ │ ├── ClientHooksMixin.java │ │ ├── ItemRendererMixin.java │ │ └── LevelRendererMixin.java │ ├── ftb/ │ │ └── mixins/ │ │ └── BaseScreenMixin.java │ ├── geckolib/ │ │ └── mixins/ │ │ ├── GeoBoneMixin.java │ │ └── GeoRendererMixin.java │ ├── items/ │ │ ├── AcceleratedItemRenderingFeature.java │ │ ├── AcceleratedQuadsRenderer.java │ │ ├── BakedModelExtension.java │ │ ├── IAcceleratedBakedModel.java │ │ ├── IAcceleratedBakedQuad.java │ │ ├── colors/ │ │ │ ├── BlockLayerColors.java │ │ │ ├── EmptyBlockColor.java │ │ │ ├── EmptyItemColor.java │ │ │ ├── FixedColors.java │ │ │ ├── ILayerColors.java │ │ │ └── ItemLayerColors.java │ │ ├── contexts/ │ │ │ ├── AcceleratedModelRenderContext.java │ │ │ ├── AcceleratedQuadsRenderContext.java │ │ │ └── DecorationRenderContext.java │ │ ├── gui/ │ │ │ ├── GuiBatchingController.java │ │ │ ├── GuiRenderTypes.java │ │ │ ├── contexts/ │ │ │ │ ├── BlitDrawContext.java │ │ │ │ ├── DecoratorDrawContext.java │ │ │ │ ├── FillDrawContext.java │ │ │ │ ├── GradientDrawContext.java │ │ │ │ ├── HighlightDrawContext.java │ │ │ │ ├── IGuiElementContext.java │ │ │ │ ├── ItemRenderContext.java │ │ │ │ └── string/ │ │ │ │ ├── ComponentStringDrawContext.java │ │ │ │ ├── FormattedStringDrawContext.java │ │ │ │ ├── IStringDrawContext.java │ │ │ │ ├── Outline8StringDrawContext.java │ │ │ │ └── RawStringDrawContext.java │ │ │ └── renderer/ │ │ │ ├── AcceleratedBlitRenderer.java │ │ │ ├── AcceleratedFillRenderer.java │ │ │ └── AcceleratedGradientRenderer.java │ │ └── mixins/ │ │ ├── ItemRendererMixin.java │ │ ├── ModelBlockRendererMixin.java │ │ ├── accessors/ │ │ │ ├── BlockColorsAccessor.java │ │ │ └── ItemColorsAccessor.java │ │ ├── compatibility/ │ │ │ ├── ClientHooksMixin.java │ │ │ └── GuiLayerManagerMixin.java │ │ ├── gui/ │ │ │ ├── AbstractContainerScreenMixin.java │ │ │ ├── FontMixin.java │ │ │ ├── GuiGraphicsMixin.java │ │ │ └── GuiMixin.java │ │ └── models/ │ │ ├── BakedCompositeModelMixin.java │ │ ├── BakedModelMixin.java │ │ ├── BakedQuadMixin.java │ │ ├── BakedSeparateTransformsModelMixin.java │ │ ├── MultipartBakedModelMixin.java │ │ ├── SimpleBakedModelMixin.java │ │ └── WeightedBakedModelMixin.java │ ├── modelparts/ │ │ └── mixins/ │ │ └── ModelPartMixin.java │ ├── simplebedrockmodel/ │ │ └── mixins/ │ │ └── BedrockPartMixin.java │ ├── text/ │ │ ├── AcceleratedBakedGlyphRenderer.java │ │ ├── AcceleratedTextRenderingFeature.java │ │ └── mixins/ │ │ ├── BakedGlyphEffectMixin.java │ │ └── BakedGlyphMixin.java │ └── touhoulittlemaid/ │ └── mixins/ │ ├── GeoBoneMixin.java │ └── IGeoRendererMixin.java └── resources/ ├── META-INF/ │ ├── accesstransformer.cfg │ └── neoforge.mods.toml ├── acceleratedrendering.compat.curios.mixins.json ├── acceleratedrendering.compat.immediatelyfast.mixins.json ├── acceleratedrendering.compat.iris.mixins.json ├── acceleratedrendering.core.mixins.json ├── acceleratedrendering.feature.entities.mixins.json ├── acceleratedrendering.feature.entitymodelfeature.mixins.json ├── acceleratedrendering.feature.filter.mixins.json ├── acceleratedrendering.feature.ftb.mixins.json ├── acceleratedrendering.feature.geckolib.mixins.json ├── acceleratedrendering.feature.items.mixins.json ├── acceleratedrendering.feature.modelparts.mixins.json ├── acceleratedrendering.feature.simplebedrockmodel.mixins.json ├── acceleratedrendering.feature.text.mixins.json ├── acceleratedrendering.feature.touhoulittlemaid.mixins.json └── assets/ └── acceleratedrendering/ ├── lang/ │ ├── en_us.json │ └── zh_cn.json └── shaders/ ├── compat/ │ ├── culling/ │ │ ├── iris_block_quad_culling_shader.compute │ │ ├── iris_block_triangle_culling_shader.compute │ │ ├── iris_entity_quad_culling_shader.compute │ │ └── iris_entity_triangle_culling_shader.compute │ ├── processing/ │ │ ├── iris_block_quad_processing_shader.compute │ │ ├── iris_block_triangle_processing_shader.compute │ │ ├── iris_entity_quad_processing_shader.compute │ │ ├── iris_entity_triangle_processing_shader.compute │ │ ├── iris_glyph_quad_processing_shader.compute │ │ └── iris_glyph_triangle_processing_shader.compute │ ├── transform/ │ │ ├── iris_block_vertex_transform_shader.compute │ │ ├── iris_entity_vertex_transform_shader.compute │ │ └── iris_glyph_vertex_transform_shader.compute │ └── uploading/ │ ├── iris_block_mesh_uploading_shader.compute │ ├── iris_entity_mesh_uploading_shader.compute │ └── iris_glyph_mesh_uploading_shader.compute └── core/ ├── culling/ │ ├── block_quad_culling_shader.compute │ ├── block_triangle_culling_shader.compute │ ├── entity_quad_culling_shader.compute │ ├── entity_triangle_culling_shader.compute │ ├── pass_through_quad_culling_shader.compute │ ├── pass_through_triangle_culling_shader.compute │ ├── pos_tex_color_quad_culling_shader.compute │ ├── pos_tex_color_triangle_culling_shader.compute │ ├── pos_tex_quad_culling_shader.compute │ └── pos_tex_triangle_culling_shader.compute ├── transform/ │ ├── block_vertex_transform_shader.compute │ ├── entity_vertex_transform_shader.compute │ ├── pos_color_tex_light_vertex_transform_shader.compute │ ├── pos_color_vertex_transform_shader.compute │ ├── pos_tex_color_vertex_transform_shader.compute │ ├── pos_tex_vertex_transform_shader.compute │ └── pos_vertex_transform_shader.compute └── uploading/ ├── block_mesh_uploading_shader.compute ├── entity_mesh_uploading_shader.compute ├── pos_color_mesh_uploading_shader.compute ├── pos_color_tex_light_mesh_uploading_shader.compute ├── pos_mesh_uploading_shader.compute ├── pos_tex_color_mesh_uploading_shader.compute └── pos_tex_mesh_uploading_shader.compute ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ # Disable autocrlf on generated files, they always generate with LF # Add any extra files or paths here to make git stop saying they # are changed when only line endings change. src/generated/**/.cache/cache text eol=lf src/generated/**/*.json text eol=lf ================================================ FILE: .github/workflows/build.yml ================================================ name: Build on: [push, pull_request, workflow_dispatch] jobs: build: runs-on: ubuntu-22.04 steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Java 21 uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: 21 - name: Get Short Identifier uses: benjlevesque/short-sha@v2.2 id: short-sha - name: Build id: build run: | chmod +x ./gradlew ./gradlew build VERSION_IDENTIFIER=SNAPSHOT+${{ steps.short-sha.outputs.sha }} FILE_NAME="$(ls ./build/libs -1 | head -n 1)" NEW_NAME="${FILE_NAME%.jar}-${VERSION_IDENTIFIER}.jar" mv "./build/libs/$FILE_NAME" "./build/libs/$NEW_NAME" echo "artifact_name=$NEW_NAME" >> "$GITHUB_OUTPUT" echo "artifact_path=./build/libs/$NEW_NAME" >> "$GITHUB_OUTPUT" - name: GitHub Action Artifact uses: actions/upload-artifact@v4 with: name: ${{ steps.build.outputs.artifact_name }} path: ${{ steps.build.outputs.artifact_path }} ================================================ FILE: .gitignore ================================================ # eclipse bin *.launch .settings .metadata .classpath .project # idea out *.ipr *.iws *.iml .idea # gradle build .gradle # other eclipse run runs run-data repo ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2023 Argon4W Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # 加速渲染 ([EN version](#english)) 加速渲染是一个客户端实体渲染优化MOD. 目的是改善在渲染大量实体或拥有大量顶点的复杂MOD实体的情况下产生的渲染性能问题, 与此同时尽可能与光影MOD和其他MOD及其自定义实体兼容. ![Benchmark](images/benchmark.jpg) ## 🍝赞助 加速渲染基本由我一人完成, 花费了数千小时对其进行开发和测试, 才得以发布. 来自广大玩家们的赞助将用于加速渲染后续的更快的开发, 创新和优化, 感谢所有支持者! 如果你喜欢这个MOD, 并且想要支持加速渲染的开发, 请前往[爱发电](https://afdian.com/a/argon4w)为狐狸买一份意面 ## ✨为什么需要这个MOD Minecraft拥有一个羸弱的, 继承使用OpenGL立即模式的老版本的渲染系统以用来渲染实体和方块实体. 这个渲染系统会在**CPU**上**单线程**每帧变换和上传实体渲染所需要的顶点. 这就导致有巨量的时间被浪费在这些单线程执行的操作上, 导致了在渲染大量顶点时CPU其他核心和GPU空闲, 而FPS却十分低的奇异景象. ## ⚙️工作原理 加速渲染构建了一个独特的渲染管线, 将变换前的顶点缓存至模型中, 并在需要渲染时将其提交到GPU使用计算着色器进行多线程并行变换. 之后使用原本渲染系统中所使用的着色器进行渲染绘制. 通过这个渲染管线, 加速渲染可以在将实体渲染效率大幅提升, 将CPU压力转移的同时维持对光影MOD的兼容性 (当前兼容Iris Shaders). 并且所有渲染特性都可以被关闭以保证兼容性. ## 🖥️硬件要求 加速渲染因为使用了持久映射缓冲区(Persistently Mapped Buffer)和计算着色器, 因此需要OpenGL 4.6才能正常工作. 理论上NVIDIA GT 400 Series, Intel HD Graphics 520/530及以上的显卡可以满足这个要求. 加速渲染已经在发布前在NVIDIA GTX 1660Ti Max-Q, NVIDIA RTX 3070Ti Laptop, NVIDIA RTX 4090 Laptop, RX 580, RX 5600XT上经过测试. 移动设备目前**不受支持**. ## 🛠️配置 配置文件可以在``/.minecraft/config/acceleratedrendering-client.toml``找到. 你可以通过配置文件修改加速特性或在游戏内进行修改. 部分特性可能需要重启游戏才能生效. 你可以在``模组 > Accelerated Rendering > 配置``找到游戏内配置编辑器. 如要让加速物品渲染正常工作, 请在"核心配置" (Core Settings) 处开启"强制加速半透明" (Force Translucent Acceleration). # AcceleratedRendering This is a client side only entity rendering optimization MOD, aiming at improving performance when rendering large amount of entities or complex modded entities with significant amount of vertices with compute shaders on GPU while being compatible with shader packs, other MODs and their entities. ![Benchmark](images/benchmark.jpg) ## 🍝Sponsorship This MOD is almost fully done by myself and took thousands of hours of my own time working and testing on it to be released. Sponsorships from players can ensure the future development, innovation and optimization of this MOD. Thanks for everyone that 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) ## ✨Why you need this MOD Minecraft has a poor immediate rendering system for rendering entities (including block entities) that is inherited from OpenGL immediate rendering mode that older versions of Minecraft uses. It transforms and uploads vertices on a **single render thread** on **CPU** every 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 when rendering large amount of vertices. ## ⚙️How it works AcceleratedRendering constructs a unique rendering pipeline that caches the "original" vertices (vertices before the transform) into meshes and transforms them to be parallel in GPU using compute shaders. Then it draws the transformed vertices with the original shader. In this way, this MOD can make entity rendering much more efficient by shifting the transforming stress off from the CPU while still being compatible with shader packs (currently support Iris Shaders). All acceleration features can be disabled for better compatibility. ## 🖥️Hardware Requirements AcceleratedRendering requires OpenGL 4.6 to work properly for the usage of persistently mapped buffers and compute shaders. Graphics cards like NVIDIA GT 400 Series and Intel HD Graphics 520/530 or newer will fit this requirement. This MOD has been tested on NVIDIA GTX 1660Ti Max-Q, NVIDIA RTX 3070Ti Laptop, NVIDIA RTX 4090 Laptop, RX 580, RX 5600XT. Mobile devices currently are **not supported**. ## 🛠️Configuration Configuration file can be found in ``/.minecraft/config/acceleratedrendering-client.toml``. You can modify acceleration features in this file or in game (some specific configurations require a game restart to take effect). In-game configuration editor can be found in ``Mods > Accelerated Rendering > Config``. "Force Translucent Acceleration" in "Core Settings" is required to be enabled for accelerated item rendering to work properly. ================================================ FILE: build.gradle ================================================ plugins { id 'java-library' id 'eclipse' id 'idea' id 'maven-publish' id 'net.neoforged.gradle.userdev' version '7.0.189' } tasks.named('wrapper', Wrapper).configure { // Define wrapper values here so as to not have to always do so when updating gradlew.properties. // Switching this to Wrapper.DistributionType.ALL will download the full gradle sources that comes with // documentation attached on cursor hover of gradle classes and methods. However, this comes with increased // file size for Gradle. If you do switch this to ALL, run the Gradle wrapper task twice afterwards. // (Verify by checking gradle/wrapper/gradle-wrapper.properties to see if distributionUrl now points to `-all`) distributionType = Wrapper.DistributionType.BIN } version = mod_version group = mod_group_id repositories { mavenLocal() exclusiveContent { forRepository { maven { name = "Modrinth" url = "https://api.modrinth.com/maven" } } filter { includeGroup "maven.modrinth" } } maven { url 'https://jitpack.io' content { includeGroup "com.github.TartaricAcid" } } maven { url "https://cursemaven.com" content { includeGroup "curse.maven" } } } base { archivesName = mod_id } // Mojang ships Java 21 to end users starting in 1.20.5, so mods should target Java 21. java.toolchain.languageVersion = JavaLanguageVersion.of(21) minecraft.accessTransformers.file rootProject.file('src/main/resources/META-INF/accesstransformer.cfg') //minecraft.accessTransformers.entry public net.minecraft.client.Minecraft textureManager # textureManager // Default run configurations. // These can be tweaked, removed, or duplicated as needed. runs { // applies to all the run configs below configureEach { // Recommended logging data for a userdev environment // The markers can be added/remove as needed separated by commas. // "SCAN": For mods scan. // "REGISTRIES": For firing of registry events. // "REGISTRYDUMP": For getting the contents of all registries. systemProperty 'forge.logging.markers', 'REGISTRIES' // Recommended logging level for the console // You can set various levels here. // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels systemProperty 'forge.logging.console.level', 'debug' modSource project.sourceSets.main } client { // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. systemProperty 'forge.enabledGameTestNamespaces', project.mod_id } server { systemProperty 'forge.enabledGameTestNamespaces', project.mod_id programArgument '--nogui' } // This run config launches GameTestServer and runs all registered gametests, then exits. // By default, the server will crash when no gametests are provided. // The gametest system is also enabled by default for other run configs under the /test command. gameTestServer { systemProperty 'forge.enabledGameTestNamespaces', project.mod_id } data { // example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it // workingDirectory project.file('run-data') // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath() } } // Include resources generated by data generators. sourceSets.main.resources { srcDir 'src/generated/resources' } // Sets up a dependency configuration called 'localRuntime'. // This configuration should be used instead of 'runtimeOnly' to declare // a dependency that will be present for runtime testing but that is // "optional", meaning it will not be pulled by dependents of this mod. configurations { runtimeClasspath.extendsFrom localRuntime } dependencies { // Specify the version of Minecraft to use. // Depending on the plugin applied there are several options. We will assume you applied the userdev plugin as shown above. // The group for userdev is net.neoforged, the module name is neoforge, and the version is the same as the neoforge version. // You can however also use the vanilla plugin (net.neoforged.gradle.vanilla) to use a version of Minecraft without the neoforge loader. // 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. // For all intends and purposes: You can treat this dependency as if it is a normal library you would use. implementation "net.neoforged:neoforge:${neo_version}" // Example optional mod dependency with JEI // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime // compileOnly "mezz.jei:jei-${mc_version}-common-api:${jei_version}" // compileOnly "mezz.jei:jei-${mc_version}-neoforge-api:${jei_version}" // We add the full version to localRuntime, not runtimeOnly, so that we do not publish a dependency on it // localRuntime "mezz.jei:jei-${mc_version}-neoforge:${jei_version}" // Example mod dependency using a mod jar from ./libs with a flat dir repository // This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar // The group id is ignored when searching -- in this case, it is "blank" // implementation "blank:coolmod-${mc_version}:${coolmod_version}" // Example mod dependency using a file as dependency // implementation files("libs/coolmod-${mc_version}-${coolmod_version}.jar") // Example project dependency using a sister or child project: // implementation project(":myproject") // For more info: // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html // http://www.gradle.org/docs/current/userguide/dependency_management.html54 implementation "maven.modrinth:sodium:mc1.21.1-0.6.13-neoforge" implementation "maven.modrinth:iris:1.8.8+1.21.1-neoforge" implementation "maven.modrinth:jei:YAcQ6elZ" implementation "maven.modrinth:modern-ui:3.12.0.2" implementation "curse.maven:architectury-api-419699:5786327" implementation "curse.maven:ftb-teams-forge-404468:7369021" implementation "curse.maven:ftb-quests-forge-289412:7429016" implementation "curse.maven:certain-questing-additions-1372051:7450467" implementation "maven.modrinth:kotlin-for-forge:5.11.0" implementation "maven.modrinth:elytra-trims:3.9.3" implementation "maven.modrinth:entitytexturefeatures:7.0.13-neoforge-1.21" implementation "maven.modrinth:entity-model-features:3.0.17-neoforge-1.21" implementation "maven.modrinth:touhou-little-maid:1.5.0-neoforge+mc1.21.1" compileOnly "maven.modrinth:geckolib:QEqpUJ1G" implementation "maven.modrinth:immediatelyfast:1.6.8+1.21.1-neoforge" compileOnly "maven.modrinth:curios:9.5.1+1.21.1" implementation "curse.maven:ftb-library-forge-404465:7420412" compileOnly "org.projectlombok:lombok:1.18.38" annotationProcessor "org.projectlombok:lombok:1.18.38" } // This block of code expands all declared replace properties in the specified resource targets. // A missing property will result in an error. Properties are expanded using ${} Groovy notation. // When "copyIdeResources" is enabled, this will also run before the game launches in IDE environments. // See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html tasks.withType(ProcessResources).configureEach { var replaceProperties = [ minecraft_version : minecraft_version, minecraft_version_range: minecraft_version_range, neo_version : neo_version, neo_version_range : neo_version_range, loader_version_range : loader_version_range, mod_id : mod_id, mod_name : mod_name, mod_license : mod_license, mod_version : mod_version, mod_authors : mod_authors, mod_description : mod_description ] inputs.properties replaceProperties filesMatching(['META-INF/neoforge.mods.toml']) { expand replaceProperties } } // Example configuration to allow publishing using the maven-publish plugin publishing { publications { register('mavenJava', MavenPublication) { from components.java } } repositories { maven { url "file://${project.projectDir}/repo" } } } tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation } // IDEA no longer automatically downloads sources/javadoc jars for dependencies, so we need to explicitly enable the behavior. idea { module { downloadSources = true downloadJavadoc = true } } ================================================ FILE: changelogs/changelog-1.0.0.md ================================================ ## 加速渲染 1.0.0-1.21.1 ALPHA - 支持加速原版/类原版MOD生物渲染. - 支持加速原版/类原版MOD方块实体渲染. - 支持加速物品模型渲染 **(需要开启``核心配置 > 强制加速半透明``)**. - 支持加速最新版车万女仆渲染. - 支持加速GeckoLib模型生物/方块实体渲染. ## Accelerated Rendering 1.0.0-1.21.1 ALPHA - Supports acceleration for rendering vanilla entities/vanilla-like modded entities. - Supports acceleration for rendering vanilla block entities/vanilla-like modded block entities. - Supports acceleration for rendering item models **(``Core Settings > Force Translucent Acceleration`` is required to be enabled)**. - Supports acceleration for rendering maids in latest version of Touhou Little Maid. - Supports acceleration for rendering GeckoLib entities/block entities. ================================================ FILE: changelogs/changelog-1.0.1.md ================================================ ## 加速渲染 1.0.1-1.21.1 ALPHA - 添加了``核心配置 > 用立即上传模型``选项以保证绘制顺序, 提供更好的兼容性. - 添加了``Curios兼容性配置``以控制Curios饰品/装备的渲染加速. - 添加了``过滤器设置``以阻止部分在渲染加速后会导致需渲染异常的生物/方块实体被加速, 提供更好的兼容性. - 修复了在与Iris环境下将``视频设置... > 图像品质``设置为 ``极佳!``导致的渲染异常. ## Accelerated Rendering 1.0.1-1.21.1 ALPHA - Adds ``Core Settings > Enable Uploading Mesh Immediately`` to ensure the draw order for better compatibility. - Adds ``Curios Compatibility Settings`` to control the acceleration of curios accessories/equipments. - Adds ``Filter Settings`` to filter entities/block entities that will cause glitches when accelerated. - Fixes rendering glitches when set ``Video Settings... > Graphics`` to ``Fabulous!`` with Iris installed. ================================================ FILE: changelogs/changelog-1.0.2.md ================================================ ## 加速渲染 1.0.2-1.21.1 ALPHA - 添加了新的Shader Overrides API功能, 以实现更好MOD兼容性. - 添加了新的Batching Layer API功能, 以实现更好的MOD兼容性. - 添加了``ModelBlockRenderer#renderModel``的渲染加速以支持展示实体渲染加速. - 添加了``加速物品渲染配置 > 启用手中物品加速``选项以支持加速在手中物品的渲染加速. - 添加了``加速物品渲染配置 > 启用GUI物品加速``选项以支持加速在GUI中物品的渲染加速. - 添加了``加速物品渲染配置 > 启用GUI物品合批``选项以支持合并GUI中物品的绘制, 更好的支持在GUI中物品的渲染加速. - 添加了``核心配置 > 合批层储存类型``选项以控制是否将半透明和不透明模型合并渲染 - 添加了``过滤器设置 > 启用物品过滤器``选项以阻止部分在渲染加速后会导致需渲染异常的物品被加速, 提供更好的兼容性. - 修复了在Iris环境下开启部分光影包时半透明模型与不透明模型合并渲染导致的半透明模型渲染异常 - 修复了在ImmediatelyFast环境下渲染HUD时导致的渲染异常. - 修复了在机械动力环境下实体与机械动力方块/结构一同出现时导致的渲染异常. ## Accelerated Rendering 1.0.2-1.21.1 ALPHA - Adds Shader Overrides API to achieve better MODs compatibility. - Adds Batching Layer API to achieve better MODs compatibility. - Adds ``ModelBlockRenderer#renderModel`` acceleration support to accelerate rendering of display entities. - Adds ``Accelerated Item Rendering Settings > Enable Hand Acceleration`` to support the acceleration of items rendering in hands. - Adds ``Accelerated Item Rendering Settings > Enable GUI Acceleration`` to support the acceleration of items rendering in GUI. - 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. - Adds ``Core Settings > Batching Layer Storage Type`` to control if the pipeline should combine the rendering of opaque and translucent geometries together. - Adds ``Filter Settings > Enable Item Filter`` to filter items that will cause glitches when accelerated. - Fixes visual glitches on translucent geometries with specific shader pack due to combined rendering of opaque and translucent geometries when Iris is installed. - Fixes visual glitches on HUD rendering when ImmediatelyFast is installed. - Fixes visual glitches when entities and flywheel accelerated geometries rendering on screen at the same time when Create is installed. ================================================ FILE: changelogs/changelog-1.0.3.md ================================================ ## 加速渲染 1.0.3-1.21.1 ALPHA - 修复了物品装饰 (如通用机械的等级标识) 加速没有正确还原帧缓冲状态导致的渲染异常. - 修复了四顶点同UV的面在静态剔除中被错误剔除导致的渲染异常. ## Accelerated Rendering 1.0.3-1.21.1 ALPHA - Fixes visual glitches caused by item decoration (like tier in Mekanism) acceleration not restoring FBO state correctly. - Fixes visual glitches caused by static culler exceptionally culled quads with same UV on both four vertices. ================================================ FILE: changelogs/changelog-1.0.4.md ================================================ ## 加速渲染 1.0.4-1.21.1 ALPHA - 修复了与使用块缓冲的MOD和光影的兼容性. - 移植到1.20.1 Forge. ## 注意事项 - 1.20.1移植需要使用**Java 21**进行启动. - 1.20.1移植的游戏内配置节目需要安装Configured以启用. - 1.20.1移植的GeckoLib加速需要安装MixinBooster以启用. - 1.20.1移植的车万女仆加速需要安装MixinBooster以启用. ## Accelerated Rendering 1.0.4-1.21.1 ALPHA - Fixes compatibility with mods and shaders that uses block buffers. - Ports to 1.20.1 Forge. ## Important Notes - 1.20.1 port requires **Java 21** to boot. - 1.20.1 port requires Configured to modify configurations in game. - 1.20.1 port of GeckoLib acceleration requires MixinBooster to enable. - 1.20.1 port of TouhouLittleMaid acceleration requires MixinBooster to enable. ================================================ FILE: changelogs/changelog-1.0.5.1.md ================================================ ## 加速渲染 1.0.5.1-1.21.1 ALPHA - 修复了在模型面没有自定义颜色的情况下获取颜色导致崩溃. ## Accelerated Rendering 1.0.5.1-1.21.1 ALPHA - Fixes crashes by requesting colors from BakedQuad when the quad is not tinted. ================================================ FILE: changelogs/changelog-1.0.5.md ================================================ ## 加速渲染 1.0.5-1.21.1 ALPHA - 修复了方块模型加速时从错误的位置获取RenderType导致崩溃. ## Accelerated Rendering 1.0.5-1.21.1 ALPHA - Fixes crashes by requesting RenderType from wrong place when accelerating block models. ================================================ FILE: changelogs/changelog-1.0.6.md ================================================ ## 加速渲染 1.0.6-1.21.1 ALPHA - 添加了``核心配置 > 启用缓存动态RenderType``选项以支持对动态渲染类型的加速. - 添加了``核心配置 > 模型合并类型``选项以支持对完全一致模型的合并以改善显存占用. - 改善了过滤器的灵活性, 现在可以在过滤器列表中使用正则表达式. - 修复了GUI物品合批时没有正确还原帧缓冲状态导致的渲染异常. - 修复了自定义渲染阶段被错误加速导致的渲染异常. - 修复了物品附魔光效无法正确渲染导致的渲染异常. - 修复了可能的部分特殊物品渲染导致的内存泄漏问题. ## Accelerated Rendering 1.0.6-1.21.1 ALPHA - Adds ``Core Settings > Enable Cache Dynamic Render Type`` to support the acceleration of dynamic render types. - Adds ``Core Settings > Mesh Merge Type`` to support reducing VRAM usage by merging duplicated meshes together. - Improves filter flexibility. Regular Expression can now be used in filter values. - Fixes visual glitches on container GUI rendering due to not correctly restoring framebuffer state. - Fixes visual glitches on geometries rendered in custom rendering stages due to incorrect acceleration. - Fixes visual glitches on item glints. - Fixes memory leaks due to acceleration on certain special items. ================================================ FILE: changelogs/changelog-1.0.7.md ================================================ ## 加速渲染 1.0.7-1.21.1 ALPHA - 添加了``过滤器配置 > 启用容器GUI过滤器``选项以阻止部分在渲染加速后会导致需渲染异常的容器GUI被加速, 提供更好的兼容性. - 修复了玩家在物品栏GUI中以错误光照渲染导致的渲染异常. - 修复了超出标准范围UV的面在静态剔除中被错误剔除导致的渲染异常. ## Accelerated Rendering 1.0.7-1.21.1 ALPHA - Adds ``Filter Settings > Enable Menu Filter`` to filter menus that will cause glitches when accelerated. - Fixes visual glitches on players rendered with wrong light direction in inventory GUI. - Fixes visual glitches on static culler exceptionally culled geometries with UV outside regular range. ================================================ FILE: changelogs/changelog-1.0.8.md ================================================ ## 加速渲染 1.0.8-1.21.1 ALPHA - 添加了``核心配置 > 裁切区域还原类型``选项以提供对修改了容器GUI渲染的MOD更好的兼容性. - 添加了``加速物品渲染配置 > 启用合并GUI物品批次``选项以以提供对修改了容器GUI渲染的MOD更好的兼容性. - 添加了对FTB Library的GUI物品合批加速支持. - 修复了在``earlyWindowControl``不可用的情况下的导致的崩溃. - 修复了因为Minecraft因为其他错误没有正确启动导致的无关加速渲染的崩溃. - 修复了带状态的EMF模型在运行中修改状态导致的渲染异常. - 修复了OpenGL内存屏障被错误使用导致的潜在渲染异常. - 阻止MOD添加的自定义HUD进行加速, 防止过度调用着色器导致性能下降. ## Accelerated Rendering 1.0.8-1.21.1 ALPHA - Adds ``Core Settings > Scissor Restoring Type`` to provide better compatibility with modified container GUI. - Adds ``Accelerated Item Rendering Settings > Enable Merge GUI Item Batches`` to provide better compatibility with modified container GUI. - Adds GUI item batching acceleration support to FTB Library. - Fixes crashes when ``earlyWindowControl`` is not available. - Fixes irrelevant crashes when Minecraft is crashed by other MODs when starting up. - Fixes visual glitches when EMF models with states modifying its state at runtime. - Fixes potential visual glitches due to incorrect OpenGL memory barrier usages. - Prevent custom HUDs by MODs from being accelerated to reduce shader overhead. ================================================ FILE: gradle/wrapper/gradle-wrapper.properties ================================================ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists ================================================ FILE: gradle.properties ================================================ # Sets default memory used for gradle commands. Can be overridden by user or command line properties. org.gradle.jvmargs=-Xmx1G org.gradle.daemon=false org.gradle.debug=false #read more on this at https://github.com/neoforged/NeoGradle/blob/NG_7.0/README.md#apply-parchment-mappings # you can also find the latest versions at: https://parchmentmc.org/docs/getting-started neogradle.subsystems.parchment.minecraftVersion=1.21.1 neogradle.subsystems.parchment.mappingsVersion=2024.11.17 # Environment Properties # You can find the latest versions here: https://projects.neoforged.net/neoforged/neoforge # The Minecraft version must agree with the Neo version to get a valid artifact minecraft_version=1.21.1 # The Minecraft version range can use any release version of Minecraft as bounds. # Snapshots, pre-releases, and release candidates are not guaranteed to sort properly # as they do not follow standard versioning conventions. minecraft_version_range=[1.21,1.21.2) # The Neo version must agree with the Minecraft version to get a valid artifact neo_version=21.1.192 # The Neo version range can use any version of Neo as bounds neo_version_range=[21.0.0,) # The loader version range can only use the major version of FML as bounds loader_version_range=[4,) ## Mod Properties # The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63} # Must match the String constant located in the main mod class annotated with @Mod. mod_id=acceleratedrendering # The human-readable display name for the mod. mod_name=Accelerated Rendering # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. mod_license=MIT # The mod version. See https://semver.org/ mod_version=1.0.8-1.21.1-alpha # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # This should match the base package used for the mod sources. # See https://maven.apache.org/guides/mini/guide-naming-conventions.html mod_group_id=com.github.argon4w # The authors of the mod. This is a simple text string that is used for display purposes in the mod list. mod_authors=Argon4W # The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list. mod_description=Fast vertex transform and caching using compute shader. ================================================ FILE: gradlew ================================================ #!/bin/sh # # Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # SPDX-License-Identifier: Apache-2.0 # ############################################################################## # # Gradle start up script for POSIX generated by Gradle. # # Important for running: # # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is # noncompliant, but you have some other compliant shell such as ksh or # bash, then to run this script, type that shell name before the whole # command line, like: # # ksh Gradle # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», # «${var#prefix}», «${var%suffix}», and «$( cmd )»; # * compound commands having a testable exit status, especially «case»; # * various built-in commands including «command», «set», and «ulimit». # # Important for patching: # # (2) This script targets any POSIX shell, so it avoids extensions provided # by Bash, Ksh, etc; in particular arrays are avoided. # # The "traditional" practice of packing multiple parameters into a # space-separated string is a well documented source of bugs and security # problems, so this is (mostly) avoided, by progressively accumulating # options in "$@", and eventually passing that to Java. # # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; # see the in-line comments for details. # # There are tweaks for specific operating systems such as AIX, CygWin, # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. # ############################################################################## # Attempt to set APP_HOME # Resolve links: $0 may be a link app_path=$0 # Need this for daisy-chained symlinks. while APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path [ -h "$app_path" ] do ls=$( ls -ld "$app_path" ) link=${ls#*' -> '} case $link in #( /*) app_path=$link ;; #( *) app_path=$APP_HOME$link ;; esac done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s ' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum warn () { echo "$*" } >&2 die () { echo echo "$*" echo exit 1 } >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false case "$( uname )" in #( CYGWIN* ) cygwin=true ;; #( Darwin* ) darwin=true ;; #( MSYS* | MINGW* ) msys=true ;; #( NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD=$JAVA_HOME/jre/sh/java else JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD=java if ! command -v java >/dev/null 2>&1 then die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac fi # Collect all arguments for the java command, stacking in reverse order: # * args from the command line # * the main class name # * -classpath # * -D...appname settings # * --module-path (only if needed) # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) # Now convert the arguments - kludge to limit ourselves to /bin/sh for arg do if case $arg in #( -*) false ;; # don't mess with options #( /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath [ -e "$t" ] ;; #( *) false ;; esac then arg=$( cygpath --path --ignore --mixed "$arg" ) fi # Roll the args list around exactly as many times as the number of # args, so each arg winds up back in the position where it started, but # possibly modified. # # NB: a `for` loop captures its iteration list before it begins, so # changing the positional parameters here affects neither the number of # iterations, nor the values presented in `arg`. shift # remove old arg set -- "$@" "$arg" # push replacement arg done fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ org.gradle.wrapper.GradleWrapperMain \ "$@" # Stop when "xargs" is not available. if ! command -v xargs >/dev/null 2>&1 then die "xargs is not available" fi # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. # # In Bash we could simply go: # # readarray ARGS < <( xargs -n1 <<<"$var" ) && # set -- "${ARGS[@]}" "$@" # # but POSIX shell has neither arrays nor command substitution, so instead we # post-process each arg (as a line of input to sed) to backslash-escape any # character that might be a shell metacharacter, then use eval to reverse # that process (while maintaining the separation between arguments), and wrap # the whole thing up as a single "set" statement. # # This will of course break if any of these variables contains a newline or # an unmatched quote. # eval "set -- $( printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | xargs -n1 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | tr '\n' ' ' )" '"$@"' exec "$JAVACMD" "$@" ================================================ FILE: gradlew.bat ================================================ @rem @rem Copyright 2015 the original author or authors. @rem @rem Licensed under the Apache License, Version 2.0 (the "License"); @rem you may not use this file except in compliance with the License. @rem You may obtain a copy of the License at @rem @rem https://www.apache.org/licenses/LICENSE-2.0 @rem @rem Unless required by applicable law or agreed to in writing, software @rem distributed under the License is distributed on an "AS IS" BASIS, @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem @rem SPDX-License-Identifier: Apache-2.0 @rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. @rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Resolve any "." and ".." in APP_HOME to make it shorter. for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute echo. 1>&2 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute echo. 1>&2 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 goto fail :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! set EXIT_CODE=%ERRORLEVEL% if %EXIT_CODE% equ 0 set EXIT_CODE=1 if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: settings.gradle ================================================ pluginManagement { repositories { gradlePluginPortal() maven { url = 'https://maven.neoforged.net/releases' } } } plugins { id 'org.gradle.toolchains.foojay-resolver-convention' version '0.9.0' } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/AcceleratedRenderingModEntry.java ================================================ package com.github.argon4w.acceleratedrendering; import com.github.argon4w.acceleratedrendering.configs.FeatureConfig; import com.mojang.logging.LogUtils; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.ModContainer; import net.neoforged.fml.common.Mod; import net.neoforged.fml.config.ModConfig; import net.neoforged.neoforge.client.gui.ConfigurationScreen; import net.neoforged.neoforge.client.gui.IConfigScreenFactory; import org.slf4j.Logger; @Mod( value = AcceleratedRenderingModEntry .MOD_ID, dist = Dist .CLIENT ) public class AcceleratedRenderingModEntry { public static final String MOD_ID = "acceleratedrendering"; public static final Logger LOGGER = LogUtils.getLogger(); public AcceleratedRenderingModEntry(IEventBus modEventBus, ModContainer modContainer) { modContainer.registerConfig (ModConfig.Type.CLIENT, FeatureConfig.SPEC); modContainer.registerExtensionPoint (IConfigScreenFactory.class, ConfigurationScreen::new); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/AbstractCompatMixinPlugin.java ================================================ package com.github.argon4w.acceleratedrendering.compat; import net.neoforged.fml.loading.LoadingModList; import org.objectweb.asm.tree.ClassNode; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; import org.spongepowered.asm.mixin.extensibility.IMixinInfo; import java.util.List; import java.util.Set; public abstract class AbstractCompatMixinPlugin implements IMixinConfigPlugin { private final boolean shouldApply; public AbstractCompatMixinPlugin() { var shouldApply = false; for (var id : getModIDs()) { if (LoadingModList.get().getModFileById(id) != null) { shouldApply = true; } } this.shouldApply = shouldApply; } protected abstract List getModIDs(); @Override public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { return shouldApply; } @Override public String getRefMapperConfig() { return null; } @Override public List getMixins() { return null; } @Override public void onLoad(String mixinPackage) { } @Override public void acceptTargets(Set myTargets, Set otherTargets) { } @Override public void preApply( String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo ) { } @Override public void postApply( String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo ) { } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/curios/CuriosCompatFeature.java ================================================ package com.github.argon4w.acceleratedrendering.compat.curios; import com.github.argon4w.acceleratedrendering.configs.FeatureConfig; import com.github.argon4w.acceleratedrendering.configs.FeatureStatus; import com.github.argon4w.acceleratedrendering.core.utils.RegistryFilter; import com.github.argon4w.acceleratedrendering.features.filter.FilterType; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import java.util.ArrayDeque; import java.util.Deque; import java.util.Set; public class CuriosCompatFeature { public static final Deque LAYER_ACCELERATION_CONTROLLER_STACK = new ArrayDeque<>(); public static final Deque CURIOS_ITEM_FILTER_CONTROLLER_STACK = new ArrayDeque<>(); private static final Set CURIOS_ITEM_FILTER_VALUES; static { CURIOS_ITEM_FILTER_VALUES = RegistryFilter.filterValues(BuiltInRegistries.ITEM, FeatureConfig.CONFIG.curiosItemFilterValues.get()); } public static boolean isEnabled() { return FeatureConfig.CONFIG.curiosCompatFeatureStatus.get() == FeatureStatus.ENABLED; } public static boolean testCuriosItem(ItemStack itemStack) { return getCuriosItemFilterType().test(CURIOS_ITEM_FILTER_VALUES, itemStack.getItem()); } public static boolean shouldAccelerateCurios() { return getLayerAccelerationSetting() == FeatureStatus.ENABLED; } public static boolean shouldFilterCuriosItems() { return getCuriosItemFilterSetting() == FeatureStatus.ENABLED; } public static FilterType getCuriosItemFilterType() { return FeatureConfig.CONFIG.curiosItemFilterType.get(); } public static void disableLayerAcceleration() { LAYER_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.DISABLED); } public static void disableCuriosItemFilter() { CURIOS_ITEM_FILTER_CONTROLLER_STACK.push(FeatureStatus.DISABLED); } public static void forceEnableLayerAcceleration() { LAYER_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.ENABLED); } public static void forceEnableCuriosItemFilter() { CURIOS_ITEM_FILTER_CONTROLLER_STACK.push(FeatureStatus.ENABLED); } public static void forceSetLayerAcceleration(FeatureStatus status) { LAYER_ACCELERATION_CONTROLLER_STACK.push(status); } public static void forceSetCuriosItemFilter(FeatureStatus status) { CURIOS_ITEM_FILTER_CONTROLLER_STACK.push(status); } public static void resetLayerAcceleration() { LAYER_ACCELERATION_CONTROLLER_STACK.pop(); } public static void resetCuriosItemFilter() { CURIOS_ITEM_FILTER_CONTROLLER_STACK.pop(); } public static FeatureStatus getLayerAccelerationSetting() { return LAYER_ACCELERATION_CONTROLLER_STACK.isEmpty() ? getDefaultLayerAccelerationSettings() : LAYER_ACCELERATION_CONTROLLER_STACK.peek(); } public static FeatureStatus getCuriosItemFilterSetting() { return CURIOS_ITEM_FILTER_CONTROLLER_STACK.isEmpty() ? getDefaultCuriosItemFilterSetting() : CURIOS_ITEM_FILTER_CONTROLLER_STACK.peek(); } public static FeatureStatus getDefaultLayerAccelerationSettings() { return FeatureConfig.CONFIG.curiosCompatLayerAcceleration.get(); } public static FeatureStatus getDefaultCuriosItemFilterSetting() { return FeatureConfig.CONFIG.curiosItemFilter.get(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/curios/mixins/CuriosLayerMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.curios.mixins; import com.github.argon4w.acceleratedrendering.compat.curios.CuriosCompatFeature; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.github.argon4w.acceleratedrendering.features.filter.FilterFeature; import com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature; import com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.entity.RenderLayerParent; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import top.theillusivec4.curios.api.SlotContext; import top.theillusivec4.curios.api.client.ICurioRenderer; import top.theillusivec4.curios.client.render.CuriosLayer; @Pseudo @Mixin(CuriosLayer.class) public class CuriosLayerMixin { @Inject( method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/world/entity/LivingEntity;FFFFFF)V", at = @At("HEAD") ) public void startRenderCuriosLayer( PoseStack matrixStack, MultiBufferSource renderTypeBuffer, int light, LivingEntity livingEntity, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch, CallbackInfo ci ) { if ( CuriosCompatFeature.isEnabled () && ! CuriosCompatFeature.shouldAccelerateCurios () ) { AcceleratedEntityRenderingFeature .useVanillaPipeline(); AcceleratedItemRenderingFeature .useVanillaPipeline(); AcceleratedTextRenderingFeature .useVanillaPipeline(); } } @Inject( method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/world/entity/LivingEntity;FFFFFF)V", at = @At("RETURN") ) public void stopRenderCuriosLayer( PoseStack matrixStack, MultiBufferSource renderTypeBuffer, int light, LivingEntity livingEntity, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch, CallbackInfo ci ) { if ( CuriosCompatFeature.isEnabled () && ! CuriosCompatFeature.shouldAccelerateCurios () ) { AcceleratedEntityRenderingFeature .resetPipeline(); AcceleratedItemRenderingFeature .resetPipeline(); AcceleratedTextRenderingFeature .resetPipeline(); } } @WrapOperation( method = "lambda$render$0", at = @At( value = "INVOKE", target = "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" ) ) public void filterCuriosItem( ICurioRenderer instance, ItemStack itemStack, SlotContext slotContext, PoseStack poseStack, RenderLayerParent renderLayerParent, MultiBufferSource bufferSource, int light, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch, Operation original ) { var pass = ! FilterFeature .isEnabled () || ! CuriosCompatFeature .isEnabled () || ! CuriosCompatFeature .shouldFilterCuriosItems() || CuriosCompatFeature .testCuriosItem (itemStack); if (!pass) { AcceleratedEntityRenderingFeature .useVanillaPipeline(); AcceleratedItemRenderingFeature .useVanillaPipeline(); AcceleratedTextRenderingFeature .useVanillaPipeline(); } original.call( instance, itemStack, slotContext, poseStack, renderLayerParent, bufferSource, light, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch ); if (!pass) { AcceleratedEntityRenderingFeature .resetPipeline(); AcceleratedItemRenderingFeature .resetPipeline(); AcceleratedTextRenderingFeature .resetPipeline(); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/immediatelyfast/mixins/BatchableBufferSourceMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.immediatelyfast.mixins; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratableBufferSource; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.llamalad7.mixinextras.injector.ModifyReturnValue; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.RenderType; import net.raphimc.immediatelyfast.feature.core.BatchableBufferSource; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.injection.At; @Pseudo @ExtensionMethod(VertexConsumerExtension.class) @Mixin (BatchableBufferSource .class) public abstract class BatchableBufferSourceMixin implements IAcceleratableBufferSource { @ModifyReturnValue( method = "getBuffer", at = @At("RETURN") ) public VertexConsumer initAcceleration(VertexConsumer original, RenderType renderType) { return original .getHolder () .initAcceleration (renderType, getBoundAcceleratedBufferSource()); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/immediatelyfast/mixins/BatchingBuffersMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.immediatelyfast.mixins; import com.github.argon4w.acceleratedrendering.core.CoreBuffersProvider; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.BufferSourceExtension; import com.llamalad7.mixinextras.injector.ModifyReturnValue; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.MultiBufferSource; import net.raphimc.immediatelyfast.feature.batching.BatchingBuffers; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.injection.At; @Pseudo @ExtensionMethod(BufferSourceExtension .class) @Mixin (BatchingBuffers .class) public class BatchingBuffersMixin { @ModifyReturnValue( method = "getNonBatchingEntityVertexConsumers", at = @At("RETURN") ) private static MultiBufferSource.BufferSource bindAcceleratableBufferSourceCore1(MultiBufferSource.BufferSource original) { original .getAcceleratable () .bindAcceleratedBufferSource(CoreBuffersProvider.CORE); return original; } @ModifyReturnValue( method = "getHudBatchingVertexConsumers", at = @At("RETURN") ) private static MultiBufferSource.BufferSource bindAcceleratableBufferSourceCore2(MultiBufferSource.BufferSource original) { original .getAcceleratable () .bindAcceleratedBufferSource(CoreBuffersProvider.CORE); return original; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/immediatelyfast/mixins/WrappedRenderLayerMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.immediatelyfast.mixins; import lombok.EqualsAndHashCode; import net.minecraft.client.renderer.RenderType; import net.raphimc.immediatelyfast.feature.batching.BatchingBuffers; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Pseudo @EqualsAndHashCode @Mixin(BatchingBuffers.WrappedRenderLayer.class) public class WrappedRenderLayerMixin { @Unique private RenderType original; @Inject( method = "", at = @At("TAIL") ) public void saveOriginal( RenderType renderLayer, Runnable additionalStartAction, Runnable additionalEndAction, CallbackInfo ci ) { this.original = renderLayer; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/IrisCompatBuffers.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris; import com.github.argon4w.acceleratedrendering.core.buffers.AcceleratedBufferSources; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.AcceleratedBufferSource; import com.github.argon4w.acceleratedrendering.core.buffers.environments.IBufferEnvironment; import com.mojang.blaze3d.vertex.VertexFormat; public class IrisCompatBuffers { public static final AcceleratedBufferSource BLOCK_SHADOW = new AcceleratedBufferSource(IBufferEnvironment.Presets.BLOCK); public static final AcceleratedBufferSource ENTITY_SHADOW = new AcceleratedBufferSource(IBufferEnvironment.Presets.ENTITY); public static final AcceleratedBufferSource GLYPH_SHADOW = new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_COLOR_TEX_LIGHT); public static final AcceleratedBufferSource POS_TEX_SHADOW = new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_TEX); public static final AcceleratedBufferSource POS_TEX_COLOR_SHADOW = new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_TEX_COLOR); public static final AcceleratedBufferSource BLOCK_HAND = new AcceleratedBufferSource(IBufferEnvironment.Presets.BLOCK); public static final AcceleratedBufferSource ENTITY_HAND = new AcceleratedBufferSource(IBufferEnvironment.Presets.ENTITY); public static final AcceleratedBufferSource POS_HAND = new AcceleratedBufferSource(IBufferEnvironment.Presets.POS); public static final AcceleratedBufferSource POS_COLOR_HAND = new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_COLOR); public static final AcceleratedBufferSource POS_TEX_HAND = new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_TEX); public static final AcceleratedBufferSource POS_TEX_COLOR_HAND = new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_TEX_COLOR); public static final AcceleratedBufferSource POS_COLOR_TEX_LIGHT_HAND = new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_COLOR_TEX_LIGHT); public static final AcceleratedBufferSources HAND = AcceleratedBufferSources .builder() .source (IrisCompatBuffers .BLOCK_HAND) .source (IrisCompatBuffers .ENTITY_HAND) .source (IrisCompatBuffers .POS_HAND) .source (IrisCompatBuffers .POS_COLOR_HAND) .source (IrisCompatBuffers .POS_TEX_HAND) .source (IrisCompatBuffers .POS_TEX_COLOR_HAND) .source (IrisCompatBuffers .POS_COLOR_TEX_LIGHT_HAND) .mode (VertexFormat.Mode .QUADS) .mode (VertexFormat.Mode .TRIANGLES) .build (); public static final AcceleratedBufferSources SHADOW = AcceleratedBufferSources .builder() .source (IrisCompatBuffers.BLOCK_SHADOW) .source (IrisCompatBuffers.ENTITY_SHADOW) .source (IrisCompatBuffers.GLYPH_SHADOW) .source (IrisCompatBuffers.POS_TEX_SHADOW) .source (IrisCompatBuffers.POS_TEX_COLOR_SHADOW) .mode (VertexFormat.Mode.QUADS) .mode (VertexFormat.Mode.TRIANGLES) .build (); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/IrisCompatBuffersProvider.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAcceleratedBufferSource; import java.util.function.Supplier; public class IrisCompatBuffersProvider { public static final Supplier SHADOW = () -> IrisCompatBuffers.SHADOW; public static final Supplier HAND = () -> IrisCompatBuffers.HAND; } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/IrisCompatFeature.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris; import com.github.argon4w.acceleratedrendering.configs.FeatureConfig; import com.github.argon4w.acceleratedrendering.configs.FeatureStatus; import java.util.ArrayDeque; import java.util.Deque; public class IrisCompatFeature { public static final Deque SHADOW_CULLING_CONTROLLER_STACK = new ArrayDeque<>(); public static final Deque POLYGON_PROCESSING_CONTROLLER_STACK = new ArrayDeque<>(); public static boolean isEnabled() { return FeatureConfig.CONFIG.irisCompatFeatureStatus.get() == FeatureStatus.ENABLED; } public static boolean isIrisCompatCullingEnabled() { return FeatureConfig.CONFIG.irisCompatOrientationCullingCompat.get() == FeatureStatus.ENABLED; } public static boolean isShadowCullingEnabled() { return getShadowCullingSetting() == FeatureStatus.ENABLED; } public static boolean isPolygonProcessingEnabled() { return getPolygonProcessingSetting() == FeatureStatus.ENABLED; } public static void disableShadowCulling() { SHADOW_CULLING_CONTROLLER_STACK.push(FeatureStatus.DISABLED); } public static void disablePolygonProcessing() { POLYGON_PROCESSING_CONTROLLER_STACK.push(FeatureStatus.DISABLED); } public static void forceEnableShadowCulling() { SHADOW_CULLING_CONTROLLER_STACK.push(FeatureStatus.ENABLED); } public static void forceEnablePolygonProcessing() { POLYGON_PROCESSING_CONTROLLER_STACK.push(FeatureStatus.ENABLED); } public static void forceSetShadowCulling(FeatureStatus status) { SHADOW_CULLING_CONTROLLER_STACK.push(status); } public static void forceSetIrisPolygonProcessing(FeatureStatus status) { POLYGON_PROCESSING_CONTROLLER_STACK.push(status); } public static void resetShadowCulling() { SHADOW_CULLING_CONTROLLER_STACK.pop(); } public static void resetPolygonProcessing() { POLYGON_PROCESSING_CONTROLLER_STACK.pop(); } public static FeatureStatus getShadowCullingSetting() { return SHADOW_CULLING_CONTROLLER_STACK.isEmpty() ? getDefaultShadowCullingSetting() : SHADOW_CULLING_CONTROLLER_STACK.peek(); } public static FeatureStatus getPolygonProcessingSetting() { return POLYGON_PROCESSING_CONTROLLER_STACK.isEmpty() ? getDefaultPolygonProcessingSetting() : POLYGON_PROCESSING_CONTROLLER_STACK.peek(); } public static FeatureStatus getDefaultShadowCullingSetting() { return FeatureConfig.CONFIG.irisCompatShadowCulling.get(); } public static FeatureStatus getDefaultPolygonProcessingSetting() { return FeatureConfig.CONFIG.irisCompatPolygonProcessing.get(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/environments/IrisBufferEnvironment.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.environments; import com.github.argon4w.acceleratedrendering.core.backends.buffers.IServerBuffer; import com.github.argon4w.acceleratedrendering.core.buffers.environments.IBufferEnvironment; import com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout; import com.github.argon4w.acceleratedrendering.core.meshes.ServerMesh; import com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramSelector; import com.github.argon4w.acceleratedrendering.core.programs.culling.LoadCullingProgramSelectorEvent; import com.github.argon4w.acceleratedrendering.core.programs.dispatchers.IPolygonProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.programs.dispatchers.MeshUploadingProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.programs.dispatchers.TransformProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.programs.overrides.IShaderProgramOverrides; import com.github.argon4w.acceleratedrendering.core.programs.overrides.ITransformShaderProgramOverride; import com.github.argon4w.acceleratedrendering.core.programs.overrides.IUploadingShaderProgramOverride; import com.github.argon4w.acceleratedrendering.core.programs.overrides.LoadShaderProgramOverridesEvent; import com.github.argon4w.acceleratedrendering.core.programs.processing.IPolygonProcessor; import com.github.argon4w.acceleratedrendering.core.programs.processing.LoadPolygonProcessorEvent; import com.mojang.blaze3d.vertex.VertexFormat; import net.irisshaders.iris.api.v0.IrisApi; import net.irisshaders.iris.vertices.ImmediateState; import net.minecraft.client.renderer.RenderType; import net.minecraft.resources.ResourceLocation; import net.neoforged.fml.ModLoader; import java.util.Set; public class IrisBufferEnvironment implements IBufferEnvironment { private final IBufferEnvironment vanillaSubSet; private final IBufferEnvironment irisSubSet; public IrisBufferEnvironment( IBufferEnvironment vanillaSubSet, VertexFormat vanillaVertexFormat, VertexFormat irisVertexFormat, ResourceLocation meshUploadingProgramKey, ResourceLocation transformProgramKey ) { this.vanillaSubSet = vanillaSubSet; this.irisSubSet = new IrisSubSet( vanillaVertexFormat, irisVertexFormat, meshUploadingProgramKey, transformProgramKey ); } private IBufferEnvironment getSubSet() { return IrisApi.getInstance().isShaderPackInUse() && ImmediateState.isRenderingLevel ? irisSubSet : vanillaSubSet; } @Override public void setupBufferState() { getSubSet().setupBufferState(); } @Override public Set getVertexFormats() { return irisSubSet.getVertexFormats(); } @Override public VertexLayout getLayout() { return getSubSet().getLayout(); } @Override public IServerBuffer getImmediateMeshBuffer() { return getSubSet().getImmediateMeshBuffer(); } @Override public ITransformShaderProgramOverride getTransformProgramOverride(RenderType renderType) { return getSubSet().getTransformProgramOverride(renderType); } @Override public IUploadingShaderProgramOverride getUploadingProgramOverride(RenderType renderType) { return getSubSet().getUploadingProgramOverride(renderType); } @Override public MeshUploadingProgramDispatcher selectMeshUploadingProgramDispatcher() { return getSubSet().selectMeshUploadingProgramDispatcher(); } @Override public TransformProgramDispatcher selectTransformProgramDispatcher() { return getSubSet().selectTransformProgramDispatcher(); } @Override public ICullingProgramDispatcher selectCullingProgramDispatcher(RenderType renderType) { return getSubSet().selectCullingProgramDispatcher(renderType); } @Override public IPolygonProgramDispatcher selectProcessingProgramDispatcher(VertexFormat.Mode mode) { return getSubSet().selectProcessingProgramDispatcher(mode); } @Override public boolean isAccelerated(VertexFormat vertexFormat) { return getSubSet().isAccelerated(vertexFormat); } @Override public int getVertexSize() { return getSubSet().getVertexSize(); } public static class IrisSubSet implements IBufferEnvironment { private final VertexFormat vanillaVertexFormat; private final VertexFormat irisVertexFormat; private final VertexLayout layout; private final IShaderProgramOverrides shaderProgramOverrides; private final MeshUploadingProgramDispatcher meshUploadingProgramDispatcher; private final TransformProgramDispatcher transformProgramDispatcher; private final ICullingProgramSelector cullingProgramSelector; private final IPolygonProcessor polygonProcessor; public IrisSubSet( VertexFormat vanillaVertexFormat, VertexFormat irisVertexFormat, ResourceLocation uploadingProgramKey, ResourceLocation transformProgramKey ) { var defaultTransformOverride = new TransformProgramDispatcher .Default(transformProgramKey, 4L * 4L); var defaultUploadingOverride = new MeshUploadingProgramDispatcher.Default(uploadingProgramKey, 7L * 4L); this.vanillaVertexFormat = vanillaVertexFormat; this.irisVertexFormat = irisVertexFormat; this.layout = new VertexLayout(this.irisVertexFormat); this.shaderProgramOverrides = ModLoader.postEventWithReturn(new LoadShaderProgramOverridesEvent (this.irisVertexFormat)).getOverrides (defaultTransformOverride, defaultUploadingOverride); this.cullingProgramSelector = ModLoader.postEventWithReturn(new LoadCullingProgramSelectorEvent (this.irisVertexFormat)).getSelector (); this.polygonProcessor = ModLoader.postEventWithReturn(new LoadPolygonProcessorEvent (this.irisVertexFormat)).getProcessor (); this.meshUploadingProgramDispatcher = new MeshUploadingProgramDispatcher(); this.transformProgramDispatcher = new TransformProgramDispatcher (); } @Override public void setupBufferState() { irisVertexFormat.setupBufferState(); } @Override public boolean isAccelerated(VertexFormat vertexFormat) { return this.vanillaVertexFormat == vertexFormat || this.irisVertexFormat == vertexFormat; } @Override public Set getVertexFormats() { return Set.of(vanillaVertexFormat, irisVertexFormat); } @Override public VertexLayout getLayout() { return layout; } @Override public IServerBuffer getImmediateMeshBuffer() { return ServerMesh.Builder.BUFFERS.get(layout).getFirst(); } @Override public ITransformShaderProgramOverride getTransformProgramOverride(RenderType renderType) { return shaderProgramOverrides.getTransformOverrides().get(renderType); } @Override public IUploadingShaderProgramOverride getUploadingProgramOverride(RenderType renderType) { return shaderProgramOverrides.getUploadingOverrides().get(renderType); } @Override public MeshUploadingProgramDispatcher selectMeshUploadingProgramDispatcher() { return meshUploadingProgramDispatcher; } @Override public TransformProgramDispatcher selectTransformProgramDispatcher() { return transformProgramDispatcher; } @Override public ICullingProgramDispatcher selectCullingProgramDispatcher(RenderType renderType) { return cullingProgramSelector.select(renderType); } @Override public IPolygonProgramDispatcher selectProcessingProgramDispatcher(VertexFormat.Mode mode) { return polygonProcessor.select(mode); } @Override public int getVertexSize() { return irisVertexFormat.getVertexSize(); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/interfaces/IIrisAcceleratedBufferBuilder.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.interfaces; import com.github.argon4w.acceleratedrendering.core.buffers.memory.IMemoryInterface; public interface IIrisAcceleratedBufferBuilder { IMemoryInterface getEntityIdOffset (); IMemoryInterface getEntityOffset (); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/interfaces/IIrisMeshInfo.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.interfaces; public interface IIrisMeshInfo { short getRenderedEntity (); short getRenderedBlockEntity(); short getRenderedItem (); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/interfaces/IIrisMeshInfoCache.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.interfaces; public interface IIrisMeshInfoCache { short getRenderedEntity (int i); short getRenderedBlockEntity(int i); short getRenderedItem (int i); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/AcceleratedBufferBuilderMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering; import com.github.argon4w.acceleratedrendering.compat.iris.interfaces.IIrisAcceleratedBufferBuilder; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.AcceleratedRingBuffers; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.functions.ILayerFunction; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.ElementBufferPool; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.StagingBufferPool; import com.github.argon4w.acceleratedrendering.core.buffers.memory.IMemoryInterface; import com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout; import com.llamalad7.mixinextras.sugar.Local; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexFormatElement; import net.irisshaders.iris.uniforms.CapturedRenderingState; import net.irisshaders.iris.vertices.IrisVertexFormats; import net.minecraft.client.renderer.RenderType; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(AcceleratedBufferBuilder.class) public class AcceleratedBufferBuilderMixin implements IIrisAcceleratedBufferBuilder { @Shadow @Final private VertexLayout layout; @Shadow private long vertexAddress; @Unique private IMemoryInterface entityIdOffset; @Unique private IMemoryInterface entityOffset; @Inject( method = "", at = @At("TAIL") ) public void constructor( StagingBufferPool .StagingBuffer vertexBuffer, StagingBufferPool .StagingBuffer varyingBuffer, ElementBufferPool .ElementSegment elementSegment, AcceleratedRingBuffers .Buffers buffers, ILayerFunction layerFunction, RenderType renderType, CallbackInfo ci ) { entityIdOffset = layout.getElement(IrisVertexFormats.ENTITY_ID_ELEMENT); entityOffset = layout.getElement(IrisVertexFormats.ENTITY_ELEMENT); } @Inject( method = "addVertex(FFFIFFIIFFF)V", at = @At("TAIL") ) public void addIrisVertex( float pX, float pY, float pZ, int pColor, float pU, float pV, int pPackedOverlay, int pPackedLight, float pNormalX, float pNormalY, float pNormalZ, CallbackInfo ci, @Local(name = "vertexAddress") long vertexAddress ) { addIrisData(vertexAddress); } @Inject( method = "addVertex(FFF)Lcom/mojang/blaze3d/vertex/VertexConsumer;", at = @At("TAIL") ) public void addIrisVertex( float pX, float pY, float pZ, CallbackInfoReturnable cir) { addIrisData(vertexAddress); } @Inject( method = { "addServerMesh", "addClientMesh" }, at = @At( value = "INVOKE", target = "Lcom/github/argon4w/acceleratedrendering/core/buffers/memory/IMemoryInterface;putInt(JI)V", ordinal = 2, shift = At.Shift.AFTER ) ) public void addIrisMesh(CallbackInfo ci, @Local(name = "vertexAddress") long vertexAddress) { addIrisData(vertexAddress); } @Unique private void addIrisData(long vertexAddress) { entityOffset .putShort(vertexAddress + 0L, (short) -1); entityOffset .putShort(vertexAddress + 2L, (short) -1); entityIdOffset .putShort(vertexAddress + 0L, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedEntity ()); entityIdOffset .putShort(vertexAddress + 2L, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedBlockEntity ()); entityIdOffset .putShort(vertexAddress + 4L, (short) CapturedRenderingState.INSTANCE.getCurrentRenderedItem ()); } @Unique @Override public IMemoryInterface getEntityIdOffset() { return entityIdOffset; } @Unique @Override public IMemoryInterface getEntityOffset() { return entityOffset; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/AcceleratedBufferSourceMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.AcceleratedBufferSource; import net.irisshaders.batchedentityrendering.impl.WrappableRenderType; import net.irisshaders.iris.vertices.ImmediateState; import net.minecraft.client.renderer.RenderType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(AcceleratedBufferSource.class) public class AcceleratedBufferSourceMixin { @ModifyArg( method = "getBuffer", at = @At( value = "INVOKE", target = "Lcom/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/AcceleratedBufferBuilder;(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" ), index = 5 ) public RenderType unwrapIrisRenderType(RenderType renderType) { return renderType instanceof WrappableRenderType wrapped ? wrapped.unwrap() : renderType; } @Inject( method = "drawBuffers", at = @At( value = "INVOKE", target = "Lcom/github/argon4w/acceleratedrendering/core/buffers/accelerated/AcceleratedRingBuffers$Buffers;bindDrawBuffers()V", shift = At.Shift.BEFORE ) ) private void beforeBindDrawBuffers(CallbackInfo ci) { if (!ImmediateState.isRenderingLevel) { ImmediateState.renderWithExtendedVertexFormat = false; } } @Inject( method = "drawBuffers", at = @At( value = "INVOKE", target = "Lcom/github/argon4w/acceleratedrendering/core/buffers/accelerated/AcceleratedRingBuffers$Buffers;bindDrawBuffers()V", shift = At.Shift.AFTER ) ) private void afterBindDrawBuffers(CallbackInfo ci) { if (!ImmediateState.isRenderingLevel) { ImmediateState.renderWithExtendedVertexFormat = true; } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/AcceleratedRenderingModEntryMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering; import com.github.argon4w.acceleratedrendering.AcceleratedRenderingModEntry; import com.github.argon4w.acceleratedrendering.compat.iris.programs.IrisPrograms; import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.ModContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(AcceleratedRenderingModEntry.class) public class AcceleratedRenderingModEntryMixin { @Inject( method = "", at = @At("TAIL") ) public void registerIrisEvents( IEventBus modEventBus, ModContainer modContainer, CallbackInfo ci ) { modEventBus.register(IrisPrograms.class); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/CoreBuffersProviderMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering; import com.github.argon4w.acceleratedrendering.core.CoreBuffersProvider; import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import net.irisshaders.batchedentityrendering.impl.RenderBuffersExt; import net.minecraft.client.renderer.RenderBuffers; import org.spongepowered.asm.mixin.Mixin; @Mixin(CoreBuffersProvider.class) public class CoreBuffersProviderMixin { @WrapMethod(method = "bindAcceleratedBufferSources") private static void bindAcceleratedBufferSourcesForIris(RenderBuffers renderBuffers, Operation original) { var extension = (RenderBuffersExt) renderBuffers; extension .beginLevelRendering(); original .call (renderBuffers); extension .endLevelRendering (); original .call (renderBuffers); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/FlattenMeshInfoCacheMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering; import com.github.argon4w.acceleratedrendering.compat.iris.interfaces.IIrisMeshInfoCache; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.FlattenMeshInfoCache; import com.llamalad7.mixinextras.sugar.Local; import net.irisshaders.iris.uniforms.CapturedRenderingState; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Constant; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyConstant; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.lang.invoke.VarHandle; @Mixin(FlattenMeshInfoCache.class) public class FlattenMeshInfoCacheMixin implements IIrisMeshInfoCache { @Shadow @Final public static VarHandle HANDLE; @Shadow private int[] cache; @Unique private static final int IRIS_MESH_INFO_SIZE = 8; @Unique private static final int RENDERED_ENTITY_OFFSET = 5; @Unique private static final int RENDERED_BLOCK_ENTITY_OFFSET = 6; @Unique private static final int RENDERED_ITEM_OFFSET = 7; @ModifyConstant( method = { "", "setup", "getSharing", "getShouldCull", "getColor", "getLight", "getOverlay" }, constant = @Constant(intValue = 5) ) public int modifySize(int constant) { return IRIS_MESH_INFO_SIZE; } @Inject( method = "setup", at = @At( value = "INVOKE", target = "Ljava/lang/invoke/VarHandle;set([III)V", ordinal = 4, shift = At.Shift.AFTER ) ) public void addIrisData( int color, int light, int overlay, int sharing, int shouldCull, CallbackInfo ci, @Local(name = "infoIndex") int infoIndex ) { HANDLE.set(cache, infoIndex + RENDERED_ENTITY_OFFSET, CapturedRenderingState.INSTANCE.getCurrentRenderedEntity ()); HANDLE.set(cache, infoIndex + RENDERED_BLOCK_ENTITY_OFFSET, CapturedRenderingState.INSTANCE.getCurrentRenderedBlockEntity ()); HANDLE.set(cache, infoIndex + RENDERED_ITEM_OFFSET, CapturedRenderingState.INSTANCE.getCurrentRenderedItem ()); } @Override public short getRenderedEntity(int i) { return (short) (int) HANDLE.get(cache, i * IRIS_MESH_INFO_SIZE + RENDERED_ENTITY_OFFSET); } @Override public short getRenderedBlockEntity(int i) { return (short) (int) HANDLE.get(cache, i * IRIS_MESH_INFO_SIZE + RENDERED_BLOCK_ENTITY_OFFSET); } @Override public short getRenderedItem(int i) { return (short) (int) HANDLE.get(cache, i * IRIS_MESH_INFO_SIZE + RENDERED_ITEM_OFFSET); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/IBufferEnvironmentPresetsMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering; import com.github.argon4w.acceleratedrendering.compat.iris.environments.IrisBufferEnvironment; import com.github.argon4w.acceleratedrendering.compat.iris.programs.IrisPrograms; import com.github.argon4w.acceleratedrendering.core.buffers.environments.IBufferEnvironment; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import net.irisshaders.iris.vertices.IrisVertexFormats; import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @Mixin(IBufferEnvironment.Presets.class) public class IBufferEnvironmentPresetsMixin { @Mutable @Shadow @Final public static IBufferEnvironment BLOCK; @Mutable @Shadow @Final public static IBufferEnvironment ENTITY; @Mutable @Shadow @Final public static IBufferEnvironment POS_COLOR_TEX_LIGHT; @WrapOperation( method = "", at = @At( value = "FIELD", target = "Lcom/github/argon4w/acceleratedrendering/core/buffers/environments/IBufferEnvironment$Presets;BLOCK:Lcom/github/argon4w/acceleratedrendering/core/buffers/environments/IBufferEnvironment;", opcode = Opcodes.PUTSTATIC ) ) private static void useIrisBloockEnvironment(IBufferEnvironment value, Operation original) { original.call(new IrisBufferEnvironment( value, DefaultVertexFormat .BLOCK, IrisVertexFormats .TERRAIN, IrisPrograms .IRIS_BLOCK_MESH_UPLOADING_KEY, IrisPrograms .IRIS_BLOCK_VERTEX_TRANSFORM_KEY )); } @WrapOperation( method = "", at = @At( value = "FIELD", target = "Lcom/github/argon4w/acceleratedrendering/core/buffers/environments/IBufferEnvironment$Presets;ENTITY:Lcom/github/argon4w/acceleratedrendering/core/buffers/environments/IBufferEnvironment;", opcode = Opcodes.PUTSTATIC ) ) private static void useIrisEntityEnvironment(IBufferEnvironment value, Operation original) { original.call(new IrisBufferEnvironment( value, DefaultVertexFormat .NEW_ENTITY, IrisVertexFormats .ENTITY, IrisPrograms .IRIS_ENTITY_MESH_UPLOADING_KEY, IrisPrograms .IRIS_ENTITY_VERTEX_TRANSFORM_KEY )); } @WrapOperation( method = "", at = @At( value = "FIELD", target = "Lcom/github/argon4w/acceleratedrendering/core/buffers/environments/IBufferEnvironment$Presets;POS_COLOR_TEX_LIGHT:Lcom/github/argon4w/acceleratedrendering/core/buffers/environments/IBufferEnvironment;", opcode = Opcodes.PUTSTATIC ) ) private static void useIrisGlyphEnvironment(IBufferEnvironment value, Operation original) { original.call(new IrisBufferEnvironment( value, DefaultVertexFormat .POSITION_COLOR_TEX_LIGHTMAP, IrisVertexFormats .GLYPH, IrisPrograms .IRIS_GLYPH_MESH_UPLOADING_KEY, IrisPrograms .IRIS_GLYPH_VERTEX_TRANSFORM_KEY )); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/MeshUploaderMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering; import com.github.argon4w.acceleratedrendering.compat.iris.interfaces.IIrisMeshInfoCache; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.IMeshInfoCache; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.MeshUploaderPool; import com.github.argon4w.acceleratedrendering.core.buffers.memory.IMemoryInterface; import com.github.argon4w.acceleratedrendering.core.buffers.memory.SimpleDynamicMemoryInterface; import com.llamalad7.mixinextras.sugar.Local; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(MeshUploaderPool.MeshUploader.class) public abstract class MeshUploaderMixin { @Shadow @Final private IMeshInfoCache meshInfos; @Unique private final IMemoryInterface IRIS_INFO_ENTITY = new SimpleDynamicMemoryInterface(5L * 4L + 0L * 2L, (MeshUploaderPool.MeshUploader) (Object) this); @Unique private final IMemoryInterface IRIS_INFO_BLOCK_ENTITY = new SimpleDynamicMemoryInterface(5L * 4L + 1L * 2L, (MeshUploaderPool.MeshUploader) (Object) this); @Unique private final IMemoryInterface IRIS_INFO_ITEM = new SimpleDynamicMemoryInterface(5L * 4L + 2L * 2L, (MeshUploaderPool.MeshUploader) (Object) this); @Inject( method = "upload", at = @At( value = "INVOKE", target = "Lcom/github/argon4w/acceleratedrendering/core/buffers/memory/IMemoryInterface;putInt(JI)V", ordinal = 4, shift = At.Shift.AFTER ) ) public void uploadIrisData( CallbackInfo ci, @Local(name = "meshInfoAddress") long meshInfoAddress, @Local(name = "i") int offset ) { IRIS_INFO_ENTITY .at(offset).putShort(meshInfoAddress, ((IIrisMeshInfoCache) meshInfos).getRenderedEntity (offset)); IRIS_INFO_BLOCK_ENTITY .at(offset).putShort(meshInfoAddress, ((IIrisMeshInfoCache) meshInfos).getRenderedBlockEntity (offset)); IRIS_INFO_ITEM .at(offset).putShort(meshInfoAddress, ((IIrisMeshInfoCache) meshInfos).getRenderedItem (offset)); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/MeshUploadingProgramDispatcherMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering; import com.github.argon4w.acceleratedrendering.compat.iris.interfaces.IIrisAcceleratedBufferBuilder; import com.github.argon4w.acceleratedrendering.compat.iris.interfaces.IIrisMeshInfoCache; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.AcceleratedRingBuffers; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.IMeshInfoCache; import com.github.argon4w.acceleratedrendering.core.programs.dispatchers.MeshUploadingProgramDispatcher; import com.llamalad7.mixinextras.sugar.Local; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.Collection; @Mixin(MeshUploadingProgramDispatcher.class) public class MeshUploadingProgramDispatcherMixin { @Inject( method = "dispatch", at = @At( value = "INVOKE", target = "Lcom/github/argon4w/acceleratedrendering/core/buffers/memory/IMemoryInterface;putInt(JI)V", ordinal = 2, shift = At.Shift.AFTER ) ) public void addIrisData( Collection builders, AcceleratedRingBuffers.Buffers buffers, CallbackInfo ci, @Local(name = "meshInfos") IMeshInfoCache meshInfos, @Local(name = "builder") AcceleratedBufferBuilder builder, @Local(name = "offset") int offset, @Local(name = "i") int i, @Local(name = "vertexAddress") long vertexAddress ) { ((IIrisAcceleratedBufferBuilder) builder).getEntityIdOffset() .at(offset).putShort(vertexAddress + 0L, ((IIrisMeshInfoCache) meshInfos).getRenderedEntity (i)); ((IIrisAcceleratedBufferBuilder) builder).getEntityIdOffset() .at(offset).putShort(vertexAddress + 2L, ((IIrisMeshInfoCache) meshInfos).getRenderedEntity (i)); ((IIrisAcceleratedBufferBuilder) builder).getEntityIdOffset() .at(offset).putShort(vertexAddress + 4L, ((IIrisMeshInfoCache) meshInfos).getRenderedEntity (i)); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/RenderTypeUtilsMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType; import com.github.argon4w.acceleratedrendering.core.utils.RenderTypeUtils; import net.irisshaders.batchedentityrendering.impl.BlendingStateHolder; import net.irisshaders.batchedentityrendering.impl.TransparencyType; import net.irisshaders.batchedentityrendering.impl.WrappableRenderType; import net.minecraft.client.renderer.RenderType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(RenderTypeUtils.class) public class RenderTypeUtilsMixin { @ModifyVariable( method = "getTextureLocation", at = @At("HEAD"), ordinal = 0, argsOnly = true ) private static RenderType unwrapIrisRenderType1(RenderType renderType) { return renderType instanceof WrappableRenderType wrapped ? wrapped.unwrap() : renderType; } @ModifyVariable( method = "isCulled", at = @At("HEAD"), ordinal = 0, argsOnly = true ) private static RenderType unwrapIrisRenderType2(RenderType renderType) { return renderType instanceof WrappableRenderType wrapped ? wrapped.unwrap() : renderType; } @ModifyVariable( method = "isDynamic", at = @At("HEAD"), ordinal = 0, argsOnly = true ) private static RenderType unwrapIrisRenderType3(RenderType renderType) { return renderType instanceof WrappableRenderType wrapped ? wrapped.unwrap() : renderType; } @ModifyVariable( method = "hasDepth", at = @At("HEAD"), ordinal = 0, argsOnly = true ) private static RenderType unwrapIrisRenderType4(RenderType renderType) { return renderType instanceof WrappableRenderType wrapped ? wrapped.unwrap() : renderType; } @ModifyVariable( method = "withDepth", at = @At("HEAD"), ordinal = 0, argsOnly = true ) private static RenderType unwrapIrisRenderType5(RenderType renderType) { return renderType instanceof WrappableRenderType wrapped ? wrapped.unwrap() : renderType; } @Inject( method = "getDrawType", at = @At("HEAD"), cancellable = true ) private static void getIrisRenderTypeDrawType(RenderType renderType, CallbackInfoReturnable cir) { var holder = (BlendingStateHolder) renderType; cir.setReturnValue( holder.getTransparencyType() == TransparencyType.GENERAL_TRANSPARENT || holder.getTransparencyType() == TransparencyType.DECAL ? LayerDrawType.TRANSLUCENT : LayerDrawType.OPAQUE ); } @Inject( method = "isTranslucent", at = @At("HEAD"), cancellable = true ) private static void checkIrisTransparency(RenderType renderType, CallbackInfoReturnable cir) { var holder = (BlendingStateHolder) renderType; cir.setReturnValue( holder.getTransparencyType() == TransparencyType.GENERAL_TRANSPARENT || holder.getTransparencyType() == TransparencyType.DECAL ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/SimpleMeshInfoCacheMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering; import com.github.argon4w.acceleratedrendering.compat.iris.interfaces.IIrisMeshInfo; import com.github.argon4w.acceleratedrendering.compat.iris.interfaces.IIrisMeshInfoCache; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.SimpleMeshInfo; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.SimpleMeshInfoCache; import com.github.argon4w.acceleratedrendering.core.utils.SimpleCachedArray; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @Mixin(SimpleMeshInfoCache.class) public class SimpleMeshInfoCacheMixin implements IIrisMeshInfoCache { @Shadow @Final private SimpleCachedArray meshInfos; @Override public short getRenderedEntity(int i) { return ((IIrisMeshInfo) meshInfos.at(i)).getRenderedEntity(); } @Override public short getRenderedBlockEntity(int i) { return ((IIrisMeshInfo) meshInfos.at(i)).getRenderedBlockEntity(); } @Override public short getRenderedItem(int i) { return ((IIrisMeshInfo) meshInfos.at(i)).getRenderedItem(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/SimpleMeshInfoMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering; import com.github.argon4w.acceleratedrendering.compat.iris.interfaces.IIrisMeshInfo; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.SimpleMeshInfo; import net.irisshaders.iris.uniforms.CapturedRenderingState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(SimpleMeshInfo.class) public class SimpleMeshInfoMixin implements IIrisMeshInfo { @Unique private short renderedEntity; @Unique private short renderedBlockEntity; @Unique private short renderedItem; @Inject(method = "setupMeshInfo", at = @At("TAIL")) public void setIrisData( int color, int light, int overlay, int sharing, int shouldCull, CallbackInfo ci ) { renderedEntity = (short) CapturedRenderingState.INSTANCE.getCurrentRenderedEntity (); renderedBlockEntity = (short) CapturedRenderingState.INSTANCE.getCurrentRenderedBlockEntity (); renderedItem = (short) CapturedRenderingState.INSTANCE.getCurrentRenderedItem (); } @Unique @Override public short getRenderedEntity() { return renderedEntity; } @Unique @Override public short getRenderedBlockEntity() { return renderedBlockEntity; } @Unique @Override public short getRenderedItem() { return renderedItem; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/acceleratedrendering/UnsafeMemoryMeshInfoCacheMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.mixins.acceleratedrendering; import com.github.argon4w.acceleratedrendering.compat.iris.interfaces.IIrisMeshInfoCache; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.UnsafeMemoryMeshInfoCache; import com.llamalad7.mixinextras.sugar.Local; import net.irisshaders.iris.uniforms.CapturedRenderingState; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Constant; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyConstant; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import sun.misc.Unsafe; @Mixin(UnsafeMemoryMeshInfoCache.class) public class UnsafeMemoryMeshInfoCacheMixin implements IIrisMeshInfoCache { @Shadow @Final public static Unsafe UNSAFE; @Shadow private long address; @Unique private static final long IRIS_MESH_INFO_SIZE = 8L * 4L; @Unique private static final long RENDERED_ENTITY_OFFSET = 5L * 4L; @Unique private static final long RENDERED_BLOCK_ENTITY_OFFSET = 6L * 4L; @Unique private static final long RENDERED_ITEM_OFFSET = 7L * 4L; @ModifyConstant( method = { "", "setup", "getSharing", "getShouldCull", "getColor", "getLight", "getOverlay" }, constant = @Constant(longValue = 20L) ) public long modifySize(long constant) { return IRIS_MESH_INFO_SIZE; } @Inject( method = "setup", at = @At( value = "INVOKE", target = "Lsun/misc/Unsafe;putInt(JI)V", ordinal = 4, shift = At.Shift.AFTER ) ) public void addIrisData( int color, int light, int overlay, int sharing, int shouldCull, CallbackInfo ci, @Local(name = "infoAddress") long infoAddress ) { UNSAFE.putInt(infoAddress + RENDERED_ENTITY_OFFSET, CapturedRenderingState.INSTANCE.getCurrentRenderedEntity ()); UNSAFE.putInt(infoAddress + RENDERED_BLOCK_ENTITY_OFFSET, CapturedRenderingState.INSTANCE.getCurrentRenderedBlockEntity ()); UNSAFE.putInt(infoAddress + RENDERED_ITEM_OFFSET, CapturedRenderingState.INSTANCE.getCurrentRenderedItem ()); } @Override public short getRenderedEntity(int i) { return (short) UNSAFE.getInt(address + i * IRIS_MESH_INFO_SIZE + RENDERED_ENTITY_OFFSET); } @Override public short getRenderedBlockEntity(int i) { return (short) UNSAFE.getInt(address + i * IRIS_MESH_INFO_SIZE + RENDERED_BLOCK_ENTITY_OFFSET); } @Override public short getRenderedItem(int i) { return (short) UNSAFE.getInt(address + i * IRIS_MESH_INFO_SIZE + RENDERED_ITEM_OFFSET); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/iris/FullyBufferedMultiBufferSourceMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.mixins.iris; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratableBufferSource; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.llamalad7.mixinextras.injector.ModifyReturnValue; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.experimental.ExtensionMethod; import net.irisshaders.batchedentityrendering.impl.FullyBufferedMultiBufferSource; import net.minecraft.client.renderer.RenderType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.injection.At; @Pseudo @ExtensionMethod(VertexConsumerExtension .class) @Mixin (FullyBufferedMultiBufferSource .class) public abstract class FullyBufferedMultiBufferSourceMixin implements IAcceleratableBufferSource { @ModifyReturnValue( method = "getBuffer", at = @At("RETURN") ) public VertexConsumer initAcceleration(VertexConsumer original, RenderType renderType) { return original .getHolder () .initAcceleration (renderType, getBoundAcceleratedBufferSource()); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/iris/HandRendererMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.mixins.iris; import com.github.argon4w.acceleratedrendering.compat.iris.IrisCompatBuffers; import com.github.argon4w.acceleratedrendering.compat.iris.IrisCompatBuffersProvider; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.CoreStates; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.BufferSourceExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import lombok.experimental.ExtensionMethod; import net.irisshaders.batchedentityrendering.impl.FullyBufferedMultiBufferSource; import net.irisshaders.iris.pathways.HandRenderer; import net.irisshaders.iris.pipeline.WorldRenderingPipeline; import net.minecraft.client.Camera; import net.minecraft.client.renderer.GameRenderer; import org.joml.Matrix4fc; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Pseudo @ExtensionMethod(BufferSourceExtension .class) @Mixin (HandRenderer .class) public class HandRendererMixin { @Shadow @Final private FullyBufferedMultiBufferSource bufferSource; @Inject( method = "", at = @At("TAIL") ) public void bindAcceleratedBufferSourceHand(CallbackInfo ci) { bufferSource .getAcceleratable () .bindAcceleratedBufferSource(IrisCompatBuffersProvider.HAND); } @Inject( method = "renderSolid", at = @At( value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;renderHandsWithItems(FLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/player/LocalPlayer;I)V", shift = At.Shift.BEFORE ) ) public void startRenderSolidFast( Matrix4fc modelMatrix, float tickDelta, Camera camera, GameRenderer gameRenderer, WorldRenderingPipeline pipeline, CallbackInfo ci ) { CoreFeature.setRenderingHand(); } @Inject( method = "renderSolid", at = @At( value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;renderHandsWithItems(FLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/player/LocalPlayer;I)V", shift = At.Shift.AFTER ) ) public void stopRenderSolidFast( Matrix4fc modelMatrix, float tickDelta, Camera camera, GameRenderer gameRenderer, WorldRenderingPipeline pipeline, CallbackInfo ci ) { CoreFeature .resetRenderingHand (); CoreStates .recordBuffers (); IrisCompatBuffers.ENTITY_HAND .prepareBuffers (); IrisCompatBuffers.BLOCK_HAND .prepareBuffers (); IrisCompatBuffers.POS_HAND .prepareBuffers (); IrisCompatBuffers.POS_COLOR_HAND .prepareBuffers (); IrisCompatBuffers.POS_TEX_HAND .prepareBuffers (); IrisCompatBuffers.POS_TEX_COLOR_HAND .prepareBuffers (); IrisCompatBuffers.POS_COLOR_TEX_LIGHT_HAND .prepareBuffers (); CoreStates .restoreBuffers (); IrisCompatBuffers.ENTITY_HAND .drawBuffers (LayerDrawType.ALL); IrisCompatBuffers.BLOCK_HAND .drawBuffers (LayerDrawType.ALL); IrisCompatBuffers.POS_HAND .drawBuffers (LayerDrawType.ALL); IrisCompatBuffers.POS_COLOR_HAND .drawBuffers (LayerDrawType.ALL); IrisCompatBuffers.POS_TEX_HAND .drawBuffers (LayerDrawType.ALL); IrisCompatBuffers.POS_TEX_COLOR_HAND .drawBuffers (LayerDrawType.ALL); IrisCompatBuffers.POS_COLOR_TEX_LIGHT_HAND .drawBuffers (LayerDrawType.ALL); IrisCompatBuffers.ENTITY_HAND .clearBuffers (); IrisCompatBuffers.BLOCK_HAND .clearBuffers (); IrisCompatBuffers.POS_HAND .clearBuffers (); IrisCompatBuffers.POS_COLOR_HAND .clearBuffers (); IrisCompatBuffers.POS_TEX_HAND .clearBuffers (); IrisCompatBuffers.POS_TEX_COLOR_HAND .clearBuffers (); IrisCompatBuffers.POS_COLOR_TEX_LIGHT_HAND .clearBuffers (); } @Inject( method = "renderTranslucent", at = @At( value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;renderHandsWithItems(FLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/player/LocalPlayer;I)V", shift = At.Shift.BEFORE ) ) public void startRenderTranslucentFast( Matrix4fc modelMatrix, float tickDelta, Camera camera, GameRenderer gameRenderer, WorldRenderingPipeline pipeline, CallbackInfo ci ) { CoreFeature.setRenderingHand(); } @Inject( method = "renderTranslucent", at = @At( value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;renderHandsWithItems(FLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/player/LocalPlayer;I)V", shift = At.Shift.AFTER ) ) public void stopRenderTranslucentFast( Matrix4fc modelMatrix, float tickDelta, Camera camera, GameRenderer gameRenderer, WorldRenderingPipeline pipeline, CallbackInfo ci ) { CoreFeature .resetRenderingHand (); CoreStates .recordBuffers (); IrisCompatBuffers.ENTITY_HAND .prepareBuffers (); IrisCompatBuffers.BLOCK_HAND .prepareBuffers (); IrisCompatBuffers.POS_HAND .prepareBuffers (); IrisCompatBuffers.POS_COLOR_HAND .prepareBuffers (); IrisCompatBuffers.POS_TEX_HAND .prepareBuffers (); IrisCompatBuffers.POS_TEX_COLOR_HAND .prepareBuffers (); IrisCompatBuffers.POS_COLOR_TEX_LIGHT_HAND .prepareBuffers (); CoreStates .restoreBuffers (); IrisCompatBuffers.ENTITY_HAND .drawBuffers (LayerDrawType.ALL); IrisCompatBuffers.BLOCK_HAND .drawBuffers (LayerDrawType.ALL); IrisCompatBuffers.POS_HAND .drawBuffers (LayerDrawType.ALL); IrisCompatBuffers.POS_COLOR_HAND .drawBuffers (LayerDrawType.ALL); IrisCompatBuffers.POS_TEX_HAND .drawBuffers (LayerDrawType.ALL); IrisCompatBuffers.POS_TEX_COLOR_HAND .drawBuffers (LayerDrawType.ALL); IrisCompatBuffers.POS_COLOR_TEX_LIGHT_HAND .drawBuffers (LayerDrawType.ALL); IrisCompatBuffers.ENTITY_HAND .clearBuffers (); IrisCompatBuffers.BLOCK_HAND .clearBuffers (); IrisCompatBuffers.POS_HAND .clearBuffers (); IrisCompatBuffers.POS_COLOR_HAND .clearBuffers (); IrisCompatBuffers.POS_TEX_HAND .clearBuffers (); IrisCompatBuffers.POS_TEX_COLOR_HAND .clearBuffers (); IrisCompatBuffers.POS_COLOR_TEX_LIGHT_HAND .clearBuffers (); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/iris/IrisVertexFormatsMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.mixins.iris; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormatElement; import net.irisshaders.iris.vertices.IrisVertexFormats; import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; @Pseudo @Mixin( value = IrisVertexFormats.class, priority = Integer.MAX_VALUE ) public class IrisVertexFormatsMixin { @Shadow @Final @Mutable public static VertexFormat ENTITY; @Shadow @Final @Mutable public static VertexFormat GLYPH; @Shadow @Final public static VertexFormatElement ENTITY_ID_ELEMENT; @Shadow @Final public static VertexFormatElement MID_TEXTURE_ELEMENT; @Shadow @Final public static VertexFormatElement TANGENT_ELEMENT; @WrapOperation( method = "", at = @At( value = "FIELD", target = "Lnet/irisshaders/iris/vertices/IrisVertexFormats;ENTITY:Lcom/mojang/blaze3d/vertex/VertexFormat;", opcode = Opcodes.PUTSTATIC ) ) private static void addPaddingForEntityFormat(VertexFormat value, Operation original) { original.call (VertexFormat .builder() .add ("Position", VertexFormatElement.POSITION) .add ("Color", VertexFormatElement.COLOR) .add ("UV0", VertexFormatElement.UV0) .add ("UV1", VertexFormatElement.UV1) .add ("UV2", VertexFormatElement.UV2) .add ("Normal", VertexFormatElement.NORMAL) .padding(1) .add ("iris_Entity", ENTITY_ID_ELEMENT) .padding(2) .add ("mc_midTexCoord", MID_TEXTURE_ELEMENT) .add ("at_tangent", TANGENT_ELEMENT) .build () ); } @WrapOperation( method = "", at = @At( value = "FIELD", target = "Lnet/irisshaders/iris/vertices/IrisVertexFormats;GLYPH:Lcom/mojang/blaze3d/vertex/VertexFormat;", opcode = Opcodes.PUTSTATIC ) ) private static void addPaddingForGlyphFormat(VertexFormat value, Operation original) { original.call (VertexFormat .builder() .add ("Position", VertexFormatElement.POSITION) .add ("Color", VertexFormatElement.COLOR) .add ("UV0", VertexFormatElement.UV0) .add ("UV2", VertexFormatElement.UV2) .add ("Normal", VertexFormatElement.NORMAL) .padding(1) .add ("iris_Entity", ENTITY_ID_ELEMENT) .padding(2) .add ("mc_midTexCoord", MID_TEXTURE_ELEMENT) .add ("at_tangent", TANGENT_ELEMENT) .build () ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/iris/ModelToEntityVertexSerializerMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.mixins.iris; import net.irisshaders.iris.vertices.sodium.ModelToEntityVertexSerializer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.injection.Constant; import org.spongepowered.asm.mixin.injection.ModifyConstant; @Pseudo @Mixin(ModelToEntityVertexSerializer.class) public class ModelToEntityVertexSerializerMixin { @ModifyConstant( method = "serialize", constant = @Constant(longValue = 42L) ) public long modifyMidU(long constant) { return 44L; } @ModifyConstant( method = "serialize", constant = @Constant(longValue = 46L) ) public long modifyMidV(long constant) { return 48L; } @ModifyConstant( method = "serialize", constant = @Constant(longValue = 50L) ) public long modifyTangent(long constant) { return 52L; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/iris/ShadowRendererMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.mixins.iris; import com.github.argon4w.acceleratedrendering.compat.iris.IrisCompatBuffers; import com.github.argon4w.acceleratedrendering.compat.iris.IrisCompatBuffersProvider; import com.github.argon4w.acceleratedrendering.core.CoreStates; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.BufferSourceExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType; import lombok.experimental.ExtensionMethod; import net.irisshaders.batchedentityrendering.impl.RenderBuffersExt; import net.irisshaders.iris.mixin.LevelRendererAccessor; import net.irisshaders.iris.pipeline.IrisRenderingPipeline; import net.irisshaders.iris.shaderpack.programs.ProgramSource; import net.irisshaders.iris.shaderpack.properties.PackDirectives; import net.irisshaders.iris.shadows.ShadowCompositeRenderer; import net.irisshaders.iris.shadows.ShadowRenderTargets; import net.irisshaders.iris.shadows.ShadowRenderer; import net.irisshaders.iris.uniforms.custom.CustomUniforms; import net.minecraft.client.Camera; import net.minecraft.client.renderer.RenderBuffers; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Pseudo @ExtensionMethod(BufferSourceExtension .class) @Mixin (ShadowRenderer .class) public class ShadowRendererMixin { @Shadow @Final private RenderBuffers buffers; @Shadow @Final private RenderBuffersExt renderBuffersExt; @Inject(method = "", at = @At("TAIL")) public void bindAcceleratedShadowBufferSources( IrisRenderingPipeline pipeline, ProgramSource shadow, PackDirectives directives, ShadowRenderTargets shadowRenderTargets, ShadowCompositeRenderer compositeRenderer, CustomUniforms customUniforms, boolean separateHardwareSamplers, CallbackInfo ci ) { renderBuffersExt.beginLevelRendering(); buffers.bufferSource ().getAcceleratable().bindAcceleratedBufferSource(IrisCompatBuffersProvider.SHADOW); buffers.crumblingBufferSource ().getAcceleratable().bindAcceleratedBufferSource(IrisCompatBuffersProvider.SHADOW); buffers.outlineBufferSource ().getAcceleratable().bindAcceleratedBufferSource(IrisCompatBuffersProvider.SHADOW); renderBuffersExt.endLevelRendering(); } @Inject( method = "renderShadows", at = @At( value = "INVOKE", target = "Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;endBatch()V" ) ) public void endAllBatches( LevelRendererAccessor levelRenderer, Camera playerCamera, CallbackInfo ci ) { CoreStates .recordBuffers (); IrisCompatBuffers.BLOCK_SHADOW .prepareBuffers (); IrisCompatBuffers.ENTITY_SHADOW .prepareBuffers (); IrisCompatBuffers.GLYPH_SHADOW .prepareBuffers (); IrisCompatBuffers.POS_TEX_SHADOW .prepareBuffers (); IrisCompatBuffers.POS_TEX_COLOR_SHADOW .prepareBuffers (); CoreStates .restoreBuffers (); IrisCompatBuffers.BLOCK_SHADOW .drawBuffers (LayerDrawType.ALL); IrisCompatBuffers.ENTITY_SHADOW .drawBuffers (LayerDrawType.ALL); IrisCompatBuffers.GLYPH_SHADOW .drawBuffers (LayerDrawType.ALL); IrisCompatBuffers.POS_TEX_SHADOW .drawBuffers (LayerDrawType.ALL); IrisCompatBuffers.POS_TEX_COLOR_SHADOW .drawBuffers (LayerDrawType.ALL); IrisCompatBuffers.BLOCK_SHADOW .clearBuffers (); IrisCompatBuffers.ENTITY_SHADOW .clearBuffers (); IrisCompatBuffers.GLYPH_SHADOW .clearBuffers (); IrisCompatBuffers.POS_TEX_SHADOW .clearBuffers (); IrisCompatBuffers.POS_TEX_COLOR_SHADOW .clearBuffers (); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/plugin/IrisCompatMixinPlugin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.mixins.plugin; import com.github.argon4w.acceleratedrendering.compat.AbstractCompatMixinPlugin; import java.util.List; public class IrisCompatMixinPlugin extends AbstractCompatMixinPlugin { @Override protected List getModIDs() { return List.of("iris"); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/mixins/vanilla/LevelRendererMixin.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.mixins.vanilla; import com.github.argon4w.acceleratedrendering.compat.iris.IrisCompatBuffers; import com.github.argon4w.acceleratedrendering.core.CoreBuffers; import com.github.argon4w.acceleratedrendering.core.CoreStates; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.client.Camera; import net.minecraft.client.DeltaTracker; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin( value = LevelRenderer.class, priority = 999 ) public class LevelRendererMixin { @Inject( method = "renderLevel", at = @At( value = "INVOKE", target = "Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;endBatch()V", ordinal = 1 ) ) public void drawIrisAllCoreBuffers( DeltaTracker pDeltaTracker, boolean pRenderBlockOutline, Camera pCamera, GameRenderer pGameRenderer, LightTexture pLightTexture, Matrix4f pFrustumMatrix, Matrix4f pProjectionMatrix, CallbackInfo ci ) { CoreStates .recordBuffers (); CoreBuffers.ENTITY .prepareBuffers (); CoreBuffers.BLOCK .prepareBuffers (); CoreBuffers.POS .prepareBuffers (); CoreBuffers.POS_COLOR .prepareBuffers (); CoreBuffers.POS_TEX .prepareBuffers (); CoreBuffers.POS_TEX_COLOR .prepareBuffers (); CoreBuffers.POS_COLOR_TEX_LIGHT .prepareBuffers (); CoreStates .restoreBuffers (); CoreBuffers.ENTITY .drawBuffers (LayerDrawType.ALL); CoreBuffers.BLOCK .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_COLOR .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_TEX .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_TEX_COLOR .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_COLOR_TEX_LIGHT .drawBuffers (LayerDrawType.ALL); CoreBuffers.ENTITY .clearBuffers (); CoreBuffers.BLOCK .clearBuffers (); CoreBuffers.POS .clearBuffers (); CoreBuffers.POS_COLOR .clearBuffers (); CoreBuffers.POS_TEX .clearBuffers (); CoreBuffers.POS_TEX_COLOR .clearBuffers (); CoreBuffers.POS_COLOR_TEX_LIGHT .clearBuffers (); } @Inject( method = "renderLevel", at = @At( value = "CONSTANT", args = "stringValue=translucent", ordinal = 1 ) ) public void drawIrisOpaqueCoreBuffers( DeltaTracker pDeltaTracker, boolean pRenderBlockOutline, Camera pCamera, GameRenderer pGameRenderer, LightTexture pLightTexture, Matrix4f pFrustumMatrix, Matrix4f pProjectionMatrix, CallbackInfo ci ) { CoreStates .recordBuffers (); CoreBuffers.ENTITY .prepareBuffers (); CoreBuffers.BLOCK .prepareBuffers (); CoreBuffers.POS .prepareBuffers (); CoreBuffers.POS_COLOR .prepareBuffers (); CoreBuffers.POS_TEX .prepareBuffers (); CoreBuffers.POS_TEX_COLOR .prepareBuffers (); CoreBuffers.POS_COLOR_TEX_LIGHT .prepareBuffers (); CoreStates .restoreBuffers (); CoreBuffers.ENTITY .drawBuffers (LayerDrawType.OPAQUE); CoreBuffers.BLOCK .drawBuffers (LayerDrawType.OPAQUE); CoreBuffers.POS .drawBuffers (LayerDrawType.OPAQUE); CoreBuffers.POS_COLOR .drawBuffers (LayerDrawType.OPAQUE); CoreBuffers.POS_TEX .drawBuffers (LayerDrawType.OPAQUE); CoreBuffers.POS_TEX_COLOR .drawBuffers (LayerDrawType.OPAQUE); CoreBuffers.POS_COLOR_TEX_LIGHT .drawBuffers (LayerDrawType.OPAQUE); } @Inject( method = "renderLevel", at = @At( value = "CONSTANT", args = "stringValue=translucent", ordinal = 1, shift = At.Shift.AFTER ) ) public void drawIrisTranslucentCoreBuffers( DeltaTracker pDeltaTracker, boolean pRenderBlockOutline, Camera pCamera, GameRenderer pGameRenderer, LightTexture pLightTexture, Matrix4f pFrustumMatrix, Matrix4f pProjectionMatrix, CallbackInfo ci ) { CoreBuffers.ENTITY .drawBuffers (LayerDrawType.TRANSLUCENT); CoreBuffers.BLOCK .drawBuffers (LayerDrawType.TRANSLUCENT); CoreBuffers.POS .drawBuffers (LayerDrawType.TRANSLUCENT); CoreBuffers.POS_COLOR .drawBuffers (LayerDrawType.TRANSLUCENT); CoreBuffers.POS_TEX .drawBuffers (LayerDrawType.TRANSLUCENT); CoreBuffers.POS_TEX_COLOR .drawBuffers (LayerDrawType.TRANSLUCENT); CoreBuffers.POS_COLOR_TEX_LIGHT .drawBuffers (LayerDrawType.TRANSLUCENT); CoreBuffers.ENTITY .clearBuffers (); CoreBuffers.BLOCK .clearBuffers (); CoreBuffers.POS .clearBuffers (); CoreBuffers.POS_COLOR .clearBuffers (); CoreBuffers.POS_TEX .clearBuffers (); CoreBuffers.POS_TEX_COLOR .clearBuffers (); CoreBuffers.POS_COLOR_TEX_LIGHT .clearBuffers (); } @WrapOperation( method = "renderLevel", at = @At( value = "INVOKE", target = "Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;endLastBatch()V" ) ) public void preventDrawVanillaCoreBuffers(MultiBufferSource.BufferSource instance, Operation original) { instance.endLastBatch(); } @Inject( method = "close", at = @At("TAIL") ) public void deleteIrisBuffers(CallbackInfo ci) { IrisCompatBuffers.BLOCK_SHADOW .delete(); IrisCompatBuffers.ENTITY_SHADOW .delete(); IrisCompatBuffers.GLYPH_SHADOW .delete(); IrisCompatBuffers.POS_TEX_SHADOW .delete(); IrisCompatBuffers.POS_TEX_COLOR_SHADOW .delete(); IrisCompatBuffers.ENTITY_HAND .delete(); IrisCompatBuffers.BLOCK_HAND .delete(); IrisCompatBuffers.POS_HAND .delete(); IrisCompatBuffers.POS_COLOR_HAND .delete(); IrisCompatBuffers.POS_TEX_HAND .delete(); IrisCompatBuffers.POS_TEX_COLOR_HAND .delete(); IrisCompatBuffers.POS_COLOR_TEX_LIGHT_HAND .delete(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/programs/IrisPrograms.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.programs; import com.github.argon4w.acceleratedrendering.compat.iris.programs.culling.IrisCullingProgramSelector; import com.github.argon4w.acceleratedrendering.compat.iris.programs.processing.IrisPolygonProcessor; import com.github.argon4w.acceleratedrendering.core.backends.programs.BarrierFlags; import com.github.argon4w.acceleratedrendering.core.programs.LoadComputeShaderEvent; import com.github.argon4w.acceleratedrendering.core.programs.culling.LoadCullingProgramSelectorEvent; import com.github.argon4w.acceleratedrendering.core.programs.processing.LoadPolygonProcessorEvent; import com.github.argon4w.acceleratedrendering.core.utils.ResourceLocationUtils; import net.irisshaders.iris.vertices.IrisVertexFormats; import net.minecraft.resources.ResourceLocation; import net.neoforged.bus.api.SubscribeEvent; public class IrisPrograms { public static final ResourceLocation IRIS_BLOCK_VERTEX_TRANSFORM_KEY = ResourceLocationUtils.create("compat_block_vertex_transform_iris"); public static final ResourceLocation IRIS_ENTITY_VERTEX_TRANSFORM_KEY = ResourceLocationUtils.create("compat_entity_vertex_transform_iris"); public static final ResourceLocation IRIS_GLYPH_VERTEX_TRANSFORM_KEY = ResourceLocationUtils.create("compat_glyph_vertex_transform_iris"); public static final ResourceLocation IRIS_BLOCK_QUAD_CULLING_KEY = ResourceLocationUtils.create("compat_block_quad_cull_iris"); public static final ResourceLocation IRIS_BLOCK_TRIANGLE_CULLING_KEY = ResourceLocationUtils.create("compat_block_triangle_cull_iris"); public static final ResourceLocation IRIS_ENTITY_QUAD_CULLING_KEY = ResourceLocationUtils.create("compat_entity_quad_cull_iris"); public static final ResourceLocation IRIS_ENTITY_TRIANGLE_CULLING_KEY = ResourceLocationUtils.create("compat_entity_triangle_cull_iris"); public static final ResourceLocation IRIS_BLOCK_QUAD_PROCESSING_KEY = ResourceLocationUtils.create("compat_block_quad_processing_iris"); public static final ResourceLocation IRIS_BLOCK_TRIANGLE_PROCESSING_KEY = ResourceLocationUtils.create("compat_block_triangle_processing_iris"); public static final ResourceLocation IRIS_ENTITY_QUAD_PROCESSING_KEY = ResourceLocationUtils.create("compat_entity_quad_processing_iris"); public static final ResourceLocation IRIS_ENTITY_TRIANGLE_PROCESSING_KEY = ResourceLocationUtils.create("compat_entity_triangle_processing_iris"); public static final ResourceLocation IRIS_GLYPH_QUAD_PROCESSING_KEY = ResourceLocationUtils.create("compat_glyph_quad_processing_iris"); public static final ResourceLocation IRIS_GLYPH_TRIANGLE_PROCESSING_KEY = ResourceLocationUtils.create("compat_glyph_triangle_processing_iris"); public static final ResourceLocation IRIS_BLOCK_MESH_UPLOADING_KEY = ResourceLocationUtils.create("compat_block_mesh_uploading_iris"); public static final ResourceLocation IRIS_ENTITY_MESH_UPLOADING_KEY = ResourceLocationUtils.create("compat_entity_mesh_uploading_iris"); public static final ResourceLocation IRIS_GLYPH_MESH_UPLOADING_KEY = ResourceLocationUtils.create("compat_glyph_mesh_uploading_iris"); @SubscribeEvent public static void onLoadComputeShaders(LoadComputeShaderEvent event) { event.loadComputeShader( IRIS_BLOCK_VERTEX_TRANSFORM_KEY, ResourceLocationUtils .create("shaders/compat/transform/iris_block_vertex_transform_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( IRIS_ENTITY_VERTEX_TRANSFORM_KEY, ResourceLocationUtils .create("shaders/compat/transform/iris_entity_vertex_transform_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( IRIS_GLYPH_VERTEX_TRANSFORM_KEY, ResourceLocationUtils .create("shaders/compat/transform/iris_glyph_vertex_transform_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( IRIS_BLOCK_QUAD_CULLING_KEY, ResourceLocationUtils .create("shaders/compat/culling/iris_block_quad_culling_shader.compute"), BarrierFlags .SHADER_STORAGE, BarrierFlags .ATOMIC_COUNTER ); event.loadComputeShader( IRIS_BLOCK_TRIANGLE_CULLING_KEY, ResourceLocationUtils .create("shaders/compat/culling/iris_block_triangle_culling_shader.compute"), BarrierFlags .SHADER_STORAGE, BarrierFlags .ATOMIC_COUNTER ); event.loadComputeShader( IRIS_ENTITY_QUAD_CULLING_KEY, ResourceLocationUtils .create("shaders/compat/culling/iris_entity_quad_culling_shader.compute"), BarrierFlags .SHADER_STORAGE, BarrierFlags .ATOMIC_COUNTER ); event.loadComputeShader( IRIS_ENTITY_TRIANGLE_CULLING_KEY, ResourceLocationUtils .create("shaders/compat/culling/iris_entity_triangle_culling_shader.compute"), BarrierFlags .SHADER_STORAGE, BarrierFlags .ATOMIC_COUNTER ); event.loadComputeShader( IRIS_BLOCK_QUAD_PROCESSING_KEY, ResourceLocationUtils .create("shaders/compat/processing/iris_block_quad_processing_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( IRIS_BLOCK_TRIANGLE_PROCESSING_KEY, ResourceLocationUtils .create("shaders/compat/processing/iris_block_triangle_processing_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( IRIS_ENTITY_QUAD_PROCESSING_KEY, ResourceLocationUtils .create("shaders/compat/processing/iris_entity_quad_processing_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( IRIS_ENTITY_TRIANGLE_PROCESSING_KEY, ResourceLocationUtils .create("shaders/compat/processing/iris_entity_triangle_processing_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( IRIS_GLYPH_QUAD_PROCESSING_KEY, ResourceLocationUtils .create("shaders/compat/processing/iris_glyph_quad_processing_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( IRIS_GLYPH_TRIANGLE_PROCESSING_KEY, ResourceLocationUtils .create("shaders/compat/processing/iris_glyph_triangle_processing_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( IRIS_BLOCK_MESH_UPLOADING_KEY, ResourceLocationUtils .create("shaders/compat/uploading/iris_block_mesh_uploading_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( IRIS_ENTITY_MESH_UPLOADING_KEY, ResourceLocationUtils .create("shaders/compat/uploading/iris_entity_mesh_uploading_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( IRIS_GLYPH_MESH_UPLOADING_KEY, ResourceLocationUtils .create("shaders/compat/uploading/iris_glyph_mesh_uploading_shader.compute"), BarrierFlags .SHADER_STORAGE ); } @SubscribeEvent public static void onLoadCullingPrograms(LoadCullingProgramSelectorEvent event) { event.loadFor(IrisVertexFormats.TERRAIN, parent -> new IrisCullingProgramSelector( parent, IRIS_BLOCK_QUAD_CULLING_KEY, IRIS_BLOCK_TRIANGLE_CULLING_KEY )); event.loadFor(IrisVertexFormats.ENTITY, parent -> new IrisCullingProgramSelector( parent, IRIS_ENTITY_QUAD_CULLING_KEY, IRIS_ENTITY_TRIANGLE_CULLING_KEY )); } @SubscribeEvent public static void onLoadPolygonProcessors(LoadPolygonProcessorEvent event) { event.loadFor(IrisVertexFormats.TERRAIN, parent -> new IrisPolygonProcessor( parent, IRIS_BLOCK_QUAD_PROCESSING_KEY, IRIS_BLOCK_TRIANGLE_PROCESSING_KEY )); event.loadFor(IrisVertexFormats.ENTITY, parent -> new IrisPolygonProcessor( parent, IRIS_ENTITY_QUAD_PROCESSING_KEY, IRIS_ENTITY_TRIANGLE_PROCESSING_KEY )); event.loadFor(IrisVertexFormats.GLYPH, parent -> new IrisPolygonProcessor( parent, IRIS_GLYPH_QUAD_PROCESSING_KEY, IRIS_GLYPH_TRIANGLE_PROCESSING_KEY )); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/programs/culling/IrisCullingProgramDispatcher.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.programs.culling; import com.github.argon4w.acceleratedrendering.compat.iris.IrisCompatFeature; import com.github.argon4w.acceleratedrendering.core.backends.programs.ComputeProgram; import com.github.argon4w.acceleratedrendering.core.backends.programs.Uniform; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder; import com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderProgramLoader; import com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramDispatcher; import com.github.argon4w.acceleratedrendering.features.culling.OrientationCullingFeature; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.VertexFormat; import net.irisshaders.iris.shadows.ShadowRenderer; import net.irisshaders.iris.shadows.ShadowRenderingState; import net.minecraft.resources.ResourceLocation; public class IrisCullingProgramDispatcher implements ICullingProgramDispatcher { private static final int GROUP_SIZE = 128; private static final int DISPATCH_COUNT_Y_Z = 1; private final VertexFormat.Mode mode; private final ComputeProgram program; private final Uniform viewMatrixUniform; private final Uniform projectMatrixUniform; private final Uniform polygonCountUniform; private final Uniform vertexOffsetUniform; private final Uniform varyingOffsetUniform; public IrisCullingProgramDispatcher(VertexFormat.Mode mode, ResourceLocation key) { this.mode = mode; this.program = ComputeShaderProgramLoader.getProgram(key); this.viewMatrixUniform = this.program .getUniform("viewMatrix"); this.projectMatrixUniform = this.program .getUniform("projectMatrix"); this.polygonCountUniform = this.program .getUniform("polygonCount"); this.vertexOffsetUniform = this.program .getUniform("vertexOffset"); this.varyingOffsetUniform = this.program .getUniform("varyingOffset"); } @Override public int dispatch(AcceleratedBufferBuilder builder) { var shadowState = ShadowRenderingState .areShadowsCurrentlyBeingRendered (); var vertexCount = builder .getTotalVertexCount (); var polygonCount = vertexCount / mode .primitiveLength; viewMatrixUniform .uploadMatrix4f (shadowState ? ShadowRenderer.MODELVIEW : RenderSystem.getModelViewMatrix ()); projectMatrixUniform.uploadMatrix4f (shadowState ? ShadowRenderer.PROJECTION : RenderSystem.getProjectionMatrix ()); polygonCountUniform .uploadUnsignedInt (polygonCount); vertexOffsetUniform .uploadUnsignedInt ((int) (builder.getVertexBuffer ().getOffset() / builder.getVertexSize ())); varyingOffsetUniform.uploadUnsignedInt ((int) (builder.getVaryingBuffer().getOffset() / builder.getVaryingSize ())); program.useProgram (); program.dispatch ( (polygonCount + GROUP_SIZE - 1) / GROUP_SIZE, DISPATCH_COUNT_Y_Z, DISPATCH_COUNT_Y_Z ); return program.getBarrierFlags(); } @Override public boolean shouldCull() { return OrientationCullingFeature.shouldCull() && ( IrisCompatFeature.isShadowCullingEnabled() || !ShadowRenderingState.areShadowsCurrentlyBeingRendered()); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/programs/culling/IrisCullingProgramSelector.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.programs.culling; import com.github.argon4w.acceleratedrendering.compat.iris.IrisCompatFeature; import com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramSelector; import com.github.argon4w.acceleratedrendering.core.utils.RenderTypeUtils; import com.github.argon4w.acceleratedrendering.features.culling.OrientationCullingFeature; import com.mojang.blaze3d.vertex.VertexFormat; import net.irisshaders.iris.shadows.ShadowRenderingState; import net.minecraft.client.renderer.RenderType; import net.minecraft.resources.ResourceLocation; public class IrisCullingProgramSelector implements ICullingProgramSelector { private final ICullingProgramSelector parent; private final ICullingProgramDispatcher quadDispatcher; private final ICullingProgramDispatcher triangleDispatcher; public IrisCullingProgramSelector( ICullingProgramSelector parent, ResourceLocation quadProgramKey, ResourceLocation triangleProgramKey ) { this.parent = parent; this.quadDispatcher = new IrisCullingProgramDispatcher(VertexFormat.Mode.QUADS, quadProgramKey); this.triangleDispatcher = new IrisCullingProgramDispatcher(VertexFormat.Mode.TRIANGLES, triangleProgramKey); } @Override public ICullingProgramDispatcher select(RenderType renderType) { if ( IrisCompatFeature .isEnabled () && IrisCompatFeature .isIrisCompatCullingEnabled () && ( IrisCompatFeature .isShadowCullingEnabled () || ! ShadowRenderingState.areShadowsCurrentlyBeingRendered()) && OrientationCullingFeature .isEnabled () && ( OrientationCullingFeature .shouldIgnoreCullState () || RenderTypeUtils .isCulled(renderType)) ) { return switch (renderType.mode) { case QUADS -> quadDispatcher; case TRIANGLES -> triangleDispatcher; default -> parent.select(renderType); }; } return parent.select(renderType); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/compat/iris/programs/processing/IrisPolygonProcessor.java ================================================ package com.github.argon4w.acceleratedrendering.compat.iris.programs.processing; import com.github.argon4w.acceleratedrendering.compat.iris.IrisCompatFeature; import com.github.argon4w.acceleratedrendering.core.programs.dispatchers.FixedPolygonProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.programs.dispatchers.IPolygonProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.programs.processing.IPolygonProcessor; import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.resources.ResourceLocation; public class IrisPolygonProcessor implements IPolygonProcessor { private final IPolygonProcessor parent; private final IPolygonProgramDispatcher quadDispatcher; private final IPolygonProgramDispatcher triangleDispatcher; public IrisPolygonProcessor( IPolygonProcessor parent, ResourceLocation quadProgramKey, ResourceLocation triangleProgramKey ) { this.parent = parent; this.quadDispatcher = new FixedPolygonProgramDispatcher (VertexFormat.Mode.QUADS, quadProgramKey); this.triangleDispatcher = new FixedPolygonProgramDispatcher (VertexFormat.Mode.TRIANGLES, triangleProgramKey); } @Override public IPolygonProgramDispatcher select(VertexFormat.Mode mode) { if ( IrisCompatFeature .isEnabled () && IrisCompatFeature .isPolygonProcessingEnabled () ) { return switch (mode) { case QUADS -> quadDispatcher; case TRIANGLES -> triangleDispatcher; default -> parent.select(mode); }; } return parent.select(mode); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/configs/FeatureConfig.java ================================================ package com.github.argon4w.acceleratedrendering.configs; import com.github.argon4w.acceleratedrendering.core.backends.states.buffers.BlockBufferBindingStateType; import com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache.BlockBufferBindingCacheType; import com.github.argon4w.acceleratedrendering.core.backends.states.scissors.ScissorBindingStateType; import com.github.argon4w.acceleratedrendering.core.backends.states.viewports.ViewportBindingStateType; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.LayerStorageType; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.MeshInfoCacheType; import com.github.argon4w.acceleratedrendering.core.meshes.MeshType; import com.github.argon4w.acceleratedrendering.core.meshes.data.cache.MeshDataCacheType; import com.github.argon4w.acceleratedrendering.features.filter.FilterType; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.neoforged.neoforge.common.ModConfigSpec; import org.apache.commons.lang3.tuple.Pair; import java.util.List; public class FeatureConfig { public static final FeatureConfig CONFIG; public static final ModConfigSpec SPEC; public final ModConfigSpec.IntValue corePooledRingBufferSize; public final ModConfigSpec.IntValue corePooledBatchingSize; public final ModConfigSpec.IntValue coreCachedImageSize; public final ModConfigSpec.IntValue coreDynamicUVResolution; public final ModConfigSpec.ConfigValue coreDebugContextEnabled; public final ModConfigSpec.ConfigValue coreForceTranslucentAcceleration; public final ModConfigSpec.ConfigValue coreCacheIdenticalPose; public final ModConfigSpec.ConfigValue coreMeshInfoCacheType; public final ModConfigSpec.ConfigValue coreLayerStorageType; public final ModConfigSpec.ConfigValue coreMeshMergeType; public final ModConfigSpec.ConfigValue coreUploadMeshImmediately; public final ModConfigSpec.ConfigValue coreCacheDynamicRenderType; public final ModConfigSpec.ConfigValue coreViewportBindingType; public final ModConfigSpec.ConfigValue coreScissorBindingType; public final ModConfigSpec.ConfigValue restoringFeatureStatus; public final ModConfigSpec.ConfigValue restoringBindingCacheType; public final ModConfigSpec.ConfigValue restoringShaderStorageType; public final ModConfigSpec.ConfigValue restoringAtomicCounterType; public final ModConfigSpec.IntValue restoringShaderStorageRange; public final ModConfigSpec.IntValue restoringAtomicCounterRange; public final ModConfigSpec.ConfigValue acceleratedEntityRenderingFeatureStatus; public final ModConfigSpec.ConfigValue acceleratedEntityRenderingDefaultPipeline; public final ModConfigSpec.ConfigValue acceleratedEntityRenderingMeshType; public final ModConfigSpec.ConfigValue acceleratedEntityRenderingGuiAcceleration; public final ModConfigSpec.ConfigValue acceleratedTextRenderingFeatureStatus; public final ModConfigSpec.ConfigValue acceleratedTextRenderingDefaultPipeline; public final ModConfigSpec.ConfigValue acceleratedTextRenderingMeshType; public final ModConfigSpec.ConfigValue acceleratedItemRenderingFeatureStatus; public final ModConfigSpec.ConfigValue acceleratedItemRenderingBakeMeshForQuads; public final ModConfigSpec.ConfigValue acceleratedItemRenderingDefaultPipeline; public final ModConfigSpec.ConfigValue acceleratedItemRenderingMeshType; public final ModConfigSpec.ConfigValue acceleratedItemRenderingHandAcceleration; public final ModConfigSpec.ConfigValue acceleratedItemRenderingGuiAcceleration; public final ModConfigSpec.ConfigValue acceleratedItemRenderingGuiItemBatching; public final ModConfigSpec.ConfigValue acceleratedItemRenderingMergeGuiItemBatches; public final ModConfigSpec.ConfigValue orientationCullingFeatureStatus; public final ModConfigSpec.ConfigValue orientationCullingDefaultCulling; public final ModConfigSpec.ConfigValue orientationCullingIgnoreCullState; public final ModConfigSpec.ConfigValue filterFeatureStatus; public final ModConfigSpec.ConfigValue filterMenuFilter; public final ModConfigSpec.ConfigValue filterEntityFilter; public final ModConfigSpec.ConfigValue filterBlockEntityFilter; public final ModConfigSpec.ConfigValue filterItemFilter; public final ModConfigSpec.ConfigValue filterStageFilter; public final ModConfigSpec.ConfigValue filterMenuFilterType; public final ModConfigSpec.ConfigValue filterEntityFilterType; public final ModConfigSpec.ConfigValue filterBlockEntityFilterType; public final ModConfigSpec.ConfigValue filterItemFilterType; public final ModConfigSpec.ConfigValue filterStageFilterType; public final ModConfigSpec.ConfigValue> filterMenuFilterValues; public final ModConfigSpec.ConfigValue> filterEntityFilterValues; public final ModConfigSpec.ConfigValue> filterBlockEntityFilterValues; public final ModConfigSpec.ConfigValue> filterItemFilterValues; public final ModConfigSpec.ConfigValue> filterStageFilterValues; public final ModConfigSpec.ConfigValue irisCompatFeatureStatus; public final ModConfigSpec.ConfigValue irisCompatOrientationCullingCompat; public final ModConfigSpec.ConfigValue irisCompatShadowCulling; public final ModConfigSpec.ConfigValue irisCompatPolygonProcessing; public final ModConfigSpec.ConfigValue curiosCompatFeatureStatus; public final ModConfigSpec.ConfigValue curiosCompatLayerAcceleration; public final ModConfigSpec.ConfigValue curiosItemFilter; public final ModConfigSpec.ConfigValue curiosItemFilterType; public final ModConfigSpec.ConfigValue> curiosItemFilterValues; static { Pair pair = new ModConfigSpec.Builder() .configure (FeatureConfig::new); CONFIG = pair .getLeft (); SPEC = pair .getRight (); } private FeatureConfig(ModConfigSpec.Builder builder) { builder .comment ("Core Settings") .comment ("Core Settings allows you to change setting that are related to all rendering features.") .translation ("acceleratedrendering.configuration.core_settings") .push ("core_settings"); corePooledRingBufferSize = builder .gameRestart () .comment ("Count of buffer sets that holds data for in-flight frame rendering.") .comment ("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.") .translation ("acceleratedrendering.configuration.core_settings.pooled_ring_buffer_size") .defineInRange ("pooled_ring_buffer_size", 8, 1, Integer.MAX_VALUE); corePooledBatchingSize = builder .gameRestart () .comment ("Count of batches of RenderTypes that is allowed in a draw call.") .comment ("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.") .translation ("acceleratedrendering.configuration.core_settings.pooled_batching_size") .defineInRange ("pooled_batching_size", 32, 1, Integer.MAX_VALUE); coreCachedImageSize = builder .comment ("Count of images that cached for static mesh culling.") .comment ("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.") .translation ("acceleratedrendering.configuration.core_settings.cached_image_size") .defineInRange ("cached_image_size", 32, 1, Integer.MAX_VALUE); coreDynamicUVResolution = builder .comment ("Resolution of UV scrolling in caching dynamic render types.") .comment ("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.") .translation ("acceleratedrendering.configuration.core_settings.dynamic_uv_resolution") .defineInRange ("dynamic_uv_resolution", 64, 1, Integer.MAX_VALUE); coreDebugContextEnabled = builder .comment ("- DISABLED: Debug context will be disabled, which may cause significant rendering glitches on some NVIDIA cards because of the \"theaded optimization\".") .comment ("- ENABLED: Debug context will be enabled, which can prevent NVIDIA driver from applying the \"threaded optimization\" that causes the glitches.") .translation ("acceleratedrendering.configuration.core_settings.debug_context") .gameRestart () .defineEnum ("debug_context", FeatureStatus.ENABLED); coreForceTranslucentAcceleration = builder .comment ("- 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.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.core_settings.force_translucent_acceleration") .defineEnum ("force_translucent_acceleration", FeatureStatus.ENABLED); coreCacheIdenticalPose = builder .comment ("- 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.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.core_settings.cache_identical_pose") .defineEnum ("cache_identical_pose", FeatureStatus.ENABLED); coreMeshInfoCacheType = builder .comment ("- SIMPLE: The most basic implementation of cache. Usually used for testing if other cache types are working correctly.") .comment ("- HANDLE: Faster implementation of cache using VarHandle and flatten values to improve performance on read/write operations.") .comment ("- UNSAFE: Fastest implementation of cache using unsafe memory operations that skip multiple safety checks to read/write.") .translation ("acceleratedrendering.configuration.core_settings.mesh_info_cache_type") .gameRestart () .defineEnum ("mesh_info_cache_type", MeshInfoCacheType.HANDLE); coreLayerStorageType = builder .comment ("- 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.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.core_settings.layer_storage_type") .gameRestart () .defineEnum ("layer_storage_type", LayerStorageType.SEPARATED); coreMeshMergeType = builder .comment ("- IGNORED: Meshes with identical vertices will not be merged, which will use less RAM but more VRAM in storing duplicated meshes.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.core_settings.mesh_merge_type") .gameRestart () .defineEnum ("mesh_merge_type", MeshDataCacheType.MERGED); coreUploadMeshImmediately = builder .comment ("- 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.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.core_settings.upload_mesh_immediately") .defineEnum ("upload_mesh_immediately", FeatureStatus.DISABLED); coreCacheDynamicRenderType = builder .comment ("- 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.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.core_settings.cache_dynamic_render_type") .defineEnum ("cache_dynamic_render_type", FeatureStatus.ENABLED); coreViewportBindingType = builder .comment ("- 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.") .comment ("- MOJANG: Viewport settings that will be modified by other mods will be recorded and restored using Mojang's GLStateManager to work correctly with them.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.core_settings.viewport_binding_state") .gameRestart () .defineEnum ("viewport_binding_state", ViewportBindingStateType.IGNORED); coreScissorBindingType = builder .comment ("- 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.") .comment ("- MOJANG: Scissor settings that will be modified by other mods will be recorded and restored using Mojang's GuiGraphics to work correctly with them.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.core_settings.scissor_binding_state") .gameRestart () .defineEnum ("scissor_binding_state", ScissorBindingStateType.MOJANG); builder .comment ("Block Buffer Restoring Settings") .comment ("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.") .comment ("Block Buffer Restoring can record the binding of block buffers before the acceleration and restore them after the acceleration to work correctly with them.") .translation ("acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring") .push ("block_buffer_binding_restoring"); restoringFeatureStatus = builder .comment ("- DISABLED: Disable block buffer restoring, which is faster but may cause visual glitches with mods and shaders that uses block buffers.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.feature_status") .defineEnum ("feature_status", FeatureStatus.ENABLED); restoringBindingCacheType = builder .comment ("- SIMPLE: The most basic implementation of cache. Usually used for testing if other cache types are working properly.") .comment ("- HANDLE: Faster implementation of cache using VarHandle and flatten values to improve performance on read/write operations.") .comment ("- UNSAFE: Fastest implementation of cache using unsafe memory operations that skip multiple safety checks to read/write.") .translation ("acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.binding_cache_type") .gameRestart () .defineEnum ("binding_cache_type", BlockBufferBindingCacheType.HANDLE); restoringShaderStorageType = builder .comment ("- IGNORED: Shader storage buffers will not be restored which improves FPS but reduces compatibility with mods and shaders that ues shader storage buffers.") .comment ("- RESTORED: Shader storage buffers will be restored, which is slight slower but has better compatibility with mods and shaders that ues shader storage buffers.") .translation ("acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.shader_storage_type") .gameRestart () .defineEnum ("shader_storage_type", BlockBufferBindingStateType.RESTORED); restoringAtomicCounterType = builder .comment ("- IGNORED: Atomic counter buffers will not be restored which improves FPS but reduces compatibility with mods and shaders that ues atomic counter buffers.") .comment ("- RESTORED: Atomic counter buffers will be restored, which is slight slower but has better compatibility with mods and shaders that ues atomic counter buffers.") .translation ("acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.atomic_counter_type") .gameRestart () .defineEnum ("atomic_counter_type", BlockBufferBindingStateType.RESTORED); restoringShaderStorageRange = builder .comment ("Range of shader storage buffer bindings that will be restored.") .comment ("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.") .translation ("acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.shader_storage_range") .gameRestart () .defineInRange ("shader_storage_range", 9, 0, 9); restoringAtomicCounterRange = builder .comment ("Range of atomic counter buffer bindings that will be restored.") .comment ("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.") .translation ("acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.atomic_counter_range") .gameRestart () .defineInRange ("atomic_counter_range", 1, 0, 1); builder.pop(); builder.pop(); builder .comment ("Accelerated Entity Rendering Settings") .comment ("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.") .translation ("acceleratedrendering.configuration.accelerated_entity_rendering") .push ("accelerated_entity_rendering"); acceleratedEntityRenderingFeatureStatus = builder .comment ("- DISABLED: Disable accelerated entity rendering.") .comment ("- ENABLED: Enable accelerated entity rendering.") .translation ("acceleratedrendering.configuration.accelerated_entity_rendering.feature_status") .defineEnum ("feature_status", FeatureStatus.ENABLED); acceleratedEntityRenderingDefaultPipeline = builder .comment ("- VANILLA: Entities will not be rendered into the accelerated pipeline unless mods explicitly enable it temporarily when rendering their own entities.") .comment ("- ACCELERATED: All entities will be rendered in the accelerated pipeline unless mods explicitly disable it temporarily when rendering their own entities.") .translation ("acceleratedrendering.configuration.accelerated_entity_rendering.default_pipeline") .defineEnum ("default_pipeline", PipelineSetting.ACCELERATED); acceleratedEntityRenderingMeshType = builder .gameRestart () .comment ("- 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.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.accelerated_entity_rendering.mesh_type") .defineEnum ("mesh_type", MeshType.SERVER); acceleratedEntityRenderingGuiAcceleration = builder .comment ("- DISABLED: Accelerated Rendering will not accelerate entities when rendering it in a GUI unless mods explicitly enable it temporarily when rendering their own entities.") .comment ("- ENABLED: Accelerated Rendering will still accelerate entities when rendering it in a GUI unless mods explicitly disable it temporarily when rendering their own entities.") .translation ("acceleratedrendering.configuration.accelerated_entity_rendering.gui_acceleration") .defineEnum ("gui_acceleration", FeatureStatus.ENABLED); builder.pop(); builder .comment ("Accelerated Item Rendering Settings") .comment ("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.") .translation ("acceleratedrendering.configuration.accelerated_item_rendering") .push ("accelerated_item_rendering"); acceleratedItemRenderingFeatureStatus = builder .comment ("- DISABLED: Disable accelerated item rendering.") .comment ("- ENABLED: Enable accelerated item rendering.") .translation ("acceleratedrendering.configuration.accelerated_item_rendering.feature_status") .defineEnum ("feature_status", FeatureStatus.ENABLED); acceleratedItemRenderingBakeMeshForQuads = builder .comment ("- 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.") .comment ("- 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?)") .translation ("acceleratedrendering.configuration.accelerated_item_rendering.bake_mesh_for_quads") .defineEnum ("bake_mesh_for_quads", FeatureStatus.ENABLED); acceleratedItemRenderingDefaultPipeline = builder .comment ("- VANILLA: Item models will not be rendered into the accelerated pipeline unless mods explicitly enable it temporarily when rendering their own item models.") .comment ("- ACCELERATED: All item models will be rendered in the accelerated pipeline unless mods explicitly disable it temporarily when rendering their own item models.") .translation ("acceleratedrendering.configuration.accelerated_item_rendering.default_pipeline") .defineEnum ("default_pipeline", PipelineSetting.ACCELERATED); acceleratedItemRenderingMeshType = builder .gameRestart () .comment ("- 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.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.accelerated_item_rendering.mesh_type") .defineEnum ("mesh_type", MeshType.SERVER); acceleratedItemRenderingHandAcceleration = builder .comment ("- 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.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.accelerated_item_rendering.hand_acceleration") .defineEnum ("hand_acceleration", FeatureStatus.ENABLED); acceleratedItemRenderingGuiAcceleration = builder .comment ("- 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.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.accelerated_item_rendering.gui_acceleration") .defineEnum ("gui_acceleration", FeatureStatus.ENABLED); acceleratedItemRenderingGuiItemBatching = builder .comment ("- 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.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.accelerated_item_rendering.gui_item_batching") .defineEnum ("gui_item_batching", FeatureStatus.ENABLED); acceleratedItemRenderingMergeGuiItemBatches = builder .comment ("- 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.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.accelerated_item_rendering.merge_gui_item_batching") .defineEnum ("merge_gui_item_batching", FeatureStatus.ENABLED); builder.pop(); builder .comment ("Accelerated Text Rendering Settings") .comment ("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.") .translation ("acceleratedrendering.configuration.accelerated_text_rendering") .push ("accelerated_text_rendering"); acceleratedTextRenderingFeatureStatus = builder .comment ("- DISABLED: Disable accelerated text rendering.") .comment ("- ENABLED: Enable accelerated text rendering.") .translation ("acceleratedrendering.configuration.accelerated_text_rendering.feature_status") .defineEnum ("feature_status", FeatureStatus.ENABLED); acceleratedTextRenderingDefaultPipeline = builder .comment ("- VANILLA: Text will not be rendered into the accelerated pipeline unless mods explicitly enable it temporarily when rendering their own text.") .comment ("- ACCELERATED: All text will be rendered in the accelerated pipeline unless mods explicitly disable it temporarily when rendering their own text.") .translation ("acceleratedrendering.configuration.accelerated_text_rendering.default_pipeline") .defineEnum ("default_pipeline", PipelineSetting.ACCELERATED); acceleratedTextRenderingMeshType = builder .gameRestart () .comment ("- 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.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.accelerated_text_rendering.mesh_type") .defineEnum ("mesh_type", MeshType.SERVER); builder.pop(); builder .comment ("Simple Orientation Face Culling Settings") .comment ("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.") .translation ("acceleratedrendering.configuration.orientation_culling") .push ("orientation_culling"); orientationCullingFeatureStatus = builder .comment ("- DISABLED: Disable simple orientation face culling.") .comment ("- ENABLED: Enable simple orientation face culling.") .translation ("acceleratedrendering.configuration.orientation_culling.feature_status") .defineEnum ("feature_Status", FeatureStatus.ENABLED); orientationCullingDefaultCulling = builder .comment ("- DISABLED: Faces will not be culled unless mods explicitly enable it temporarily when rendering their own faces.") .comment ("- ENABLED: All faces will be culled unless mods explicitly disable it temporarily when rendering their own faces.") .translation ("acceleratedrendering.configuration.orientation_culling.default_culling") .defineEnum ("default_culling", FeatureStatus.ENABLED); orientationCullingIgnoreCullState = builder .comment ("- DISABLED: Simple orientation face culling will not cull entities that are not declared as \"cullable\".") .comment ("- ENABLED: Simple orientation face culling will cull all entities even if they are not declared as \"cullable\".") .translation ("acceleratedrendering.configuration.orientation_culling.ignore_cull_state") .defineEnum ("ignore_cull_state", FeatureStatus.DISABLED); builder.pop(); builder .comment ("Filters Settings") .comment ("Filters allows you to prevent specific entities/block entities/items from being accelerated when rendering for better compatibility.") .translation ("acceleratedrendering.configuration.filter") .push ("filter"); filterFeatureStatus = builder .comment ("- DISABLED: Filters will be disabled and all entities, block entities and items will be accelerated when rendering.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.filter.feature_status") .defineEnum ("feature_status", FeatureStatus.ENABLED); filterMenuFilter = builder .comment ("- DISABLED: Menu filter will be disabled and geometries in all container GUI will be accelerated.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.filter.menu_filter") .defineEnum ("menu_filter", FeatureStatus.ENABLED); filterEntityFilter = builder .comment ("- DISABLED: Entity filter will be disabled and all entities will be accelerated.") .comment ("- ENABLED: Entity filter will test if the entities should be accelerated when rendering based on the filter values and the filter type.") .translation ("acceleratedrendering.configuration.filter.entity_filter") .defineEnum ("entity_filter", FeatureStatus.DISABLED); filterBlockEntityFilter = builder .comment ("- DISABLED: Block entity filter will be disabled and all block entities will be accelerated.") .comment ("- ENABLED: Block entity filter will test if the block entities should be accelerated when rendering based on the filter values and the filter type.") .translation ("acceleratedrendering.configuration.filter.block_entity_filter") .defineEnum ("block_entity_filter", FeatureStatus.DISABLED); filterItemFilter = builder .comment ("- DISABLED: Item filter will be disabled and all items will be accelerated.") .comment ("- ENABLED: Item filter will test if the items should be accelerated when rendering based on the filter values and the filter type.") .translation ("acceleratedrendering.configuration.filter.item_filter") .defineEnum ("item_filter", FeatureStatus.DISABLED); filterStageFilter = builder .comment ("- DISABLED: Custom rendering stage filter will be disabled and geometries in all custom rendering stages will be accelerated.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.filter.stage_filter") .defineEnum ("stage_filter", FeatureStatus.ENABLED); filterMenuFilterType = builder .comment ("- BLACKLIST: Container GUIs that are not in the filter values can pass the filter and be accelerated when rendering.") .comment ("- WHITELIST: Container GUIs that are in the filter values can pass the filter and be accelerated when rendering.") .translation ("acceleratedrendering.configuration.filter.menu_filter_type") .defineEnum ("menu_filter_type", FilterType.WHITELIST); filterEntityFilterType = builder .comment ("- BLACKLIST: Entities that are not in the filter values can pass the filter and be accelerated when rendering.") .comment ("- WHITELIST: Entities that are in the filter values can pass the filter and be accelerated when rendering.") .translation ("acceleratedrendering.configuration.filter.entity_filter_type") .defineEnum ("entity_filter_type", FilterType.BLACKLIST); filterBlockEntityFilterType = builder .comment ("- BLACKLIST: Block entities that are not in the filter values can pass the filter and be accelerated when rendering.") .comment ("- WHITELIST: Block entities that are in the filter values can pass the filter and be accelerated when rendering.") .translation ("acceleratedrendering.configuration.filter.block_entity_filter_type") .defineEnum ("block_entity_filter_type", FilterType.BLACKLIST); filterItemFilterType = builder .comment ("- BLACKLIST: Items that are not in the filter values can pass the filter and be accelerated when rendering.") .comment ("- WHITELIST: Items that are in the filter values can pass the filter and be accelerated when rendering.") .translation ("acceleratedrendering.configuration.filter.item_filter_type") .defineEnum ("item_filter_type", FilterType.BLACKLIST); filterStageFilterType = builder .comment ("- BLACKLIST: Custom rendering stages that are not in the filter values can pass the filter and be accelerated when rendering.") .comment ("- WHITELIST: Custom rendering stages that are in the filter values can pass the filter and be accelerated when rendering.") .translation ("acceleratedrendering.configuration.filter.stage_filter_type") .defineEnum ("stage_filter_type", FilterType.WHITELIST); filterMenuFilterValues = builder .comment ("You can configure the menu filter by this list.") .comment ("Menu filter will use this list and the filter type to determine if a container GUI can pass the filter.") .translation ("acceleratedrendering.configuration.filter.menu_filter_values") .gameRestart () .defineListAllowEmpty ("menu_filter_values", ObjectArrayList.of("minecraft:.*"), () -> "minecraft:empty", object -> object instanceof String); filterEntityFilterValues = builder .comment ("You can configure the entity filter by this list.") .comment ("Entity filter will use this list and the filter type to determine if an entity can pass the filter.") .translation ("acceleratedrendering.configuration.filter.entity_filter_values") .gameRestart () .defineListAllowEmpty ("entity_filter_values", new ObjectArrayList<>(), () -> "minecraft:empty", object -> object instanceof String); filterBlockEntityFilterValues = builder .comment ("You can configure the block entity filter by this list.") .comment ("Block entity filter will use this list and the filter type to determine if a block entity can pass the filter.") .translation ("acceleratedrendering.configuration.filter.block_entity_filter_values") .gameRestart () .defineListAllowEmpty ("block_entity_filter_values", new ObjectArrayList<>(), () -> "minecraft:empty", object -> object instanceof String); filterItemFilterValues = builder .comment ("You can configure the item filter by this list.") .comment ("Item filter will use this list and the filter type to determine if an item can pass the filter.") .translation ("acceleratedrendering.configuration.filter.item_filter_values") .gameRestart () .defineListAllowEmpty ("item_filter_values", new ObjectArrayList<>(), () -> "minecraft:empty", object -> object instanceof String); filterStageFilterValues = builder .comment ("You can configure the custom rendering stage filter by this list.") .comment ("Custom rendering stage filter will use this list and the filter type to determine if a custom rendering stage can pass the filter.") .comment ("It's not recommend to modify this list unless other mods adds their own custom rendering stages.") .translation ("acceleratedrendering.configuration.filter.stage_filter_values") .gameRestart () .defineListAllowEmpty ("stage_filter_values", ObjectArrayList.of("after_entities", "after_block_entities"), () -> "minecraft:empty", object -> object instanceof String); builder.pop(); builder .comment ("Iris Compatibility Settings") .comment ("Iris Compatibility Settings allows Accelerated Rendering to work correctly with Iris.") .translation ("acceleratedrendering.configuration.iris_compatibility") .push ("iris_compatibility"); irisCompatFeatureStatus = builder .comment ("- DISABLED: Accelerated Rendering will be incompatible with Iris and cause visual glitches when working with Iris.") .comment ("- ENABLED: Accelerated Rendering will use compute shaders that fits Iris's vertex formats, which make it compatible with Iris.") .translation ("acceleratedrendering.configuration.iris_compatibility.feature_status") .defineEnum ("feature_status", FeatureStatus.ENABLED); irisCompatOrientationCullingCompat = builder .comment ("- DISABLED: Simple Orientation culling will not work with Iris because the culling shader is for vanilla's vertex formats.") .comment ("- ENABLED: Simple Orientation culling will use another culling shader that fits iris's vertex format, which make it compatible with Iris.") .translation ("acceleratedrendering.configuration.iris_compatibility.orientation_culling_compatibility") .defineEnum ("orientation_culling_compatibility", FeatureStatus.ENABLED); irisCompatShadowCulling = builder .comment ("- 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.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.iris_compatibility.shadow_culling") .defineEnum ("shadow_culling", FeatureStatus.ENABLED); irisCompatPolygonProcessing = builder .comment ("- 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.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.iris_compatibility.polygon_processing") .defineEnum ("polygon_processing", FeatureStatus.ENABLED); builder.pop(); builder .comment ("Curios Compatibility Settings") .comment ("Curios Compatibility Settings allows Accelerated Rendering to work correctly with Curios.") .translation ("acceleratedrendering.configuration.curios_compatibility") .push ("curios_compatibility"); curiosCompatFeatureStatus = builder .comment ("- DISABLED: Accelerated Rendering will not interrupt the acceleration of the Curios layer on entities.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.curios_compatibility.feature_status") .defineEnum ("feature_status", FeatureStatus.ENABLED); curiosCompatLayerAcceleration = builder .comment ("- 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.") .comment ("- ENABLED: Curios layer will be accelerated by default unless mods explicitly enable the acceleration when rendering their accessories or equipments.") .translation ("acceleratedrendering.configuration.curios_compatibility.layer_acceleration") .defineEnum ("layer_acceleration", FeatureStatus.DISABLED); curiosItemFilter = builder .comment ("- 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.") .comment ("- 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.") .translation ("acceleratedrendering.configuration.curios_compatibility.item_filter") .defineEnum ("item_filter", FeatureStatus.DISABLED); curiosItemFilterType = builder .comment ("- BLACKLIST: Curios items that are not in the filter values can pass the filter and not being prevented to be accelerated.") .comment ("- WHITELIST: Curios items that are in the filter values can pass the filter and not being prevented to be accelerated.") .translation ("acceleratedrendering.configuration.curios_compatibility.item_filter_type") .defineEnum ("item_filter_type", FilterType.BLACKLIST); curiosItemFilterValues = builder .comment ("You can configure the curios item filter by this list.") .comment ("Curios item filter will use this list and the filter type to determine if a curios item can pass the filter.") .translation ("acceleratedrendering.configuration.curios_compatibility.item_filter_values") .gameRestart () .defineListAllowEmpty ("item_filter_values", new ObjectArrayList<>(), () -> "minecraft:air", object -> object instanceof String); builder.pop(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/configs/FeatureStatus.java ================================================ package com.github.argon4w.acceleratedrendering.configs; public enum FeatureStatus { DISABLED, ENABLED } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/configs/PipelineSetting.java ================================================ package com.github.argon4w.acceleratedrendering.configs; public enum PipelineSetting { VANILLA, ACCELERATED } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/CoreBuffers.java ================================================ package com.github.argon4w.acceleratedrendering.core; import com.github.argon4w.acceleratedrendering.core.buffers.AcceleratedBufferSources; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.AcceleratedBufferSource; import com.github.argon4w.acceleratedrendering.core.buffers.environments.IBufferEnvironment; import com.mojang.blaze3d.vertex.VertexFormat; public class CoreBuffers { public static final AcceleratedBufferSource BLOCK = new AcceleratedBufferSource(IBufferEnvironment.Presets.BLOCK); public static final AcceleratedBufferSource ENTITY = new AcceleratedBufferSource(IBufferEnvironment.Presets.ENTITY); public static final AcceleratedBufferSource POS = new AcceleratedBufferSource(IBufferEnvironment.Presets.POS); public static final AcceleratedBufferSource POS_COLOR = new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_COLOR); public static final AcceleratedBufferSource POS_TEX = new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_TEX); public static final AcceleratedBufferSource POS_TEX_COLOR = new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_TEX_COLOR); public static final AcceleratedBufferSource POS_COLOR_TEX_LIGHT = new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_COLOR_TEX_LIGHT); public static final AcceleratedBufferSource POS_TEX_COLOR_OUTLINE = new AcceleratedBufferSource(IBufferEnvironment.Presets.POS_TEX_COLOR); public static final AcceleratedBufferSources CORE = AcceleratedBufferSources .builder() .source (CoreBuffers .BLOCK) .source (CoreBuffers .ENTITY) .source (CoreBuffers .POS) .source (CoreBuffers .POS_COLOR) .source (CoreBuffers .POS_TEX) .source (CoreBuffers .POS_TEX_COLOR) .source (CoreBuffers .POS_COLOR_TEX_LIGHT) .mode (VertexFormat.Mode .QUADS) .mode (VertexFormat.Mode .TRIANGLES) .build (); public static final AcceleratedBufferSources OUTLINE = AcceleratedBufferSources .builder() .source (CoreBuffers .POS_TEX_COLOR_OUTLINE) .mode (VertexFormat.Mode .QUADS) .mode (VertexFormat.Mode .TRIANGLES) .build (); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/CoreBuffersProvider.java ================================================ package com.github.argon4w.acceleratedrendering.core; import com.github.argon4w.acceleratedrendering.core.buffers.EmptyAcceleratedBufferSources; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAcceleratedBufferSource; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.BufferSourceExtension; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.RenderBuffers; import java.util.function.Supplier; @ExtensionMethod(BufferSourceExtension.class) public class CoreBuffersProvider { public static final Supplier EMPTY = () -> EmptyAcceleratedBufferSources .INSTANCE; public static final Supplier CORE = () -> CoreBuffers .CORE; public static final Supplier OUTLINE = () -> CoreBuffers .OUTLINE; public static void bindAcceleratedBufferSources(RenderBuffers renderBuffers) { renderBuffers.bufferSource ().getAcceleratable().bindAcceleratedBufferSource(CoreBuffersProvider.CORE); renderBuffers.crumblingBufferSource ().getAcceleratable().bindAcceleratedBufferSource(CoreBuffersProvider.CORE); renderBuffers.outlineBufferSource ().getAcceleratable().bindAcceleratedBufferSource(CoreBuffersProvider.OUTLINE); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/CoreFeature.java ================================================ package com.github.argon4w.acceleratedrendering.core; import com.github.argon4w.acceleratedrendering.configs.FeatureConfig; import com.github.argon4w.acceleratedrendering.configs.FeatureStatus; import com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState; import com.github.argon4w.acceleratedrendering.core.backends.states.buffers.BlockBufferBindingStateType; import com.github.argon4w.acceleratedrendering.core.backends.states.buffers.BufferBlockType; import com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache.BlockBufferBindingCacheType; import com.github.argon4w.acceleratedrendering.core.backends.states.scissors.ScissorBindingStateType; import com.github.argon4w.acceleratedrendering.core.backends.states.viewports.ViewportBindingStateType; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.ILayerStorage; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.LayerStorageType; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.IMeshInfoCache; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.MeshInfoCacheType; import com.github.argon4w.acceleratedrendering.core.meshes.data.cache.IMeshDataCache; import com.github.argon4w.acceleratedrendering.core.meshes.data.cache.MeshDataCacheType; import com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderProgramLoader; import com.github.argon4w.acceleratedrendering.core.utils.PackedVector2i; import com.google.common.util.concurrent.Runnables; import java.util.ArrayDeque; public class CoreFeature { private static final ArrayDeque FORCE_TRANSLUCENT_ACCELERATION_CONTROLLER_STACK = new ArrayDeque<>(); private static final ArrayDeque CACHE_IDENTICAL_POSE_CONTROLLER_STACK = new ArrayDeque<>(); private static final ArrayDeque DEFAULT_LAYER_CONTROLLER_STACK = new ArrayDeque<>(); private static final ArrayDeque DEFAULT_LAYER_BEFORE_FUNCTION_CONTROLLER_STACK = new ArrayDeque<>(); private static final ArrayDeque DEFAULT_LAYER_AFTER_FUNCTION_CONTROLLER_STACK = new ArrayDeque<>(); private static boolean RENDERING_LEVEL = false; private static boolean RENDERING_HAND = false; private static boolean RENDERING_GUI = false; private static boolean GUI_BATCHING = false; public static boolean isLoaded() { return ComputeShaderProgramLoader.isProgramsLoaded(); } public static boolean isConfigLoaded() { return FeatureConfig.SPEC.isLoaded(); } public static boolean isDebugContextEnabled() { return FeatureConfig.CONFIG.coreDebugContextEnabled.get() == FeatureStatus.ENABLED; } public static int getPooledRingBufferSize() { return FeatureConfig.CONFIG.corePooledRingBufferSize.getAsInt(); } public static int getPooledBatchingSize() { return FeatureConfig.CONFIG.corePooledBatchingSize.getAsInt(); } public static int getCachedImageSize() { return FeatureConfig.CONFIG.coreCachedImageSize.getAsInt(); } public static float getDynamicUVResolution() { return FeatureConfig.CONFIG.coreDynamicUVResolution.getAsInt(); } public static boolean shouldForceAccelerateTranslucent() { return getForceTranslucentAccelerationSetting() == FeatureStatus.ENABLED; } public static boolean shouldCacheIdenticalPose() { return getCacheIdenticalPoseSetting() == FeatureStatus.ENABLED; } public static MeshInfoCacheType getMeshInfoCacheType() { return FeatureConfig.CONFIG.coreMeshInfoCacheType.get(); } public static LayerStorageType getLayerStorageType() { return FeatureConfig.CONFIG.coreLayerStorageType.get(); } public static MeshDataCacheType getMeshMergeType() { return FeatureConfig.CONFIG.coreMeshMergeType.get(); } public static boolean shouldUploadMeshImmediately() { return FeatureConfig.CONFIG.coreUploadMeshImmediately.get() == FeatureStatus.ENABLED; } public static boolean shouldCacheDynamicRenderType() { return FeatureConfig.CONFIG.coreCacheDynamicRenderType.get() == FeatureStatus.ENABLED; } public static boolean shouldRestoreBlockBuffers() { return FeatureConfig.CONFIG.restoringFeatureStatus.get() == FeatureStatus.ENABLED; } public static BlockBufferBindingCacheType getBlockBufferBindingCacheType() { return FeatureConfig.CONFIG.restoringBindingCacheType.get(); } public static BlockBufferBindingStateType getShaderStorageStateType() { return FeatureConfig.CONFIG.restoringShaderStorageType.get(); } public static ViewportBindingStateType getViewportBindingStateType() { return FeatureConfig.CONFIG.coreViewportBindingType.get(); } public static ScissorBindingStateType getScissorBindingStateType() { return FeatureConfig.CONFIG.coreScissorBindingType.get(); } public static BlockBufferBindingStateType getAtomicCounterStateType() { return FeatureConfig.CONFIG.restoringAtomicCounterType.get(); } public static int getShaderStorageRestoringRange() { return FeatureConfig.CONFIG.restoringShaderStorageRange.getAsInt(); } public static int getAtomicCounterRestoringRange() { return FeatureConfig.CONFIG.restoringAtomicCounterRange.getAsInt(); } public static IMeshInfoCache createMeshInfoCache() { return getMeshInfoCacheType().create(); } public static ILayerStorage createLayerStorage() { return getLayerStorageType().create(getPooledBatchingSize()); } public static IMeshDataCache createMeshDataCache() { return getMeshMergeType().create(); } public static IBindingState createViewportState() { return getViewportBindingStateType().create(); } public static IBindingState createScissorState() { return getScissorBindingStateType().create(); } public static IBindingState createShaderStorageState() { return getShaderStorageStateType().create(getBlockBufferBindingCacheType(), BufferBlockType.SHADER_STORAGE, getShaderStorageRestoringRange()); } public static IBindingState createAtomicCounterState() { return getAtomicCounterStateType().create(getBlockBufferBindingCacheType(), BufferBlockType.ATOMIC_COUNTER, getAtomicCounterRestoringRange()); } public static int packDynamicUV(float u, float v) { return PackedVector2i.pack(u * getDynamicUVResolution(), v * getDynamicUVResolution()); } public static float unpackDynamicU(int packedUV) { return PackedVector2i.unpackU(packedUV) / getDynamicUVResolution(); } public static float unpackDynamicV(int packedUV) { return PackedVector2i.unpackV(packedUV) / getDynamicUVResolution(); } public static void disableForceTranslucentAcceleration() { FORCE_TRANSLUCENT_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.DISABLED); } public static void disableCacheIdenticalPose() { CACHE_IDENTICAL_POSE_CONTROLLER_STACK.push(FeatureStatus.DISABLED); } public static void forceEnableForceTranslucentAcceleration() { FORCE_TRANSLUCENT_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.ENABLED); } public static void forceEnableCacheIdenticalPose() { CACHE_IDENTICAL_POSE_CONTROLLER_STACK.push(FeatureStatus.ENABLED); } public static void forceSetForceTranslucentAcceleration(FeatureStatus status) { FORCE_TRANSLUCENT_ACCELERATION_CONTROLLER_STACK.push(status); } public static void forceSetCacheIdenticalPose(FeatureStatus status) { CACHE_IDENTICAL_POSE_CONTROLLER_STACK.push(status); } public static void forceSetDefaultLayer(int defaultLayer) { DEFAULT_LAYER_CONTROLLER_STACK.push(defaultLayer); } public static void forceSetDefaultLayerBeforeFunction(Runnable runnable) { DEFAULT_LAYER_BEFORE_FUNCTION_CONTROLLER_STACK.push(runnable); } public static void forceSetDefaultLayerAfterFunction(Runnable runnable) { DEFAULT_LAYER_AFTER_FUNCTION_CONTROLLER_STACK.push(runnable); } public static void resetForceTranslucentAcceleration() { FORCE_TRANSLUCENT_ACCELERATION_CONTROLLER_STACK.pop(); } public static void resetCacheIdenticalPose() { CACHE_IDENTICAL_POSE_CONTROLLER_STACK.pop(); } public static void resetDefaultLayer() { DEFAULT_LAYER_CONTROLLER_STACK.pop(); } public static void resetDefaultLayerBeforeFunction() { DEFAULT_LAYER_BEFORE_FUNCTION_CONTROLLER_STACK.pop(); } public static void resetDefaultLayerAfterFunction() { DEFAULT_LAYER_AFTER_FUNCTION_CONTROLLER_STACK.pop(); } public static FeatureStatus getForceTranslucentAccelerationSetting() { return FORCE_TRANSLUCENT_ACCELERATION_CONTROLLER_STACK.isEmpty() ? getDefaultForceTranslucentAccelerationSetting() : FORCE_TRANSLUCENT_ACCELERATION_CONTROLLER_STACK.peek(); } public static FeatureStatus getCacheIdenticalPoseSetting() { return CACHE_IDENTICAL_POSE_CONTROLLER_STACK.isEmpty() ? getDefaultCacheIdenticalPoseSetting() : CACHE_IDENTICAL_POSE_CONTROLLER_STACK.peek(); } public static int getDefaultLayer() { return DEFAULT_LAYER_CONTROLLER_STACK.isEmpty() ? 0 : DEFAULT_LAYER_CONTROLLER_STACK.peek(); } public static Runnable getDefaultLayerBeforeFunction() { return DEFAULT_LAYER_BEFORE_FUNCTION_CONTROLLER_STACK.isEmpty() ? Runnables.doNothing() : DEFAULT_LAYER_BEFORE_FUNCTION_CONTROLLER_STACK.peek(); } public static Runnable getDefaultLayerAfterFunction() { return DEFAULT_LAYER_AFTER_FUNCTION_CONTROLLER_STACK.isEmpty() ? Runnables.doNothing() : DEFAULT_LAYER_AFTER_FUNCTION_CONTROLLER_STACK.peek(); } public static FeatureStatus getDefaultForceTranslucentAccelerationSetting() { return FeatureConfig.CONFIG.coreForceTranslucentAcceleration.get(); } public static FeatureStatus getDefaultCacheIdenticalPoseSetting() { return FeatureConfig.CONFIG.coreCacheIdenticalPose.get(); } public static void setRenderingLevel() { RENDERING_LEVEL = true; } public static void resetRenderingLevel() { RENDERING_LEVEL = false; } public static void setRenderingHand() { RENDERING_HAND = true; } public static void resetRenderingHand() { RENDERING_HAND = false; } public static void setRenderingGui() { RENDERING_GUI = true; } public static void resetRenderingGui() { RENDERING_GUI = false; } public static boolean isRenderingLevel() { return RENDERING_LEVEL; } public static boolean isRenderingHand() { return RENDERING_HAND; } public static boolean isRenderingGui() { return RENDERING_GUI; } public static void setGuiBatching() { GUI_BATCHING = true; } public static void resetGuiBatching() { GUI_BATCHING = false; } public static boolean isGuiBatching() { return GUI_BATCHING; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/CoreStates.java ================================================ package com.github.argon4w.acceleratedrendering.core; import com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState; public class CoreStates { public static final IBindingState SHADER_STORAGE_BUFFER_STATE = CoreFeature.createShaderStorageState(); public static final IBindingState ATOMIC_COUNTER_BUFFER_STATE = CoreFeature.createAtomicCounterState(); public static void recordBuffers() { if (CoreFeature.shouldRestoreBlockBuffers()) { SHADER_STORAGE_BUFFER_STATE.record(null); ATOMIC_COUNTER_BUFFER_STATE.record(null); } } public static void restoreBuffers() { if (CoreFeature.shouldRestoreBlockBuffers()) { SHADER_STORAGE_BUFFER_STATE.restore(); ATOMIC_COUNTER_BUFFER_STATE.restore(); } } public static void delete() { SHADER_STORAGE_BUFFER_STATE.delete(); ATOMIC_COUNTER_BUFFER_STATE.delete(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/DebugOutput.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends; import static org.lwjgl.opengl.GL46.GL_DEBUG_OUTPUT_SYNCHRONOUS; import static org.lwjgl.opengl.GL46.glEnable; public class DebugOutput { public static void enable() { glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/GLConstants.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends; import static org.lwjgl.opengl.GL46.*; public class GLConstants { public static final int MAX_SHADER_STORAGE_BLOCK_SIZE = glGetInteger (GL_MAX_SHADER_STORAGE_BLOCK_SIZE); public static final int MAX_COMPUTE_WORK_GROUP_COUNT_X = glGetIntegeri (GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0); public static final int MAX_COMPUTE_WORK_GROUP_COUNT_Y = glGetIntegeri (GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1); public static final int MAX_COMPUTE_WORK_GROUP_COUNT_Z = glGetIntegeri (GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/Sync.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends; import static org.lwjgl.opengl.GL46.*; public class Sync { private long syncHandle; public Sync() { this.syncHandle = -1; } public boolean isSyncSet() { return syncHandle != -1; } public boolean isSyncSignaled() { return glGetSynci(syncHandle, GL_SYNC_STATUS, null) == GL_SIGNALED; } public void waitSync() { glClientWaitSync(syncHandle, GL_SYNC_FLUSH_COMMANDS_BIT, Long.MAX_VALUE); } public void setSync() { syncHandle = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); } public void deleteSync() { glDeleteSync(syncHandle); } public void resetSync() { syncHandle = -1; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/VertexArray.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends; import static org.lwjgl.opengl.GL46.*; public class VertexArray { private final int vaoHandle; public VertexArray() { this.vaoHandle = glCreateVertexArrays(); } public void bind() { glBindVertexArray(vaoHandle); } public void unbind() { glBindVertexArray(0); } public void delete() { glDeleteVertexArrays(vaoHandle); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/buffers/EmptyServerBuffer.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.buffers; import java.nio.ByteBuffer; public class EmptyServerBuffer implements IServerBuffer { public static final EmptyServerBuffer INSTANCE = new EmptyServerBuffer(); @Override public int getBufferHandle() { return 0; } @Override public void delete() { } @Override public void bind(int target) { } @Override public void data(ByteBuffer data) { } @Override public void bindBase(int target, int index) { } @Override public void bindRange( int target, int index, long offset, long size ) { } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/buffers/IClientBuffer.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.buffers; public interface IClientBuffer { long reserve (long bytes); long reserve (long bytes, boolean occupied); long addressAt (long position); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/buffers/IServerBuffer.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.buffers; import java.nio.ByteBuffer; public interface IServerBuffer { int getBufferHandle (); void delete (); void data (ByteBuffer data); void bind (int target); void bindBase (int target, int index); void bindRange (int target, int index, long offset, long size); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/buffers/ImmutableBuffer.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.buffers; import java.nio.ByteBuffer; import static org.lwjgl.opengl.GL46.*; public class ImmutableBuffer implements IServerBuffer { protected final int bufferHandle; public ImmutableBuffer(long size, int bits) { this.bufferHandle = glCreateBuffers(); glNamedBufferStorage( this.bufferHandle, size, bits ); } public void copyTo(IServerBuffer buffer, long size) { glCopyNamedBufferSubData( bufferHandle, buffer.getBufferHandle(), 0, 0, size ); } public long map(long length, int bits) { return nglMapNamedBufferRange( bufferHandle, 0L, length, bits ); } public void unmap() { glUnmapNamedBuffer(bufferHandle); } @Override public int getBufferHandle() { return bufferHandle; } @Override public void delete() { glDeleteBuffers(bufferHandle); } @Override public void bind(int target) { glBindBuffer(target, bufferHandle); } @Override public void data(ByteBuffer data) { glNamedBufferSubData( bufferHandle, 0, data ); } @Override public void bindBase(int target, int index) { glBindBufferBase( target, index, bufferHandle ); } @Override public void bindRange( int target, int index, long offset, long size ) { glBindBufferRange( target, index, bufferHandle, offset, size ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/buffers/MappedBuffer.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.buffers; import lombok.Getter; import static org.lwjgl.opengl.GL46.*; @Getter public class MappedBuffer extends MutableBuffer implements IClientBuffer { protected long address; protected long position; protected long current; public MappedBuffer(long initialSize) { super(initialSize, GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT | GL_MAP_COHERENT_BIT ); this.address = map(); this.position = 0L; this.current = 0L; } @Override public long reserve(long bytes, boolean occupied) { if (bytes <= 0) { return address + position; } var oldPosition = this.position; var newPosition = oldPosition + bytes; if (occupied) { this.current = oldPosition; this.position = newPosition; } if (newPosition <= size) { return address + oldPosition; } resize(newPosition); return address + oldPosition; } @Override public long reserve(long bytes) { return reserve(bytes, true); } @Override public long addressAt(long position) { return address + position; } @Override public void beforeExpand() { unmap(); } @Override public void afterExpand() { address = map(); } public void reset() { position = 0; } public long getCurrent() { return address + current; } public long map() { return map( GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/buffers/MutableBuffer.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.buffers; import com.github.argon4w.acceleratedrendering.core.utils.MutableSize; import java.nio.ByteBuffer; public class MutableBuffer extends MutableSize implements IServerBuffer { private final int bits; protected ImmutableBuffer glBuffer; public MutableBuffer(long initialSize, int bits) { super(initialSize); this.bits = bits; this.glBuffer = new ImmutableBuffer(this.size, bits); } @Override public void doExpand(long size, long bytes) { var newSize = size + bytes; var newBuffer = new ImmutableBuffer(newSize, bits); glBuffer.copyTo(newBuffer, size); glBuffer.delete(); glBuffer = newBuffer; } public long map(int flags) { return glBuffer.map(size, flags); } public void unmap() { glBuffer.unmap(); } public void copyTo(IServerBuffer buffer) { glBuffer.copyTo(buffer, size); } @Override public int getBufferHandle() { return glBuffer.getBufferHandle(); } @Override public void delete() { glBuffer.delete(); } @Override public void bind(int target) { glBuffer.bind(target); } @Override public void data(ByteBuffer data) { glBuffer.data(data); } @Override public void bindBase(int target, int index) { glBuffer.bindBase(target, index); } @Override public void bindRange( int target, int index, long offset, long size ) { glBuffer.bindRange( target, index, offset, size ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/programs/BarrierFlags.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.programs; import static org.lwjgl.opengl.GL46.*; public enum BarrierFlags { SHADER_STORAGE (GL_SHADER_STORAGE_BARRIER_BIT), ATOMIC_COUNTER (GL_ATOMIC_COUNTER_BARRIER_BIT), ELEMENT_ARRAY (GL_ELEMENT_ARRAY_BARRIER_BIT), COMMAND (GL_COMMAND_BARRIER_BIT); private final int flag; BarrierFlags(int flag) { this.flag = flag; } public static int getFlags(BarrierFlags... barrierFlags) { int intFlags = 0; for (BarrierFlags barrierFlag : barrierFlags) { intFlags = intFlags | barrierFlag.flag; } return intFlags; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/programs/ComputeProgram.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.programs; import lombok.Getter; import static org.lwjgl.opengl.GL46.*; @Getter public class ComputeProgram { private final int programHandle; private final int barrierFlags; public ComputeProgram(int barrierFlags) { this.programHandle = glCreateProgram(); this.barrierFlags = barrierFlags; } public void dispatch( int countX, int countY, int countZ ) { glDispatchCompute( countX, countY, countZ ); } public void setup() { } public void linkProgram() { glLinkProgram(programHandle); } public boolean isLinked() { return glGetProgrami(programHandle, GL_LINK_STATUS) == GL_TRUE; } public void useProgram() { glUseProgram(programHandle); } public void resetProgram() { glUseProgram(0); } public void attachShader(ComputeShader computeShader) { glAttachShader(programHandle, computeShader.getShaderHandle()); } public void waitBarriers() { glMemoryBarrier(barrierFlags); } public int getUniformLocation(String name) { return glGetUniformLocation(programHandle, name); } public Uniform getUniform(String name) { return new Uniform(programHandle, getUniformLocation(name)); } public String getInfoLog() { return glGetProgramInfoLog(programHandle); } public void delete() { glDeleteProgram(programHandle); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/programs/ComputeShader.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.programs; import lombok.Getter; import static org.lwjgl.opengl.GL46.*; @Getter public class ComputeShader { private final int shaderHandle; public ComputeShader() { this.shaderHandle = glCreateShader(GL_COMPUTE_SHADER); } public void setShaderSource(String source) { glShaderSource(shaderHandle, source); } public void compileShader() { glCompileShader(shaderHandle); } public boolean isCompiled() { return glGetShaderi(shaderHandle, GL_COMPILE_STATUS) == GL_TRUE; } public String getInfoLog() { return glGetShaderInfoLog(shaderHandle); } public void delete() { glDeleteShader(shaderHandle); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/programs/Uniform.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.programs; import org.joml.Matrix4f; import org.lwjgl.system.MemoryStack; import static org.lwjgl.opengl.GL41.glProgramUniform1ui; import static org.lwjgl.opengl.GL46.glProgramUniformMatrix4fv; public class Uniform { private final int programHandle; private final int uniformLocation; public Uniform(int programHandle, int uniformLocation) { this.programHandle = programHandle; this.uniformLocation = uniformLocation; } public void uploadMatrix4f(Matrix4f matrix) { try (MemoryStack stack = MemoryStack.stackPush()) { glProgramUniformMatrix4fv( programHandle, uniformLocation, false, matrix.get(stack.callocFloat(16)) ); } } public void uploadUnsignedInt(int value) { glProgramUniform1ui( programHandle, uniformLocation, value ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/EmptyBindingState.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.states; import net.minecraft.client.gui.GuiGraphics; public class EmptyBindingState implements IBindingState { public static final IBindingState INSTANCE = new EmptyBindingState(); @Override public void record(GuiGraphics graphics) { } @Override public void restore() { } @Override public void delete() { } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/FramebufferBindingState.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.states; import net.minecraft.client.gui.GuiGraphics; import static org.lwjgl.opengl.GL46.*; public class FramebufferBindingState implements IBindingState { private int bindingFramebuffer; private int bindingReadFramebuffer; private int bindingDrawFramebuffer; public FramebufferBindingState() { this.bindingFramebuffer = 0; this.bindingReadFramebuffer = 0; this.bindingDrawFramebuffer = 0; } @Override public void record(GuiGraphics graphics) { bindingFramebuffer = glGetInteger(GL_FRAMEBUFFER_BINDING); if (bindingFramebuffer == 0) { bindingReadFramebuffer = glGetInteger(GL_READ_FRAMEBUFFER_BINDING); bindingDrawFramebuffer = glGetInteger(GL_DRAW_FRAMEBUFFER_BINDING); } } @Override public void restore() { if (bindingFramebuffer != 0) { glBindFramebuffer(GL_FRAMEBUFFER, bindingFramebuffer); } else { glBindFramebuffer(GL_READ_FRAMEBUFFER, bindingReadFramebuffer); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, bindingDrawFramebuffer); } } @Override public void delete() { } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/IBindingState.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.states; import net.minecraft.client.gui.GuiGraphics; public interface IBindingState { void record (GuiGraphics graphics); void restore(); void delete (); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/buffers/BlockBufferBindingStateType.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.states.buffers; import com.github.argon4w.acceleratedrendering.core.backends.states.EmptyBindingState; import com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState; import com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache.BlockBufferBindingCacheType; public enum BlockBufferBindingStateType { IGNORED, RESTORED; public IBindingState create( BlockBufferBindingCacheType cacheType, BufferBlockType blockType, int bindingRange ) { return create( this, cacheType, blockType, bindingRange ); } public static IBindingState create( BlockBufferBindingStateType stateType, BlockBufferBindingCacheType cacheType, BufferBlockType blockType, int bindingRange ) { return switch (stateType) { case IGNORED -> EmptyBindingState.INSTANCE; case RESTORED -> new SimpleBlockBufferBindingState( cacheType, bindingRange, blockType.getBindingBlock (), blockType.getBufferParam (), blockType.getOffsetParam (), blockType.getSizeParam () ); }; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/buffers/BufferBlockType.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.states.buffers; import lombok.AllArgsConstructor; import lombok.Getter; import static org.lwjgl.opengl.GL46.*; @Getter @AllArgsConstructor public enum BufferBlockType { SHADER_STORAGE( GL_SHADER_STORAGE_BUFFER, GL_SHADER_STORAGE_BUFFER_BINDING, GL_SHADER_STORAGE_BUFFER_START, GL_SHADER_STORAGE_BUFFER_SIZE ), ATOMIC_COUNTER( GL_ATOMIC_COUNTER_BUFFER, GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_ATOMIC_COUNTER_BUFFER_START, GL_ATOMIC_COUNTER_BUFFER_SIZE ); private final int bindingBlock; private final int bufferParam; private final int offsetParam; private final int sizeParam; } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/buffers/SimpleBlockBufferBindingState.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.states.buffers; import com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState; import com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache.BlockBufferBindingCacheType; import com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache.IBlockBufferBindingCache; import net.minecraft.client.gui.GuiGraphics; import static org.lwjgl.opengl.GL46.*; public class SimpleBlockBufferBindingState implements IBindingState { private final IBlockBufferBindingCache bindingCache; private final int bindingRange; private final int bindingBlock; private final int bufferParam; private final int offsetParam; private final int sizeParam; public SimpleBlockBufferBindingState( BlockBufferBindingCacheType type, int bindingRange, int bindingBlock, int bufferParam, int offsetParam, int sizeParam ) { this.bindingRange = bindingRange; this.bindingCache = type.create(this.bindingRange); this.bindingBlock = bindingBlock; this.bufferParam = bufferParam; this.offsetParam = offsetParam; this.sizeParam = sizeParam; } @Override public void record(GuiGraphics graphics) { for (var bindingPoint = 0; bindingPoint < bindingRange; bindingPoint++) { bindingCache.setup( bindingPoint, glGetIntegeri(bufferParam, bindingPoint), glGetIntegeri(offsetParam, bindingPoint), glGetIntegeri(sizeParam, bindingPoint) ); } } @Override public void restore() { for (var bindingPoint = 0; bindingPoint < bindingRange; bindingPoint ++) { var buffer = bindingCache.getBuffer(bindingPoint); var offset = bindingCache.getOffset(bindingPoint); var size = bindingCache.getSize (bindingPoint); if ( offset == 0 && size == 0 ) { glBindBufferBase( bindingBlock, bindingPoint, buffer ); } else { glBindBufferRange( bindingBlock, bindingPoint, buffer, offset, size ); } } } @Override public void delete() { bindingCache.delete(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/buffers/cache/BlockBufferBindingCacheType.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache; public enum BlockBufferBindingCacheType { SIMPLE, UNSAFE, HANDLE; public IBlockBufferBindingCache create(int size) { return create(this, size); } public static IBlockBufferBindingCache create(BlockBufferBindingCacheType type, int size) { return switch (type) { case SIMPLE -> new SimpleBlockBufferBindingCache (size); case HANDLE -> new FlattenBlockBufferBindingCache (size); case UNSAFE -> new UnsafeMemoryBlockBufferBindingCache (size); }; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/buffers/cache/FlattenBlockBufferBindingCache.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; public class FlattenBlockBufferBindingCache implements IBlockBufferBindingCache { public static final VarHandle HANDLE = MethodHandles.arrayElementVarHandle(long[].class).withInvokeExactBehavior(); public static final int BLOCK_BUFFER_BINDING_SIZE = 3; public static final int BUFFER_OFFSET = 0; public static final int OFFSET_OFFSET = 1; public static final int SIZE_OFFSET = 2; private final long[] cache; public FlattenBlockBufferBindingCache(int size) { this.cache = new long[size * BLOCK_BUFFER_BINDING_SIZE]; } @Override public void delete() { } @Override public void setup( int bindingPoint, int buffer, long offset, long size ) { var bindingIndex = bindingPoint * BLOCK_BUFFER_BINDING_SIZE; HANDLE.set(cache, bindingIndex + BUFFER_OFFSET, (long) buffer); HANDLE.set(cache, bindingIndex + OFFSET_OFFSET, offset); HANDLE.set(cache, bindingIndex + SIZE_OFFSET, size); } @Override public int getBuffer(int bindingPoint) { return (int) (long) HANDLE.get(cache, bindingPoint * BLOCK_BUFFER_BINDING_SIZE + BUFFER_OFFSET); } @Override public long getOffset(int bindingPoint) { return (long) HANDLE.get(cache, bindingPoint * BLOCK_BUFFER_BINDING_SIZE + OFFSET_OFFSET); } @Override public long getSize(int bindingPoint) { return (long) HANDLE.get(cache, bindingPoint * BLOCK_BUFFER_BINDING_SIZE + SIZE_OFFSET); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/buffers/cache/IBlockBufferBindingCache.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache; public interface IBlockBufferBindingCache { void delete (); void setup (int bindingPoint, int buffer, long offset, long size); int getBuffer (int bindingPoint); long getOffset (int bindingPoint); long getSize (int bindingPoint); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/buffers/cache/SimpleBlockBufferBinding.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache; import lombok.Getter; @Getter public class SimpleBlockBufferBinding { private int buffer; private long offset; private long size; public SimpleBlockBufferBinding() { this.buffer = -1; this.offset = -1; this.size = -1; } public void setupBlockBufferBinding( int buffer, long offset, long size ) { this.buffer = buffer; this.offset = offset; this.size = size; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/buffers/cache/SimpleBlockBufferBindingCache.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache; public class SimpleBlockBufferBindingCache implements IBlockBufferBindingCache { private final SimpleBlockBufferBinding[] cache; public SimpleBlockBufferBindingCache(int size) { cache = new SimpleBlockBufferBinding[size]; for (int i = 0; i < cache.length; i++) { cache[i] = new SimpleBlockBufferBinding(); } } @Override public void delete() { } @Override public void setup( int bindingPoint, int buffer, long offset, long size ) { cache[bindingPoint].setupBlockBufferBinding( buffer, offset, size ); } @Override public int getBuffer(int bindingPoint) { return cache[bindingPoint].getBuffer(); } @Override public long getOffset(int bindingPoint) { return cache[bindingPoint].getOffset(); } @Override public long getSize(int bindingPoint) { return cache[bindingPoint].getSize(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/buffers/cache/UnsafeMemoryBlockBufferBindingCache.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.states.buffers.cache; import io.netty.util.internal.shaded.org.jctools.util.UnsafeAccess; import sun.misc.Unsafe; public class UnsafeMemoryBlockBufferBindingCache implements IBlockBufferBindingCache { public static final Unsafe UNSAFE = UnsafeAccess.UNSAFE; public static final long BLOCK_BUFFER_BINDING_SIZE = 3L * 8L; public static final long BUFFER_OFFSET = 0L * 8L; public static final long OFFSET_OFFSET = 1L * 8L; public static final long SIZE_OFFSET = 2L * 8L; private final long address; public UnsafeMemoryBlockBufferBindingCache(int size) { this.address = UNSAFE.allocateMemory(size * BLOCK_BUFFER_BINDING_SIZE); } @Override public void delete() { UNSAFE.freeMemory(address); } @Override public void setup( int bindingPoint, int buffer, long offset, long size ) { var bindingAddress = address + bindingPoint * BLOCK_BUFFER_BINDING_SIZE; UNSAFE.putInt (bindingAddress + BUFFER_OFFSET, buffer); UNSAFE.putLong (bindingAddress + OFFSET_OFFSET, offset); UNSAFE.putLong (bindingAddress + SIZE_OFFSET, size); } @Override public int getBuffer(int bindingPoint) { return UNSAFE.getInt(address + bindingPoint * BLOCK_BUFFER_BINDING_SIZE + BUFFER_OFFSET); } @Override public long getOffset(int bindingPoint) { return UNSAFE.getLong(address + bindingPoint * BLOCK_BUFFER_BINDING_SIZE + OFFSET_OFFSET); } @Override public long getSize(int bindingPoint) { return UNSAFE.getLong(address + bindingPoint * BLOCK_BUFFER_BINDING_SIZE + SIZE_OFFSET); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/scissors/MojangScissorBindingState.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.states.scissors; import com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import static org.lwjgl.opengl.GL46.*; public class MojangScissorBindingState implements IBindingState { private boolean recorded; private boolean enabled; private int scissorX; private int scissorY; private int scissorWidth; private int scissorHeight; public MojangScissorBindingState() { this.enabled = false; this.scissorX = 0; this.scissorY = 0; this.scissorWidth = 0; this.scissorHeight = 0; } @Override public void record(GuiGraphics graphics) { var rect = graphics.scissorStack.stack.peekLast(); if (rect != null) { var window = Minecraft.getInstance() .getWindow (); var height = window .getHeight (); var scale = window .getGuiScale(); scissorY = (int) (height - rect.bottom() * scale); scissorX = (int) (rect.left () * scale); scissorWidth = (int) (rect.width () * scale); scissorHeight = (int) (rect.height() * scale); enabled = true; } else { enabled = false; } recorded = true; } @Override public void restore() { if (!recorded) { return; } if (enabled) { glEnable (GL_SCISSOR_TEST); glScissor ( scissorX, scissorY, scissorWidth, scissorHeight ); } else { glDisable(GL_SCISSOR_TEST); } recorded = false; } @Override public void delete() { enabled = false; recorded = false; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/scissors/OpenGLScissorBindingState.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.states.scissors; import com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState; import net.minecraft.client.gui.GuiGraphics; import org.lwjgl.system.MemoryUtil; import java.nio.IntBuffer; import static org.lwjgl.opengl.GL46.*; public class OpenGLScissorBindingState implements IBindingState { private final IntBuffer bindingScissor; private boolean enabled; private boolean recorded; public OpenGLScissorBindingState() { this.bindingScissor = MemoryUtil.memAllocInt(4); this.enabled = false; this.recorded = false; } @Override public void record(GuiGraphics graphics) { glGetIntegerv (GL_SCISSOR_BOX, bindingScissor); enabled = glIsEnabled (GL_SCISSOR_TEST); recorded = true; } @Override public void restore() { if (!recorded) { return; } if (enabled) { glEnable (GL_SCISSOR_TEST); glScissor ( bindingScissor.get(0), bindingScissor.get(1), bindingScissor.get(2), bindingScissor.get(3) ); } else { glDisable(GL_SCISSOR_TEST); } recorded = false; } @Override public void delete() { MemoryUtil.memFree(bindingScissor); recorded = false; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/scissors/ScissorBindingStateType.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.states.scissors; import com.github.argon4w.acceleratedrendering.core.backends.states.EmptyBindingState; import com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState; public enum ScissorBindingStateType { IGNORED, MOJANG, OPENGL; public IBindingState create() { return create(this); } public static IBindingState create(ScissorBindingStateType type) { return switch (type) { case IGNORED -> EmptyBindingState.INSTANCE; case MOJANG -> new MojangScissorBindingState(); case OPENGL -> new OpenGLScissorBindingState(); }; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/viewports/MojangViewportBindingState.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.states.viewports; import com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState; import com.mojang.blaze3d.platform.GlStateManager; import net.minecraft.client.gui.GuiGraphics; public class MojangViewportBindingState implements IBindingState { private int viewportX; private int viewportY; private int viewportWidth; private int viewportHeight; public MojangViewportBindingState() { this.viewportX = 0; this.viewportY = 0; this.viewportWidth = 0; this.viewportHeight = 0; } @Override public void record(GuiGraphics graphics) { viewportX = GlStateManager.Viewport.x (); viewportY = GlStateManager.Viewport.y (); viewportWidth = GlStateManager.Viewport.width (); viewportHeight = GlStateManager.Viewport.height(); } @Override public void restore() { if ( viewportX != GlStateManager.Viewport.x () || viewportY != GlStateManager.Viewport.y () || viewportWidth != GlStateManager.Viewport.width () || viewportHeight != GlStateManager.Viewport.height () ) { GlStateManager._viewport( viewportX, viewportY, viewportWidth, viewportHeight ); } } @Override public void delete() { } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/viewports/OpenGLViewportBindingState.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.states.viewports; import com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState; import net.minecraft.client.gui.GuiGraphics; import org.lwjgl.system.MemoryUtil; import java.nio.IntBuffer; import static org.lwjgl.opengl.GL46.*; public class OpenGLViewportBindingState implements IBindingState { private final IntBuffer bindingViewport; public OpenGLViewportBindingState() { this.bindingViewport = MemoryUtil.memAllocInt(4); } @Override public void record(GuiGraphics graphics) { glGetIntegerv(GL_VIEWPORT, bindingViewport); } @Override public void restore() { glViewport( bindingViewport.get(0), bindingViewport.get(1), bindingViewport.get(2), bindingViewport.get(3) ); } @Override public void delete() { MemoryUtil.memFree(bindingViewport); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/backends/states/viewports/ViewportBindingStateType.java ================================================ package com.github.argon4w.acceleratedrendering.core.backends.states.viewports; import com.github.argon4w.acceleratedrendering.core.backends.states.EmptyBindingState; import com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState; public enum ViewportBindingStateType { IGNORED, MOJANG, OPENGL; public IBindingState create() { return create(this); } public static IBindingState create(ViewportBindingStateType type) { return switch (type) { case IGNORED -> EmptyBindingState.INSTANCE; case MOJANG -> new MojangViewportBindingState(); case OPENGL -> new OpenGLViewportBindingState(); }; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/AcceleratedBufferSources.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.AcceleratedBufferSource; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAcceleratedBufferSource; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder; import com.github.argon4w.acceleratedrendering.core.utils.RenderTypeUtils; import com.mojang.blaze3d.vertex.VertexFormat; import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; import net.minecraft.client.renderer.RenderType; import java.util.Map; import java.util.Set; public class AcceleratedBufferSources implements IAcceleratedBufferSource { private final Map sources; private final Set validModes; private final boolean supportTranslucent; private final boolean supportDynamic; private AcceleratedBufferSources( Map sources, Set validModes, boolean supportTranslucent, boolean supportDynamic ) { this.sources = sources; this.validModes = validModes; this.supportTranslucent = supportTranslucent; this.supportDynamic = supportDynamic; } @Override public AcceleratedBufferBuilder getBuffer( RenderType renderType, Runnable before, Runnable after, int layer ) { if ( renderType != null && ( CoreFeature .shouldForceAccelerateTranslucent () || supportTranslucent || !RenderTypeUtils.isTranslucent (renderType)) && ( CoreFeature .shouldCacheDynamicRenderType () || supportDynamic || !RenderTypeUtils.isDynamic (renderType)) && validModes .contains (renderType.mode) && sources .containsKey (renderType.format) ) { return sources .get (renderType.format) .getBuffer ( renderType, before, after, layer ); } return null; } public static Builder builder() { return new Builder(); } public static class Builder { private final Map sources; private final Set validModes; private boolean supportTranslucent; private boolean supportDynamic; private Builder() { this.sources = new Reference2ObjectOpenHashMap <>(); this.validModes = new ReferenceOpenHashSet <>(); this.supportTranslucent = false; this.supportDynamic = false; } public Builder source(AcceleratedBufferSource bufferSource) { for (var format : bufferSource .getEnvironment () .getVertexFormats () ) { sources.put(format, bufferSource); } return this; } public Builder mode(VertexFormat.Mode mode) { validModes.add(mode); return this; } public Builder supportTranslucent() { supportTranslucent = true; return this; } public Builder supportDynamic() { supportDynamic = true; return this; } public AcceleratedBufferSources build() { return new AcceleratedBufferSources( sources, validModes, supportTranslucent, supportDynamic ); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/EmptyAcceleratedBufferSources.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAcceleratedBufferSource; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder; import net.minecraft.client.renderer.RenderType; public class EmptyAcceleratedBufferSources implements IAcceleratedBufferSource { public static final IAcceleratedBufferSource INSTANCE = new EmptyAcceleratedBufferSources(); @Override public AcceleratedBufferBuilder getBuffer( RenderType renderType, Runnable before, Runnable after, int layer ) { return null; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/AcceleratedBufferSource.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerKey; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.functions.CustomLayerFunction; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.functions.EmptyLayerFunction; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.empty.EmptyLayerStorage; import com.github.argon4w.acceleratedrendering.core.buffers.environments.IBufferEnvironment; import com.github.argon4w.acceleratedrendering.core.programs.dispatchers.MeshUploadingProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.utils.RenderTypeUtils; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.BufferUploader; import it.unimi.dsi.fastutil.ints.IntAVLTreeSet; import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; import lombok.Getter; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; import java.util.Map; import java.util.Set; import static org.lwjgl.opengl.GL46.*; public class AcceleratedBufferSource implements IAcceleratedBufferSource { @Getter private final IBufferEnvironment environment; private final AcceleratedRingBuffers ringBuffers; private final Set buffers; private final Map activeBuilders; private final IntSet activeLayers; private AcceleratedRingBuffers.Buffers currentBuffer; private boolean used; private int barriers; public AcceleratedBufferSource(IBufferEnvironment bufferEnvironment) { this.environment = bufferEnvironment; this.ringBuffers = new AcceleratedRingBuffers (this.environment); this.buffers = new ObjectLinkedOpenHashSet <> (); this.activeBuilders = new Object2ObjectOpenHashMap <> (); this.activeLayers = new IntAVLTreeSet (); this.currentBuffer = this.ringBuffers.get(false); this.used = false; this.barriers = GL_SHADER_STORAGE_BARRIER_BIT; this.buffers.add(this.currentBuffer); } public void delete() { ringBuffers.delete(); } @Override public AcceleratedBufferBuilder getBuffer( RenderType renderType, Runnable before, Runnable after, int layerIndex ) { var layerKey = new LayerKey (layerIndex, renderType); var builder = activeBuilders.get (layerKey); var builders = currentBuffer .getBuilders (); var functions = currentBuffer .getFunctions (); var layers = currentBuffer .getLayers (); var function = functions .get (layerIndex); var layer = layers .get (layerIndex); if (builder != null) { function = builder .getFunction(); function .addBefore (before); function .addAfter (after); return builder; } var vertexBuffer = currentBuffer.getVertexBuffer (); var varyingBuffer = currentBuffer.getVaryingBuffer (); var elementSegment = currentBuffer.getElementSegment (); if (vertexBuffer == null) { currentBuffer = ringBuffers .get (true); builders = currentBuffer .getBuilders (); functions = currentBuffer .getFunctions (); layers = currentBuffer .getLayers (); function = functions .get (layerIndex); layer = layers .get (layerIndex); vertexBuffer = currentBuffer .getVertexBuffer (); varyingBuffer = currentBuffer .getVaryingBuffer (); elementSegment = currentBuffer .getElementSegment (); buffers.add(currentBuffer); } if (layer == null) { function = new CustomLayerFunction (); layer = CoreFeature .createLayerStorage (); layers .put (layerIndex, layer); functions .put (layerIndex, function); } builder = new AcceleratedBufferBuilder( vertexBuffer, varyingBuffer, elementSegment, currentBuffer, function, renderType ); used = true; builders .put (layerKey, builder); function .addBefore (before); function .addAfter (after); activeBuilders .put (layerKey, builder); activeLayers .add (layerIndex); return builder; } public void prepareBuffers() { if (!used) { return; } for (var buffer : buffers) { var builders = buffer.getBuilders(); var program = glGetInteger (GL_CURRENT_PROGRAM); if (builders.isEmpty()) { continue; } environment.getImmediateMeshBuffer ().bindBase (GL_SHADER_STORAGE_BUFFER, MeshUploadingProgramDispatcher.SPARSE_MESH_BUFFER_INDEX); environment.selectMeshUploadingProgramDispatcher().dispatch (builders.values(), buffer); environment.selectTransformProgramDispatcher ().dispatch (builders.values()); glMemoryBarrier(barriers); for (var layerKey : builders.keySet()) { var builder = builders.get(layerKey); if (builder.isEmpty()) { continue; } var drawContext = buffer .getDrawContext (); var elementSegment = builder .getElementSegment (); var renderType = layerKey .renderType (); var layer = layerKey .layer (); var drawType = RenderTypeUtils .getDrawType (renderType); builder .setOutdated (); elementSegment .allocateOffset (); buffer .bindElementBuffer (elementSegment); drawContext .bindComputeBuffers (elementSegment); drawContext .setRenderType (renderType); buffer .getLayers () .get (layer) .get (drawType) .add (drawContext); barriers |= builder.getPolygonProgramDispatcher().dispatch(builder); barriers |= builder.getCullingProgramDispatcher().dispatch(builder); } glUseProgram(program); } } public void drawBuffers(LayerDrawType drawType) { if (!used) { return; } glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_COMMAND_BARRIER_BIT ); for ( int layerIndex : activeLayers) { for ( var buffer : buffers) { var function = buffer.getFunctions ().getOrDefault(layerIndex, EmptyLayerFunction .INSTANCE); var contexts = buffer.getLayers ().getOrDefault(layerIndex, EmptyLayerStorage .INSTANCE).get(drawType); if (contexts.isEmpty()) { continue; } BufferUploader .invalidate (); buffer .bindDrawBuffers(); contexts .prepare (); function .runBefore (); for (var drawContext : contexts) { var renderType = drawContext .getRenderType (); renderType .setupRenderState (); var mode = renderType .mode; var shader = RenderSystem .getShader(); shader.setDefaultUniforms( mode, RenderSystem .getModelViewMatrix (), RenderSystem .getProjectionMatrix(), Minecraft.getInstance() .getWindow () ); shader .apply (); drawContext .drawElements (mode); shader .clear (); renderType .clearRenderState (); } function.runAfter (); contexts.reset (); buffer .unbindVertexArray (); } } } public void clearBuffers() { if (!used) { return; } for (var buffer : buffers) { buffer.reset (); buffer.setInFlight (); } used = false; currentBuffer = ringBuffers .get (false); activeBuilders .clear (); activeLayers .clear (); buffers .clear (); buffers .add (currentBuffer); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/AcceleratedRingBuffers.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.backends.Sync; import com.github.argon4w.acceleratedrendering.core.backends.VertexArray; import com.github.argon4w.acceleratedrendering.core.backends.buffers.MappedBuffer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerKey; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.functions.ILayerFunction; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.ILayerStorage; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.DrawContextPool; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.ElementBufferPool; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.StagingBufferPool; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.MeshUploaderPool; import com.github.argon4w.acceleratedrendering.core.buffers.environments.IBufferEnvironment; import com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout; import com.github.argon4w.acceleratedrendering.core.utils.LoopResetPool; import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import lombok.Getter; import org.apache.commons.lang3.mutable.MutableInt; import java.util.Map; import static org.lwjgl.opengl.GL15.GL_ELEMENT_ARRAY_BUFFER; import static org.lwjgl.opengl.GL40.GL_DRAW_INDIRECT_BUFFER; import static org.lwjgl.opengl.GL46.GL_ARRAY_BUFFER; import static org.lwjgl.opengl.GL46.GL_SHADER_STORAGE_BUFFER; public class AcceleratedRingBuffers extends LoopResetPool { public AcceleratedRingBuffers(IBufferEnvironment bufferEnvironment) { super(CoreFeature.getPooledRingBufferSize(), bufferEnvironment); } @Override protected Buffers create(IBufferEnvironment context, int i) { return new Buffers(context); } @Override protected void reset(Buffers buffers) { } @Override protected void delete(Buffers buffers) { buffers.delete(); } @Override protected boolean test(Buffers buffers) { return buffers.isFree(); } @Override public void init(Buffers buffers) { buffers.setUsed(); } @Override protected Buffers fail(boolean force) { var index = 0; if (force) { index = size; expand(); } var buffer = at (index); buffer.waitSync (); buffer.setUsed (); return buffer; } public static class Buffers { public static final int VERTEX_BUFFER_OUT_INDEX = 1; public static final int SHARING_BUFFER_INDEX = 2; public static final int VARYING_BUFFER_OUT_INDEX = 4; public static final int ELEMENT_BUFFER_INDEX = 6; private final MeshUploaderPool meshUploaderPool; private final DrawContextPool drawContextPool; private final ElementBufferPool elementBufferPool; private final MappedBuffer sharingBuffer; private final StagingBufferPool varyingBuffer; private final StagingBufferPool vertexBuffer; private final VertexArray vertexArray; private final Sync sync; private final MutableInt sharing; @Getter private final Map builders; @Getter private final Int2ReferenceMap layers; @Getter private final Int2ReferenceMap functions; @Getter private final IBufferEnvironment bufferEnvironment; @Getter private final int size; private boolean used; private VertexLayout layout; public Buffers(IBufferEnvironment bufferEnvironment) { this.size = CoreFeature.getPooledBatchingSize (); this.meshUploaderPool = new MeshUploaderPool (); this.drawContextPool = new DrawContextPool (size); this.elementBufferPool = new ElementBufferPool (size); this.sharingBuffer = new MappedBuffer (64L); this.varyingBuffer = new StagingBufferPool (size); this.vertexBuffer = new StagingBufferPool (size); this.vertexArray = new VertexArray (); this.sync = new Sync (); this.sharing = new MutableInt (0); this.builders = new Object2ObjectLinkedOpenHashMap<> (); this.layers = new Int2ReferenceOpenHashMap <> (); this.functions = new Int2ReferenceOpenHashMap <> (); this.bufferEnvironment = bufferEnvironment; this.used = false; } public void reset() { meshUploaderPool .reset (); drawContextPool .reset (); elementBufferPool .reset (); varyingBuffer .reset (); sharingBuffer .reset (); vertexBuffer .reset (); sharing .setValue (0); builders .clear (); for (int i : layers.keySet()) { layers .get(i).reset(); functions .get(i).reset(); } } public void bindTransformBuffers() { vertexBuffer .getBufferOut() .bindBase(GL_SHADER_STORAGE_BUFFER, VERTEX_BUFFER_OUT_INDEX); varyingBuffer .getBufferOut() .bindBase(GL_SHADER_STORAGE_BUFFER, VARYING_BUFFER_OUT_INDEX); sharingBuffer .bindBase(GL_SHADER_STORAGE_BUFFER, SHARING_BUFFER_INDEX); } public void bindElementBuffer(ElementBufferPool.ElementSegment elementSegment) { elementBufferPool .getElementBufferOut() .bindRange ( GL_SHADER_STORAGE_BUFFER, ELEMENT_BUFFER_INDEX, elementSegment.getOffset(), elementSegment.getSize () ); } public void bindDrawBuffers() { vertexArray .bind(); drawContextPool.getContext().bind(GL_DRAW_INDIRECT_BUFFER); if ( ! bufferEnvironment .getLayout ().equals (layout) || vertexBuffer .getBufferOut ().isResized() || elementBufferPool .getElementBufferOut().isResized() ) { layout = bufferEnvironment .getLayout (); elementBufferPool .getElementBufferOut() .bind (GL_ELEMENT_ARRAY_BUFFER); elementBufferPool .getElementBufferOut() .resetResized (); vertexBuffer .getBufferOut() .bind (GL_ARRAY_BUFFER); vertexBuffer .getBufferOut() .resetResized (); bufferEnvironment .setupBufferState (); } } public void prepare() { vertexBuffer .prepare(); varyingBuffer .prepare(); elementBufferPool .prepare(); } public void unbindVertexArray() { vertexArray.unbind(); } public MeshUploaderPool.MeshUploader getMeshUploader() { return meshUploaderPool.get(); } public StagingBufferPool.StagingBuffer getVertexBuffer() { return vertexBuffer.get(); } public StagingBufferPool.StagingBuffer getVaryingBuffer() { return varyingBuffer.get(); } public ElementBufferPool.ElementSegment getElementSegment() { return elementBufferPool.get(); } public DrawContextPool.DrawContext getDrawContext() { return drawContextPool.get(); } public long getVertexSize() { return bufferEnvironment.getVertexSize(); } public int getSharing() { return sharing.getAndIncrement(); } public long reserveSharing() { return sharingBuffer.reserve(4L * 4L * 4L + 4L * 4L * 3L); } public void setUsed() { used = true; } public void setInFlight() { used = false; sync.setSync(); } protected void waitSync() { if (!sync.isSyncSet()) { return; } if (!sync.isSyncSignaled()) { sync.waitSync(); } sync.deleteSync (); sync.resetSync (); } public boolean isFree() { if (used) { return false; } if (!sync.isSyncSet()) { return true; } if (!sync.isSyncSignaled()) { return false; } sync.deleteSync (); sync.resetSync (); return true; } public void delete() { meshUploaderPool .delete (); drawContextPool .delete (); elementBufferPool .delete (); sharingBuffer .delete (); varyingBuffer .delete (); vertexBuffer .delete (); vertexArray .delete (); waitSync (); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/IAcceleratedBufferSource.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder; import net.minecraft.client.renderer.RenderType; public interface IAcceleratedBufferSource { AcceleratedBufferBuilder getBuffer(RenderType renderType, Runnable before, Runnable after, int layer); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/IAccelerationHolder.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder; import com.mojang.blaze3d.vertex.VertexConsumer; import net.minecraft.client.renderer.RenderType; import java.util.function.Supplier; public interface IAccelerationHolder { VertexConsumer initAcceleration(RenderType renderType, Supplier bufferSource); AcceleratedBufferBuilder getAccelerated (); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/AcceleratedBufferBuilder.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.AcceleratedRingBuffers; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.functions.ILayerFunction; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.ElementBufferPool; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.StagingBufferPool; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.MeshUploaderPool; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.github.argon4w.acceleratedrendering.core.buffers.memory.*; import com.github.argon4w.acceleratedrendering.core.meshes.ServerMesh; import com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.programs.dispatchers.IPolygonProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.programs.overrides.ITransformShaderProgramOverride; import com.github.argon4w.acceleratedrendering.core.programs.overrides.IUploadingShaderProgramOverride; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormatElement; import it.unimi.dsi.fastutil.objects.Reference2ObjectLinkedOpenHashMap; import lombok.EqualsAndHashCode; import lombok.Getter; import net.minecraft.client.renderer.RenderType; import net.minecraft.util.FastColor; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.lwjgl.system.MemoryUtil; import java.nio.ByteBuffer; import java.util.Map; import java.util.function.LongSupplier; @EqualsAndHashCode(onlyExplicitlyIncluded = true) public class AcceleratedBufferBuilder implements IAcceleratedVertexConsumer, VertexConsumer, LongSupplier { public static final long SHARING_SIZE = 4L * 4L * 4L + 4L * 3L * 4L; public static final IMemoryInterface SHARING_TRANSFORM = new SimpleMemoryInterface (0L, SHARING_SIZE); public static final IMemoryInterface SHARING_NORMAL = new SimpleMemoryInterface (4L * 4L * 4L, SHARING_SIZE); @Getter public final IMemoryInterface varyingOffset; @Getter public final IMemoryInterface varyingSharing; @Getter public final IMemoryInterface varyingMesh; @Getter public final IMemoryInterface varyingShouldCull; @Getter private final Map meshUploaders; @Getter private final StagingBufferPool .StagingBuffer vertexBuffer; @Getter private final StagingBufferPool .StagingBuffer varyingBuffer; @Getter private final ElementBufferPool .ElementSegment elementSegment; @Getter private final AcceleratedRingBuffers .Buffers buffer; @Getter private final ILayerFunction function; @EqualsAndHashCode.Include private final RenderType renderType; @Getter @EqualsAndHashCode.Include private final VertexLayout layout; @Getter private final IPolygonProgramDispatcher polygonProgramDispatcher; @Getter private final ICullingProgramDispatcher cullingProgramDispatcher; @Getter private final ITransformShaderProgramOverride transformOverride; @Getter private final IUploadingShaderProgramOverride uploadingOverride; @Getter private final VertexFormat.Mode mode; @Getter private final int polygonSize; @Getter private final int polygonElementCount; @Getter private final long vertexSize; private final IMemoryInterface posOffset; @Getter private final IMemoryInterface colorOffset; private final IMemoryInterface uv0Offset; @Getter private final IMemoryInterface uv1Offset; @Getter private final IMemoryInterface uv2Offset; private final IMemoryInterface normalOffset; private final Matrix4f cachedTransformValue; private final Matrix3f cachedNormalValue; private int elementCount; @Getter private int meshVertexCount; @Getter private int vertexCount; private long vertexAddress; private long sharingAddress; private int activeSharing; private int cachedSharing; @Getter private boolean outdated; private Matrix4f cachedTransform; private Matrix3f cachedNormal; public AcceleratedBufferBuilder( StagingBufferPool .StagingBuffer vertexBuffer, StagingBufferPool .StagingBuffer varyingBuffer, ElementBufferPool .ElementSegment elementSegment, AcceleratedRingBuffers .Buffers buffer, ILayerFunction layerFunction, RenderType renderType ) { var environment = buffer.getBufferEnvironment(); this.varyingOffset = new SimpleDynamicMemoryInterface (0L * 4L, this); this.varyingSharing = new SimpleDynamicMemoryInterface (1L * 4L, this); this.varyingMesh = new SimpleDynamicMemoryInterface (2L * 4L, this); this.varyingShouldCull = new SimpleDynamicMemoryInterface (3L * 4L, this); this.meshUploaders = new Reference2ObjectLinkedOpenHashMap<> (); this.vertexBuffer = vertexBuffer; this.varyingBuffer = varyingBuffer; this.elementSegment = elementSegment; this.buffer = buffer; this.function = layerFunction; this.renderType = renderType; this.layout = environment .getLayout (); this.polygonProgramDispatcher = environment .selectProcessingProgramDispatcher (this.renderType.mode); this.cullingProgramDispatcher = environment .selectCullingProgramDispatcher (this.renderType); this.transformOverride = environment .getTransformProgramOverride (this.renderType); this.uploadingOverride = environment .getUploadingProgramOverride (this.renderType); this.mode = this.renderType .mode; this.polygonSize = this.mode .primitiveLength; this.polygonElementCount = this.mode .indexCount (this.polygonSize); this.vertexSize = this.buffer .getVertexSize (); this.posOffset = this.layout .getElement (VertexFormatElement.POSITION); this.colorOffset = this.layout .getElement (VertexFormatElement.COLOR); this.uv0Offset = this.layout .getElement (VertexFormatElement.UV0); this.uv1Offset = this.layout .getElement (VertexFormatElement.UV1); this.uv2Offset = this.layout .getElement (VertexFormatElement.UV2); this.normalOffset = this.layout .getElement (VertexFormatElement.NORMAL); this.cachedTransformValue = new Matrix4f(); this.cachedNormalValue = new Matrix3f(); this.elementCount = 0; this.meshVertexCount = 0; this.vertexCount = 0; this.vertexAddress = -1; this.sharingAddress = -1; this.activeSharing = -1; this.cachedSharing = -1; this.cachedTransform = null; this.cachedNormal = null; } @Override public VertexConsumer addVertex( PoseStack.Pose pPose, float pX, float pY, float pZ ) { beginTransform( pPose.pose (), pPose.normal() ); return addVertex( pX, pY, pZ ); } @Override public VertexConsumer addVertex( float pX, float pY, float pZ ) { var vertexAddress = vertexBuffer .reserve(getVertexSize ()); var varyingAddress = varyingBuffer .reserve(getVaryingSize ()); this.vertexAddress = vertexAddress; posOffset .putFloat (vertexAddress + 0L, pX); posOffset .putFloat (vertexAddress + 4L, pY); posOffset .putFloat (vertexAddress + 8L, pZ); varyingOffset .putInt (varyingAddress, 0); varyingSharing .putInt (varyingAddress, activeSharing); varyingMesh .putInt (varyingAddress, -1); varyingShouldCull .putInt (varyingAddress, cullingProgramDispatcher.shouldCull() ? 1 : 0); transformOverride .uploadVarying (vertexAddress, 0); vertexCount ++; elementCount ++; if (elementCount >= polygonSize) { elementSegment.countElements(polygonElementCount); elementCount = 0; activeSharing = -1; } return this; } @Override public VertexConsumer setColor( int pRed, int pGreen, int pBlue, int pAlpha ) { if (vertexAddress == -1) { throw new IllegalStateException("Vertex not building!"); } colorOffset.putByte(vertexAddress + 0L, (byte) pRed); colorOffset.putByte(vertexAddress + 1L, (byte) pGreen); colorOffset.putByte(vertexAddress + 2L, (byte) pBlue); colorOffset.putByte(vertexAddress + 3L, (byte) pAlpha); return this; } @Override public VertexConsumer setUv(float pU, float pV) { if (vertexAddress == -1) { throw new IllegalStateException("Vertex not building!"); } uv0Offset.putFloat(vertexAddress + 0L, pU); uv0Offset.putFloat(vertexAddress + 4L, pV); return this; } @Override public VertexConsumer setUv1(int pU, int pV) { if (vertexAddress == -1) { throw new IllegalStateException("Vertex not building!"); } uv1Offset.putShort(vertexAddress + 0L, (short) pU); uv1Offset.putShort(vertexAddress + 2L, (short) pV); return this; } @Override public VertexConsumer setUv2(int pU, int pV) { if (vertexAddress == -1) { throw new IllegalStateException("Vertex not building!"); } uv2Offset.putShort(vertexAddress + 0L, (short) pU); uv2Offset.putShort(vertexAddress + 2L, (short) pV); return this; } @Override public VertexConsumer setNormal( PoseStack.Pose pPose, float pNormalX, float pNormalY, float pNormalZ ) { var normal = pPose.normal(); if (activeSharing == -1) { return VertexConsumer.super.setNormal( pPose, pNormalX, pNormalY, pNormalZ ); } if (!normal.equals(cachedNormal)) { SHARING_NORMAL.putMatrix3f(sharingAddress, normal); } return setNormal( pNormalX, pNormalY, pNormalZ ); } @Override public VertexConsumer setNormal( float pNormalX, float pNormalY, float pNormalZ ) { if (vertexAddress == -1) { throw new IllegalStateException("Vertex not building!"); } normalOffset.putNormal(vertexAddress + 0L, pNormalX); normalOffset.putNormal(vertexAddress + 1L, pNormalY); normalOffset.putNormal(vertexAddress + 2L, pNormalZ); return this; } @Override public void addVertex( float pX, float pY, float pZ, int pColor, float pU, float pV, int pPackedOverlay, int pPackedLight, float pNormalX, float pNormalY, float pNormalZ ) { var vertexAddress = vertexBuffer .reserve(getVertexSize ()); var varyingAddress = varyingBuffer .reserve(getVaryingSize ()); posOffset .putFloat (vertexAddress + 0L, pX); posOffset .putFloat (vertexAddress + 4L, pY); posOffset .putFloat (vertexAddress + 8L, pZ); colorOffset .putInt (vertexAddress, FastColor.ABGR32.fromArgb32(pColor)); uv0Offset .putFloat (vertexAddress + 0L, pU); uv0Offset .putFloat (vertexAddress + 4L, pV); uv1Offset .putInt (vertexAddress, pPackedOverlay); uv2Offset .putInt (vertexAddress, pPackedLight); normalOffset .putNormal (vertexAddress + 0L, pNormalX); normalOffset .putNormal (vertexAddress + 1L, pNormalY); normalOffset .putNormal (vertexAddress + 2L, pNormalZ); varyingOffset .putInt (varyingAddress, 0); varyingSharing .putInt (varyingAddress, activeSharing); varyingMesh .putInt (varyingAddress, -1); varyingShouldCull .putInt (varyingAddress, cullingProgramDispatcher.shouldCull() ? 1 : 0); transformOverride .uploadVarying (varyingAddress, 0); vertexCount ++; elementCount ++; if (elementCount >= polygonSize) { elementSegment.countElements(polygonElementCount); elementCount = 0; activeSharing = -1; } } @Override public void beginTransform(Matrix4f transform, Matrix3f normal) { if ( CoreFeature .shouldCacheIdenticalPose () && transform .equals (cachedTransform) && normal .equals (cachedNormal) ) { activeSharing = cachedSharing; return; } cachedTransform = cachedTransformValue .set (transform); cachedNormal = cachedNormalValue .set (normal); sharingAddress = buffer .reserveSharing (); cachedSharing = buffer .getSharing (); activeSharing = cachedSharing; SHARING_TRANSFORM .putMatrix4f(sharingAddress, transform); SHARING_NORMAL .putMatrix3f(sharingAddress, normal); } @Override public void endTransform() { cachedTransform = null; cachedNormal = null; activeSharing = -1; cachedSharing = -1; } @Override public void addClientMesh( ByteBuffer meshBuffer, int size, int color, int light, int overlay ) { var bufferSize = vertexSize * size; var vertexAddress = vertexBuffer .reserve(bufferSize); var varyingAddress = varyingBuffer .reserve(getVaryingSize() * size); MemoryUtil.memCopy( MemoryUtil.memAddress0(meshBuffer), vertexAddress, bufferSize ); colorOffset .putInt (vertexAddress, FastColor.ABGR32.fromArgb32(color)); uv1Offset .putInt (vertexAddress, overlay); uv2Offset .putInt (vertexAddress, light); varyingSharing .putInt (varyingAddress, activeSharing); varyingMesh .putInt (varyingAddress, -1); varyingShouldCull .putInt (varyingAddress, cullingProgramDispatcher.shouldCull() ? 1 : 0); transformOverride .uploadVarying (varyingAddress, 0); for (var i = 0; i < size; i ++) { varyingOffset.at(i).putInt(varyingAddress, i); } elementSegment.countElements(mode.indexCount(size)); vertexCount += size; } @Override public void addServerMesh( ServerMesh serverMesh, int color, int light, int overlay ) { if (CoreFeature.shouldUploadMeshImmediately()) { var meshSize = serverMesh .size (); var vertexAddress = vertexBuffer .reserve(getVertexSize () * meshSize); var varyingAddress = varyingBuffer .reserve(getVaryingSize () * meshSize); colorOffset .putInt (vertexAddress, FastColor.ABGR32.fromArgb32(color)); uv1Offset .putInt (vertexAddress, overlay); uv2Offset .putInt (vertexAddress, light); varyingSharing .putInt (varyingAddress, activeSharing); varyingMesh .putInt (varyingAddress, serverMesh .offset ()); varyingShouldCull .putInt (varyingAddress, cullingProgramDispatcher.shouldCull () ? 1 : 0); transformOverride .uploadVarying (varyingAddress, 0); for (var i = 0; i < meshSize; i ++) { varyingOffset.at(i).putInt(varyingAddress, i); } elementSegment.countElements(mode.indexCount(meshSize)); vertexCount += meshSize; return; } var meshSize = serverMesh .size (); var meshUploader = meshUploaders .get (serverMesh); if (meshUploader == null) { meshUploader = buffer .getMeshUploader (); meshUploader .setServerMesh (serverMesh); meshUploader .setUploadingOverride (uploadingOverride); meshUploaders .put (serverMesh, meshUploader); } elementSegment.countElements(mode.indexCount(meshSize)); meshVertexCount += meshSize; meshUploader.addUpload( color, light, overlay, activeSharing, cullingProgramDispatcher.shouldCull() ? 1 : 0 ); } @Override public void doRender( IAcceleratedRenderer renderer, T context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { renderer.render( this, context, transform, normal, light, overlay, color ); } @Override public VertexConsumer decorate(VertexConsumer buffer) { return buffer; } @Override public boolean isAccelerated() { return true; } @Override public RenderType getRenderType() { return renderType; } @Override public long getAsLong() { return getVaryingSize(); } public long getVaryingSize() { return transformOverride.getVaryingSize(); } public int getTotalVertexCount() { return vertexCount + meshVertexCount; } public boolean isEmpty() { return getTotalVertexCount() == 0; } public void setOutdated() { outdated = true; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/AcceleratedEntityOutlineGenerator.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders; import com.github.argon4w.acceleratedrendering.core.meshes.ServerMesh; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.experimental.ExtensionMethod; import java.nio.ByteBuffer; @AllArgsConstructor @EqualsAndHashCode (callSuper = false) @ExtensionMethod (VertexConsumerExtension.class) public class AcceleratedEntityOutlineGenerator extends AcceleratedVertexConsumerWrapper { private final VertexConsumer delegate; private final int color; @Override public VertexConsumer getDelegate() { return delegate; } @Override public VertexConsumer decorate(VertexConsumer buffer) { return new AcceleratedEntityOutlineGenerator( getDelegate () .getAccelerated () .decorate (buffer), color ); } @Override public void addClientMesh( ByteBuffer meshBuffer, int size, int color, int light, int overlay ) { getDelegate () .getAccelerated () .addClientMesh ( meshBuffer, size, this.color, light, overlay ); } @Override public void addServerMesh( ServerMesh serverMesh, int color, int light, int overlay ) { getDelegate () .getAccelerated () .addServerMesh ( serverMesh, this.color, light, overlay ); } @Override public VertexConsumer addVertex( float pX, float pY, float pZ ) { delegate.addVertex( pX, pY, pZ ).setColor(color); return this; } @Override public VertexConsumer addVertex( PoseStack.Pose pPose, float pX, float pY, float pZ ) { delegate.addVertex( pPose, pX, pY, pZ ).setColor(color); return this; } @Override public VertexConsumer setColor( int pRed, int pGreen, int pBlue, int pAlpha ) { return this; } @Override public VertexConsumer setUv1(int pU, int pV) { return this; } @Override public VertexConsumer setUv2(int pU, int pV) { return this; } @Override public VertexConsumer setNormal( float pNormalX, float pNormalY, float pNormalZ ) { return this; } @Override public VertexConsumer setNormal( PoseStack.Pose pPose, float pNormalX, float pNormalY, float pNormalZ ) { return this; } @Override public void addVertex( float x, float y, float z, int color, float u, float v, int packedOverlay, int packedLight, float normalX, float normalY, float normalZ ) { getDelegate().addVertex( x, y, z, this.color, u, v, packedOverlay, packedLight, normalX, normalY, normalZ ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/AcceleratedSheetedDecalTextureGenerator.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders; import com.github.argon4w.acceleratedrendering.core.meshes.ServerMesh; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.EqualsAndHashCode; import lombok.experimental.ExtensionMethod; import net.minecraft.core.Direction; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.joml.Vector3f; import java.nio.ByteBuffer; @ExtensionMethod (VertexConsumerExtension.class) @EqualsAndHashCode ( onlyExplicitlyIncluded = true, callSuper = false ) public class AcceleratedSheetedDecalTextureGenerator extends AcceleratedVertexConsumerWrapper { @EqualsAndHashCode.Include private final VertexConsumer delegate; @EqualsAndHashCode.Include private final Matrix4f cameraInverse; private final Matrix3f normalInverse; private final float textureScale; private final Vector3f cachedCamera; private final Vector3f cachedNormal; private float vertexX; private float vertexY; private float vertexZ; public AcceleratedSheetedDecalTextureGenerator( VertexConsumer delegate, Matrix4f cameraInverse, Matrix3f normalInverse, float textureScale ) { this.delegate = delegate; this.cameraInverse = cameraInverse; this.normalInverse = normalInverse; this.textureScale = textureScale; this.cachedCamera = new Vector3f(); this.cachedNormal = new Vector3f(); this.vertexX = 0; this.vertexY = 0; this.vertexZ = 0; } @Override protected VertexConsumer getDelegate() { return delegate; } @Override public VertexConsumer decorate(VertexConsumer buffer) { return new AcceleratedSheetedDecalTextureGenerator( getDelegate () .getAccelerated () .decorate (buffer), cameraInverse, normalInverse, textureScale ); } @Override public void addClientMesh( ByteBuffer meshBuffer, int size, int color, int light, int overlay ) { getDelegate () .getAccelerated () .addClientMesh ( meshBuffer, size, -1, light, overlay ); } @Override public void addServerMesh( ServerMesh serverMesh, int color, int light, int overlay ) { getDelegate () .getAccelerated () .addServerMesh ( serverMesh, -1, light, overlay ); } @Override public VertexConsumer addVertex( float pX, float pY, float pZ ) { vertexX = pX; vertexY = pY; vertexZ = pZ; delegate.addVertex( pX, pY, pZ ); return this; } @Override public VertexConsumer setUv(float pU, float pV) { return this; } @Override public VertexConsumer setColor( int pRed, int pGreen, int pBlue, int pAlpha ) { delegate.setColor(-1); return this; } @Override public VertexConsumer setNormal( float pNormalX, float pNormalY, float pNormalZ ) { delegate.setNormal( pNormalX, pNormalY, pNormalZ ); var normal = normalInverse.transform( pNormalX, pNormalY, pNormalZ, cachedNormal ); var camera = cameraInverse.transformPosition( vertexX, vertexY, vertexZ, cachedCamera ); var direction = Direction.getNearest( normal.x(), normal.y(), normal.z() ); camera .rotateY((float) Math.PI); camera .rotateX((float) (- Math.PI / 2)); camera .rotate (direction.getRotation()); delegate.setUv (-camera.x() * textureScale, -camera.y() * textureScale); return this; } @Override public void addVertex( float x, float y, float z, int color, float u, float v, int packedOverlay, int packedLight, float normalX, float normalY, float normalZ ) { this .addVertex (x, y, z) .setColor (color) .setUv (u, v) .setOverlay (packedOverlay) .setLight (packedLight) .setNormal (normalX, normalY, normalZ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/AcceleratedSpriteCoordinateExpander.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.texture.TextureAtlasSprite; @AllArgsConstructor @EqualsAndHashCode (callSuper = false) @ExtensionMethod (VertexConsumerExtension.class) public class AcceleratedSpriteCoordinateExpander extends AcceleratedVertexConsumerWrapper { private final VertexConsumer delegate; private final TextureAtlasSprite sprite; @Override public VertexConsumer getDelegate() { return delegate; } @Override public VertexConsumer decorate(VertexConsumer buffer) { return new AcceleratedSpriteCoordinateExpander( getDelegate () .getAccelerated () .decorate (buffer), sprite ); } @Override public VertexConsumer setUv(float pU, float pV) { delegate.setUv( sprite.getU(pU), sprite.getV(pV) ); return this; } @Override public void addVertex( float pX, float pY, float pZ, int pColor, float pU, float pV, int pPackedOverlay, int pPackedLight, float pNormalX, float pNormalY, float pNormalZ ) { delegate.addVertex( pX, pY, pZ, pColor, sprite.getU(pU), sprite.getV(pV), pPackedOverlay, pPackedLight, pNormalX, pNormalY, pNormalZ ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/AcceleratedVertexConsumerWrapper.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout; import com.github.argon4w.acceleratedrendering.core.meshes.ServerMesh; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.RenderType; import org.joml.Matrix3f; import org.joml.Matrix4f; import java.nio.ByteBuffer; @ExtensionMethod(VertexConsumerExtension.class) public abstract class AcceleratedVertexConsumerWrapper implements IAcceleratedVertexConsumer, VertexConsumer { @Override public abstract VertexConsumer decorate (VertexConsumer buffer); protected abstract VertexConsumer getDelegate (); @Override public void beginTransform(Matrix4f transform, Matrix3f normal) { getDelegate () .getAccelerated () .beginTransform (transform, normal); } @Override public void endTransform() { getDelegate() .getAccelerated () .endTransform (); } @Override public boolean isAccelerated() { return getDelegate () .getAccelerated () .isAccelerated (); } @Override public RenderType getRenderType() { return getDelegate () .getAccelerated () .getRenderType (); } @Override public VertexLayout getLayout() { return getDelegate () .getAccelerated () .getLayout (); } @Override public int getPolygonSize() { return getDelegate () .getAccelerated () .getPolygonSize (); } @Override public void addClientMesh( ByteBuffer meshBuffer, int size, int color, int light, int overlay ) { getDelegate () .getAccelerated () .addClientMesh ( meshBuffer, size, color, light, overlay ); } @Override public void addServerMesh( ServerMesh serverMesh, int color, int light, int overlay ) { getDelegate () .getAccelerated () .addServerMesh ( serverMesh, color, light, overlay ); } @Override public void doRender( IAcceleratedRenderer renderer, T context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { renderer.render( this, context, transform, normal, light, overlay, color ); } @Override public VertexConsumer addVertex( float x, float y, float z ) { getDelegate().addVertex( x, y, z ); return this; } @Override public VertexConsumer addVertex( PoseStack.Pose pose, float x, float y, float z ) { getDelegate().addVertex( pose, x, y, z ); return this; } @Override public VertexConsumer setColor( int red, int green, int blue, int alpha ) { getDelegate().setColor( red, green, blue, alpha ); return this; } @Override public VertexConsumer setUv(float u, float v) { getDelegate().setUv(u, v); return this; } @Override public VertexConsumer setUv1(int u, int v) { getDelegate().setUv1(u, v); return this; } @Override public VertexConsumer setUv2(int u, int v) { getDelegate().setUv2(u, v); return this; } @Override public VertexConsumer setNormal( float normalX, float normalY, float normalZ ) { getDelegate().setNormal( normalX, normalY, normalZ ); return this; } @Override public VertexConsumer setNormal( PoseStack.Pose pose, float normalX, float normalY, float normalZ ) { getDelegate().setNormal( pose, normalX, normalY, normalZ ); return this; } @Override public void addVertex( float x, float y, float z, int color, float u, float v, int packedOverlay, int packedLight, float normalX, float normalY, float normalZ ) { getDelegate().addVertex( x, y, z, color, u, v, packedOverlay, packedLight, normalX, normalY, normalZ ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/BufferSourceExtension.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders; import net.minecraft.client.renderer.MultiBufferSource; public class BufferSourceExtension { public static IAcceleratableBufferSource getAcceleratable(MultiBufferSource in) { return (IAcceleratableBufferSource) in; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/IAcceleratableBufferSource.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAcceleratedBufferSource; import java.util.function.Supplier; public interface IAcceleratableBufferSource { Supplier getBoundAcceleratedBufferSource (); boolean isBufferSourceAcceleratable (); void bindAcceleratedBufferSource (Supplier bufferSource); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/IAcceleratedVertexConsumer.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IBufferDecorator; import com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout; import com.github.argon4w.acceleratedrendering.core.meshes.ServerMesh; import com.github.argon4w.acceleratedrendering.core.utils.TextureUtils; import com.mojang.blaze3d.platform.NativeImage; import com.mojang.blaze3d.vertex.VertexConsumer; import net.minecraft.client.renderer.RenderType; import org.joml.Matrix3f; import org.joml.Matrix4f; import java.nio.ByteBuffer; public interface IAcceleratedVertexConsumer extends IBufferDecorator, IBufferGraph { @Override default VertexConsumer decorate(VertexConsumer buffer) { throw new UnsupportedOperationException("Unsupported Operation."); } default void beginTransform(Matrix4f transform, Matrix3f normal) { throw new UnsupportedOperationException("Unsupported Operation."); } default void endTransform() { throw new UnsupportedOperationException("Unsupported Operation."); } default boolean isAccelerated() { throw new UnsupportedOperationException("Unsupported Operation."); } default RenderType getRenderType() { throw new UnsupportedOperationException("Unsupported Operation."); } default VertexLayout getLayout() { throw new UnsupportedOperationException("Unsupported Operation."); } default int getPolygonSize() { throw new UnsupportedOperationException("Unsupported Operation."); } default NativeImage downloadTexture() { return TextureUtils.downloadTexture(getRenderType(), 0); } default void doRender( IAcceleratedRenderer renderer, T context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { throw new UnsupportedOperationException("Unsupported Operation."); } default void addClientMesh( ByteBuffer meshBuffer, int size, int color, int light, int overlay ) { throw new UnsupportedOperationException("Unsupported Operation."); } default void addServerMesh( ServerMesh serverMesh, int color, int light, int overlay ) { throw new UnsupportedOperationException("Unsupported Operation."); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/IBufferGraph.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders; public interface IBufferGraph { } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/builders/VertexConsumerExtension.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAccelerationHolder; import com.mojang.blaze3d.vertex.VertexConsumer; public class VertexConsumerExtension { public static IAcceleratedVertexConsumer getAccelerated(VertexConsumer in) { return (IAcceleratedVertexConsumer) in; } public static IAccelerationHolder getHolder(VertexConsumer in) { return (IAccelerationHolder) in; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/LayerDrawType.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers; public enum LayerDrawType { TRANSLUCENT, OPAQUE, ALL } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/LayerKey.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers; import net.minecraft.client.renderer.RenderType; public record LayerKey(int layer, RenderType renderType) { } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/functions/CustomLayerFunction.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.functions; import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet; import java.util.Set; import java.util.function.Consumer; public class CustomLayerFunction implements ILayerFunction, Consumer { private final Set before; private final Set after; public CustomLayerFunction() { this.before = new ReferenceLinkedOpenHashSet<>(); this.after = new ReferenceLinkedOpenHashSet<>(); } @Override public void addBefore(Runnable before) { this.before.add(before); } @Override public void addAfter(Runnable after) { this.after.add(after); } @Override public void runBefore() { before.forEach(this); } @Override public void runAfter() { after.forEach(this); } @Override public void reset() { before .clear(); after .clear(); } @Override public void accept(Runnable runnable) { runnable.run(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/functions/EmptyLayerFunction.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.functions; public class EmptyLayerFunction implements ILayerFunction { public static final ILayerFunction INSTANCE = new EmptyLayerFunction(); @Override public void addBefore(Runnable before) { } @Override public void addAfter(Runnable after) { } @Override public void runBefore() { } @Override public void runAfter() { } @Override public void reset() { } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/functions/ILayerFunction.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.functions; public interface ILayerFunction { void addBefore (Runnable before); void addAfter (Runnable after); void runBefore (); void runAfter (); void reset (); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/storage/ILayerContexts.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.DrawContextPool; public interface ILayerContexts extends Iterable { void add (DrawContextPool.DrawContext drawContext); void reset (); void prepare (); boolean isEmpty (); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/storage/ILayerStorage.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType; public interface ILayerStorage { ILayerContexts get (LayerDrawType type); void reset (); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/storage/LayerStorageType.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.sorted.SortedLayerStorage; public enum LayerStorageType { SORTED, SEPARATED; public ILayerStorage create(int size) { return create(this, size); } public static ILayerStorage create(LayerStorageType type, int size) { return switch (type) { case SORTED -> new SortedLayerStorage (size); case SEPARATED -> new SeparatedLayerStorage(size); }; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/storage/SeparatedLayerStorage.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.DrawContextPool; import com.google.common.collect.Iterators; import java.util.Iterator; public class SeparatedLayerStorage implements ILayerStorage { private final ILayerContexts[] contexts; private final ILayerContexts opaqueContexts; private final ILayerContexts translucentContexts; public SeparatedLayerStorage(int size) { this.contexts = new ILayerContexts [3]; this.opaqueContexts = new SimpleLayerContexts (size); this.translucentContexts = new SimpleLayerContexts (size); contexts[0] = this.translucentContexts; contexts[1] = this.opaqueContexts; contexts[2] = new AllContexts(); } @Override public ILayerContexts get(LayerDrawType type) { return contexts[type.ordinal()]; } @Override public void reset() { opaqueContexts .reset(); translucentContexts .reset(); } public class AllContexts implements ILayerContexts { @Override public void add(DrawContextPool.DrawContext drawContext) { throw new UnsupportedOperationException("Unsupported Operation."); } @Override public void reset() { opaqueContexts .reset(); translucentContexts .reset(); } @Override public void prepare() { } @Override public boolean isEmpty() { return opaqueContexts .isEmpty() && translucentContexts .isEmpty(); } @Override public Iterator iterator() { return Iterators.concat( opaqueContexts .iterator(), translucentContexts .iterator() ); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/storage/SimpleLayerContexts.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.DrawContextPool; import it.unimi.dsi.fastutil.objects.ReferenceArrayList; import java.util.Iterator; public class SimpleLayerContexts implements ILayerContexts { protected final ReferenceArrayList contexts; public SimpleLayerContexts(int size) { contexts = new ReferenceArrayList<>(size); } @Override public void add(DrawContextPool.DrawContext drawContext) { contexts.add(drawContext); } @Override public void reset() { contexts.clear(); } @Override public void prepare() { } @Override public boolean isEmpty() { return contexts.isEmpty(); } @Override public Iterator iterator() { return contexts.iterator(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/storage/empty/EmptyLayerContexts.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.empty; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.ILayerContexts; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.DrawContextPool; import com.github.argon4w.acceleratedrendering.core.utils.EmptyIterator; import java.util.Iterator; public class EmptyLayerContexts implements ILayerContexts { public static final EmptyLayerContexts INSTANCE = new EmptyLayerContexts(); @Override public void add(DrawContextPool.DrawContext drawContext) { } @Override public void reset() { } @Override public void prepare() { } @Override public boolean isEmpty() { return true; } @Override public Iterator iterator() { return EmptyIterator.of(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/storage/empty/EmptyLayerStorage.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.empty; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.ILayerContexts; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.ILayerStorage; public class EmptyLayerStorage implements ILayerStorage { public static final EmptyLayerStorage INSTANCE = new EmptyLayerStorage(); @Override public ILayerContexts get(LayerDrawType type) { return EmptyLayerContexts.INSTANCE; } @Override public void reset() { } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/storage/sorted/SortedLayerContexts.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.sorted; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.SimpleLayerContexts; import java.util.Comparator; public class SortedLayerContexts extends SimpleLayerContexts { public SortedLayerContexts(int size) { super(size); } @Override public void prepare() { contexts.sort(Comparator.naturalOrder()); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/layers/storage/sorted/SortedLayerStorage.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.sorted; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.ILayerContexts; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.ILayerStorage; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.storage.SimpleLayerContexts; public class SortedLayerStorage implements ILayerStorage { private final SimpleLayerContexts contexts; public SortedLayerStorage(int size) { this.contexts = new SortedLayerContexts(size); } @Override public ILayerContexts get(LayerDrawType type) { return contexts; } @Override public void reset() { contexts.reset(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/DrawContextPool.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools; import com.github.argon4w.acceleratedrendering.core.backends.buffers.MappedBuffer; import com.github.argon4w.acceleratedrendering.core.buffers.memory.IMemoryInterface; import com.github.argon4w.acceleratedrendering.core.buffers.memory.SimpleMemoryInterface; import com.github.argon4w.acceleratedrendering.core.utils.SimpleResetPool; import com.mojang.blaze3d.vertex.VertexFormat; import lombok.Getter; import lombok.Setter; import net.minecraft.client.renderer.RenderType; import static org.lwjgl.opengl.GL46.*; public class DrawContextPool extends SimpleResetPool { public DrawContextPool(int size) { super(size, new MappedBuffer(20L * size)); } @Override protected DrawContext create(MappedBuffer buffer, int i) { return new DrawContext(i); } @Override protected void reset(DrawContext drawContext) { } @Override protected void delete(DrawContext drawContext) { } @Override public void delete() { getContext().delete(); } @Override public DrawContext fail() { expand(); return get(); } @Getter @Setter public class DrawContext implements Comparable { public static final int ELEMENT_COUNT_INDEX = 0; public static final IMemoryInterface INDIRECT_COUNT = new SimpleMemoryInterface(0L * 4L, 4); public static final IMemoryInterface INDIRECT_INSTANCE_COUNT = new SimpleMemoryInterface(1L * 4L, 4); public static final IMemoryInterface INDIRECT_FIRST_INDEX = new SimpleMemoryInterface(2L * 4L, 4); public static final IMemoryInterface INDIRECT_BASE_INDEX = new SimpleMemoryInterface(3L * 4L, 4); public static final IMemoryInterface INDIRECT_BASE_INSTANCE = new SimpleMemoryInterface(4L * 4L, 4); private final long commandOffset; private RenderType renderType; public DrawContext(int index) { this.commandOffset = index * 20L; this.renderType = null; var address = context .reserve(20L); INDIRECT_COUNT .putInt (address, 0); INDIRECT_INSTANCE_COUNT .putInt (address, 1); INDIRECT_FIRST_INDEX .putInt (address, 0); INDIRECT_BASE_INDEX .putInt (address, 0); INDIRECT_BASE_INSTANCE .putInt (address, 0); } public void bindComputeBuffers(ElementBufferPool.ElementSegment elementSegmentIn) { var elementOffset = elementSegmentIn .getOffset (); var commandAddress = context .addressAt (commandOffset); INDIRECT_COUNT .putInt (commandAddress, 0); INDIRECT_FIRST_INDEX.putInt (commandAddress, elementOffset / 4); context .bindRange ( GL_ATOMIC_COUNTER_BUFFER, ELEMENT_COUNT_INDEX, commandOffset, 4 ); } public void drawElements(VertexFormat.Mode mode) { glDrawElementsIndirect( mode.asGLMode, GL_UNSIGNED_INT, commandOffset ); } @Override public int compareTo(DrawContext that) { return Boolean.compare( this.renderType.sortOnUpload, that.renderType.sortOnUpload ); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/ElementBufferPool.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools; import com.github.argon4w.acceleratedrendering.core.backends.GLConstants; import com.github.argon4w.acceleratedrendering.core.backends.buffers.MutableBuffer; import com.github.argon4w.acceleratedrendering.core.utils.MutableSize; import com.github.argon4w.acceleratedrendering.core.utils.SimpleResetPool; import lombok.Getter; import org.apache.commons.lang3.mutable.MutableLong; import static org.lwjgl.opengl.GL44.GL_DYNAMIC_STORAGE_BIT; public class ElementBufferPool extends SimpleResetPool { @Getter private final MutableBuffer elementBufferOut; private final MutableLong elementBufferSegments; private final MutableLong elementBufferOutSize; private final MutableLong elementBufferOutUsedSize; public ElementBufferPool(int size) { super(size, null); this.elementBufferOut = new MutableBuffer (64L * size, GL_DYNAMIC_STORAGE_BIT); this.elementBufferSegments = new MutableLong (0L); this.elementBufferOutSize = new MutableLong (64L * size); this.elementBufferOutUsedSize = new MutableLong (64L * size); } public void prepare() { elementBufferOut.resizeTo(elementBufferOutSize.getValue()); } @Override public void reset() { elementBufferOutUsedSize.setValue (0L); elementBufferSegments .setValue (0L); super .reset (); } @Override public void delete() { elementBufferOut.delete(); } @Override protected ElementSegment create(Void value, int i) { return new ElementSegment(); } @Override protected void reset(ElementSegment elementSegment) { elementSegment.reset(); } @Override protected void delete(ElementSegment elementSegment) { } @Override public boolean test(ElementSegment elementSegment) { return elementBufferOutUsedSize.addAndGet(elementSegment.getSize()) <= GLConstants.MAX_SHADER_STORAGE_BLOCK_SIZE; } @Getter public class ElementSegment extends MutableSize { private long bytes; private long offset; public ElementSegment() { super(64L); this.bytes = 0L; this.offset = -1L; } @Override public void onExpand(long bytes) { elementBufferOutSize .add(bytes); elementBufferOutUsedSize.add(bytes); } private void reset() { bytes = 0L; } public void allocateOffset() { offset = elementBufferSegments.getAndAdd(size); } public void countElements(int count) { bytes += count * 4L; if (bytes > size) { resize(bytes); } } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/StagingBufferPool.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools; import com.github.argon4w.acceleratedrendering.core.backends.GLConstants; import com.github.argon4w.acceleratedrendering.core.backends.buffers.MappedBuffer; import com.github.argon4w.acceleratedrendering.core.backends.buffers.MutableBuffer; import com.github.argon4w.acceleratedrendering.core.utils.SimpleResetPool; import lombok.Getter; import org.apache.commons.lang3.mutable.MutableLong; import static org.lwjgl.opengl.GL44.GL_DYNAMIC_STORAGE_BIT; public class StagingBufferPool extends SimpleResetPool { @Getter private final MutableBuffer bufferOut; private final MutableLong bufferSegments; private final MutableLong bufferOutSize; private final MutableLong bufferOutUsedSize; public StagingBufferPool(int size) { super(size, null); this.bufferOut = new MutableBuffer (64L * size, GL_DYNAMIC_STORAGE_BIT); this.bufferSegments = new MutableLong (0L); this.bufferOutSize = new MutableLong (64L * size); this.bufferOutUsedSize = new MutableLong (0L); } public void prepare() { bufferOut.resizeTo(bufferOutSize.getValue()); } @Override public void delete() { bufferOut .delete(); super .delete(); } @Override public void reset() { bufferOutUsedSize .setValue (0L); bufferSegments .setValue (0L); super .reset (); } @Override protected StagingBuffer create(Void context, int i) { return new StagingBuffer(); } @Override protected void reset(StagingBuffer stagingBuffer) { stagingBuffer.poolReset(); } @Override protected void delete(StagingBuffer stagingBuffer) { stagingBuffer.poolDelete(); } @Override public boolean test(StagingBuffer stagingBuffer) { return bufferOutUsedSize.addAndGet(stagingBuffer.getSize()) <= GLConstants.MAX_SHADER_STORAGE_BLOCK_SIZE; } @Getter public class StagingBuffer extends MappedBuffer { private long offset; public StagingBuffer() { super(64L); this.offset = -1; } @Override public void onExpand(long bytes) { bufferOutSize .add(bytes); bufferOutUsedSize .add(bytes); } @Override public void delete() { throw new IllegalStateException("Pooled buffers cannot be deleted directly."); } @Override public void reset() { throw new IllegalStateException("Pooled buffers cannot be reset directly."); } private void poolDelete() { super.delete(); } private void poolReset() { super.reset(); } public void allocateOffset() { offset = bufferSegments.getAndAdd(position); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/meshes/FlattenMeshInfoCache.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.util.Arrays; public class FlattenMeshInfoCache implements IMeshInfoCache { public static final VarHandle HANDLE = MethodHandles.arrayElementVarHandle(int[].class).withInvokeExactBehavior(); public static final int MESH_INFO_SIZE = 5; public static final int COLOR_OFFSET = 0; public static final int LIGHT_OFFSET = 1; public static final int OVERLAY_OFFSET = 2; public static final int SHARING_OFFSET = 3; public static final int SHOULD_CULL_OFFSET = 4; private int[] cache; private int size; private int count; public FlattenMeshInfoCache() { this.size = 128; this.cache = new int[this.size * MESH_INFO_SIZE]; this.count = 0; } @Override public void reset() { count = 0; } @Override public void delete() { } @Override public void setup( int color, int light, int overlay, int sharing, int shouldCull ) { if (count >= size) { size = size * 2; cache = Arrays.copyOf(cache, size * MESH_INFO_SIZE); } var infoIndex = count * MESH_INFO_SIZE; HANDLE.set(cache, infoIndex + COLOR_OFFSET, color); HANDLE.set(cache, infoIndex + LIGHT_OFFSET, light); HANDLE.set(cache, infoIndex + OVERLAY_OFFSET, overlay); HANDLE.set(cache, infoIndex + SHARING_OFFSET, sharing); HANDLE.set(cache, infoIndex + SHOULD_CULL_OFFSET, shouldCull); count ++; } @Override public int getMeshCount() { return count; } @Override public int getSharing(int i) { return (int) HANDLE.get(cache, i * MESH_INFO_SIZE + SHARING_OFFSET); } @Override public int getShouldCull(int i) { return (int) HANDLE.get(cache, i * MESH_INFO_SIZE + SHOULD_CULL_OFFSET); } @Override public int getColor(int i) { return (int) HANDLE.get(cache, i * MESH_INFO_SIZE + COLOR_OFFSET); } @Override public int getLight(int i) { return (int) HANDLE.get(cache, i * MESH_INFO_SIZE + LIGHT_OFFSET); } @Override public int getOverlay(int i) { return (int) HANDLE.get(cache, i * MESH_INFO_SIZE + OVERLAY_OFFSET); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/meshes/IMeshInfoCache.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes; public interface IMeshInfoCache { void reset (); void delete (); void setup (int color, int light, int overlay, int sharing, int shouldCull); int getMeshCount (); int getSharing (int i); int getShouldCull (int i); int getColor (int i); int getLight (int i); int getOverlay (int i); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/meshes/MeshInfoCacheType.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes; public enum MeshInfoCacheType { SIMPLE, HANDLE, UNSAFE; public IMeshInfoCache create() { return create(this); } public static IMeshInfoCache create(MeshInfoCacheType type) { return switch (type) { case SIMPLE -> new SimpleMeshInfoCache (); case HANDLE -> new FlattenMeshInfoCache (); case UNSAFE -> new UnsafeMemoryMeshInfoCache (); }; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/meshes/MeshUploaderPool.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.backends.buffers.MappedBuffer; import com.github.argon4w.acceleratedrendering.core.buffers.memory.IMemoryInterface; import com.github.argon4w.acceleratedrendering.core.buffers.memory.SimpleDynamicMemoryInterface; import com.github.argon4w.acceleratedrendering.core.meshes.ServerMesh; import com.github.argon4w.acceleratedrendering.core.programs.overrides.IUploadingShaderProgramOverride; import com.github.argon4w.acceleratedrendering.core.utils.SimpleResetPool; import lombok.Getter; import lombok.Setter; import net.minecraft.util.FastColor; import java.util.function.LongSupplier; import static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BUFFER; public class MeshUploaderPool extends SimpleResetPool { public MeshUploaderPool() { super(128, null); } @Override protected MeshUploader create(Void context, int i) { return new MeshUploader(); } @Override protected void reset(MeshUploader meshUploader) { meshUploader.reset(); } @Override protected void delete(MeshUploader meshUploader) { meshUploader.delete(); } @Override public MeshUploader fail() { expand(); return get(); } public static class MeshUploader implements LongSupplier { public static final int MESH_INFO_BUFFER_INDEX = 8; public final IMemoryInterface meshInfoSharing; public final IMemoryInterface meshInfoNoCull; public final IMemoryInterface meshInfoColor; public final IMemoryInterface meshInfoOverlay; public final IMemoryInterface meshInfoLight; private final MappedBuffer meshInfoBuffer; @Getter private final IMeshInfoCache meshInfos; @Getter @Setter private ServerMesh serverMesh; @Getter @Setter private IUploadingShaderProgramOverride uploadingOverride; public MeshUploader() { this.meshInfoSharing = new SimpleDynamicMemoryInterface (0L * 4L, this); this.meshInfoNoCull = new SimpleDynamicMemoryInterface (1L * 4L, this); this.meshInfoColor = new SimpleDynamicMemoryInterface (2L * 4L, this); this.meshInfoOverlay = new SimpleDynamicMemoryInterface (3L * 4L, this); this.meshInfoLight = new SimpleDynamicMemoryInterface (4L * 4L, this); this.meshInfoBuffer = new MappedBuffer (64L); this.meshInfos = CoreFeature.createMeshInfoCache (); this.serverMesh = null; this.uploadingOverride = null; } public void addUpload( int color, int light, int overlay, int sharing, int shouldCull ) { meshInfos.setup( color, light, overlay, sharing, shouldCull ); } public void upload() { var meshCount = meshInfos .getMeshCount (); var meshInfoAddress = meshInfoBuffer.reserve (getAsLong() * meshCount); for (var i = 0; i < meshCount; i ++) { meshInfoSharing .at(i) .putInt (meshInfoAddress, meshInfos .getSharing (i)); meshInfoNoCull .at(i) .putInt (meshInfoAddress, meshInfos .getShouldCull (i)); meshInfoColor .at(i) .putInt (meshInfoAddress, FastColor.ABGR32 .fromArgb32 (meshInfos.getColor(i))); meshInfoOverlay .at(i) .putInt (meshInfoAddress, meshInfos .getOverlay (i)); meshInfoLight .at(i) .putInt (meshInfoAddress, meshInfos .getLight (i)); uploadingOverride .uploadMeshInfo (meshInfoAddress, i); } } public void bindBuffers() { meshInfoBuffer.bindBase(GL_SHADER_STORAGE_BUFFER, MESH_INFO_BUFFER_INDEX); } public void reset() { meshInfos .reset(); meshInfoBuffer .reset(); } public void delete() { meshInfos .delete(); meshInfoBuffer .delete(); } @Override public long getAsLong() { return uploadingOverride.getMeshInfoSize(); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/meshes/SimpleMeshInfo.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes; import com.github.argon4w.acceleratedrendering.core.utils.SimpleCachedArray; import lombok.Getter; @Getter public class SimpleMeshInfo implements SimpleCachedArray.Element { private int color; private int light; private int overlay; private int sharing; private int shouldCull; public SimpleMeshInfo() { this.color = -1; this.light = -1; this.overlay = -1; this.sharing = -1; } public void setupMeshInfo( int color, int light, int overlay, int sharing, int shouldCull ) { this.color = color; this.light = light; this.overlay = overlay; this.sharing = sharing; this.shouldCull = shouldCull; } @Override public void reset() { } @Override public void delete() { } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/meshes/SimpleMeshInfoCache.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes; import com.github.argon4w.acceleratedrendering.core.utils.SimpleCachedArray; import java.util.function.IntFunction; public class SimpleMeshInfoCache implements IMeshInfoCache, IntFunction { private final SimpleCachedArray meshInfos; public SimpleMeshInfoCache() { this.meshInfos = new SimpleCachedArray<>(128, this); } @Override public void setup( int color, int light, int overlay, int sharing, int shouldCull ) { meshInfos.get().setupMeshInfo( color, light, overlay, sharing, shouldCull ); } @Override public void reset() { meshInfos.reset(); } @Override public void delete() { meshInfos.delete(); } @Override public int getMeshCount() { return meshInfos.getCursor(); } @Override public int getSharing(int i) { return meshInfos.at(i).getSharing(); } @Override public int getShouldCull(int i) { return meshInfos.at(i).getShouldCull(); } @Override public int getColor(int i) { return meshInfos.at(i).getColor(); } @Override public int getLight(int i) { return meshInfos.at(i).getLight(); } @Override public int getOverlay(int i) { return meshInfos.at(i).getOverlay(); } @Override public SimpleMeshInfo apply(int value) { return new SimpleMeshInfo(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/pools/meshes/UnsafeMemoryMeshInfoCache.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes; import io.netty.util.internal.shaded.org.jctools.util.UnsafeAccess; import sun.misc.Unsafe; public class UnsafeMemoryMeshInfoCache implements IMeshInfoCache { public static final Unsafe UNSAFE = UnsafeAccess.UNSAFE; public static final long MESH_INFO_SIZE = 5L * 4L; public static final long COLOR_OFFSET = 0L * 4L; public static final long LIGHT_OFFSET = 1L * 4L; public static final long OVERLAY_OFFSET = 2L * 4L; public static final long SHARING_OFFSET = 3L * 4L; public static final long SHOULD_CULL_OFFSET = 4L * 4L; private long address; private int size; private int count; public UnsafeMemoryMeshInfoCache() { this.size = 128; this.address = UNSAFE.allocateMemory(this.size * MESH_INFO_SIZE); this.count = 0; } @Override public void reset() { count = 0; } @Override public void delete() { UNSAFE.freeMemory(address); } @Override public void setup( int color, int light, int overlay, int sharing, int shouldCull ) { if (count >= size) { size = size * 2; address = UNSAFE.reallocateMemory(address, size * MESH_INFO_SIZE); } var infoAddress = address + count * MESH_INFO_SIZE; UNSAFE.putInt(infoAddress + COLOR_OFFSET, color); UNSAFE.putInt(infoAddress + LIGHT_OFFSET, light); UNSAFE.putInt(infoAddress + OVERLAY_OFFSET, overlay); UNSAFE.putInt(infoAddress + SHARING_OFFSET, sharing); UNSAFE.putInt(infoAddress + SHOULD_CULL_OFFSET, shouldCull); count ++; } @Override public int getMeshCount() { return count; } @Override public int getSharing(int i) { return UNSAFE.getInt(address + i * MESH_INFO_SIZE + SHARING_OFFSET); } @Override public int getShouldCull(int i) { return UNSAFE.getInt(address + i * MESH_INFO_SIZE + SHOULD_CULL_OFFSET); } @Override public int getColor(int i) { return UNSAFE.getInt(address + i * MESH_INFO_SIZE + COLOR_OFFSET); } @Override public int getLight(int i) { return UNSAFE.getInt(address + i * MESH_INFO_SIZE + LIGHT_OFFSET); } @Override public int getOverlay(int i) { return UNSAFE.getInt(address + i * MESH_INFO_SIZE + OVERLAY_OFFSET); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/renderers/DecoratedRenderer.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.AllArgsConstructor; import org.joml.Matrix3f; import org.joml.Matrix4f; @AllArgsConstructor public class DecoratedRenderer implements IAcceleratedRenderer { private final IAcceleratedRenderer renderer; private final IBufferDecorator bufferDecorator; @Override public void render( VertexConsumer vertexConsumer, T context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { renderer.render( bufferDecorator.decorate(vertexConsumer), context, transform, normal, light, overlay, color ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/renderers/IAcceleratedRenderer.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers; import com.mojang.blaze3d.vertex.VertexConsumer; import org.joml.Matrix3f; import org.joml.Matrix4f; public interface IAcceleratedRenderer { void render(VertexConsumer vertexConsumer, T context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/renderers/IBufferDecorator.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers; import com.mojang.blaze3d.vertex.VertexConsumer; public interface IBufferDecorator { VertexConsumer decorate(VertexConsumer buffer); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/accelerated/renderers/SheetedDecalTextureRenderer.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedSheetedDecalTextureGenerator; import com.github.argon4w.acceleratedrendering.core.utils.FuzzyMatrix4f; import com.mojang.blaze3d.vertex.VertexConsumer; import org.joml.Matrix3f; import org.joml.Matrix4f; public class SheetedDecalTextureRenderer implements IAcceleratedRenderer { private final IAcceleratedRenderer renderer; private final Matrix4f cameraInverse; private final Matrix3f normalInverse; private final float textureScale; public SheetedDecalTextureRenderer( IAcceleratedRenderer renderer, Matrix4f cameraInverse, Matrix3f normalInverse, float textureScale ) { this.renderer = renderer; this.cameraInverse = cameraInverse; this.normalInverse = normalInverse; this.textureScale = textureScale; } @Override public void render( VertexConsumer vertexConsumer, T context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { renderer.render( new AcceleratedSheetedDecalTextureGenerator( vertexConsumer, new FuzzyMatrix4f (cameraInverse).mul(transform), new Matrix3f (normalInverse).mul(normal), textureScale ), context, transform, normal, light, overlay, color ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/environments/IBufferEnvironment.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.environments; import com.github.argon4w.acceleratedrendering.core.backends.buffers.IServerBuffer; import com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout; import com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderPrograms; import com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.programs.dispatchers.IPolygonProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.programs.dispatchers.MeshUploadingProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.programs.dispatchers.TransformProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.programs.overrides.ITransformShaderProgramOverride; import com.github.argon4w.acceleratedrendering.core.programs.overrides.IUploadingShaderProgramOverride; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.client.renderer.RenderType; import java.util.Set; public interface IBufferEnvironment { int getVertexSize (); Set getVertexFormats (); VertexLayout getLayout (); IServerBuffer getImmediateMeshBuffer (); MeshUploadingProgramDispatcher selectMeshUploadingProgramDispatcher(); TransformProgramDispatcher selectTransformProgramDispatcher (); ITransformShaderProgramOverride getTransformProgramOverride (RenderType renderType); IUploadingShaderProgramOverride getUploadingProgramOverride (RenderType renderType); ICullingProgramDispatcher selectCullingProgramDispatcher (RenderType renderType); IPolygonProgramDispatcher selectProcessingProgramDispatcher (VertexFormat.Mode mode); boolean isAccelerated (VertexFormat vertexFormat); void setupBufferState (); class Presets { public static final IBufferEnvironment BLOCK = new VanillaBufferEnvironment(DefaultVertexFormat.BLOCK, ComputeShaderPrograms.CORE_BLOCK_MESH_UPLOADING_KEY, ComputeShaderPrograms.CORE_BLOCK_VERTEX_TRANSFORM_KEY); public static final IBufferEnvironment ENTITY = new VanillaBufferEnvironment(DefaultVertexFormat.NEW_ENTITY, ComputeShaderPrograms.CORE_ENTITY_MESH_UPLOADING_KEY, ComputeShaderPrograms.CORE_ENTITY_VERTEX_TRANSFORM_KEY); public static final IBufferEnvironment POS = new VanillaBufferEnvironment(DefaultVertexFormat.POSITION, ComputeShaderPrograms.CORE_POS_MESH_UPLOADING_KEY, ComputeShaderPrograms.CORE_POS_VERTEX_TRANSFORM_KEY); public static final IBufferEnvironment POS_COLOR = new VanillaBufferEnvironment(DefaultVertexFormat.POSITION_COLOR, ComputeShaderPrograms.CORE_POS_COLOR_MESH_UPLOADING_KEY, ComputeShaderPrograms.CORE_POS_COLOR_VERTEX_TRANSFORM_KEY); public static final IBufferEnvironment POS_TEX = new VanillaBufferEnvironment(DefaultVertexFormat.POSITION_TEX, ComputeShaderPrograms.CORE_POS_TEX_MESH_UPLOADING_KEY, ComputeShaderPrograms.CORE_POS_TEX_VERTEX_TRANSFORM_KEY); public static final IBufferEnvironment POS_TEX_COLOR = new VanillaBufferEnvironment(DefaultVertexFormat.POSITION_TEX_COLOR, ComputeShaderPrograms.CORE_POS_TEX_COLOR_MESH_UPLOADING_KEY, ComputeShaderPrograms.CORE_POS_TEX_COLOR_VERTEX_TRANSFORM_KEY); public static final IBufferEnvironment POS_COLOR_TEX_LIGHT = new VanillaBufferEnvironment(DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP, ComputeShaderPrograms.CORE_POS_COLOR_TEX_LIGHT_MESH_UPLOADING_KEY, ComputeShaderPrograms.CORE_POS_COLOR_TEX_LIGHT_VERTEX_TRANSFORM_KEY); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/environments/VanillaBufferEnvironment.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.environments; import com.github.argon4w.acceleratedrendering.core.backends.buffers.IServerBuffer; import com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout; import com.github.argon4w.acceleratedrendering.core.meshes.ServerMesh; import com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramSelector; import com.github.argon4w.acceleratedrendering.core.programs.culling.LoadCullingProgramSelectorEvent; import com.github.argon4w.acceleratedrendering.core.programs.dispatchers.IPolygonProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.programs.dispatchers.MeshUploadingProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.programs.dispatchers.TransformProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.programs.overrides.IShaderProgramOverrides; import com.github.argon4w.acceleratedrendering.core.programs.overrides.ITransformShaderProgramOverride; import com.github.argon4w.acceleratedrendering.core.programs.overrides.IUploadingShaderProgramOverride; import com.github.argon4w.acceleratedrendering.core.programs.overrides.LoadShaderProgramOverridesEvent; import com.github.argon4w.acceleratedrendering.core.programs.processing.IPolygonProcessor; import com.github.argon4w.acceleratedrendering.core.programs.processing.LoadPolygonProcessorEvent; import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.client.renderer.RenderType; import net.minecraft.resources.ResourceLocation; import net.neoforged.fml.ModLoader; import java.util.Set; public class VanillaBufferEnvironment implements IBufferEnvironment { private final VertexFormat vertexFormat; private final VertexLayout layout; private final IShaderProgramOverrides shaderProgramOverrides; private final MeshUploadingProgramDispatcher meshUploadingProgramDispatcher; private final TransformProgramDispatcher transformProgramDispatcher; private final ICullingProgramSelector cullingProgramSelector; private final IPolygonProcessor polygonProcessor; public VanillaBufferEnvironment( VertexFormat vertexFormat, ResourceLocation uploadingProgramKey, ResourceLocation transformProgramKey ) { var defaultTransformOverride = new TransformProgramDispatcher .Default(transformProgramKey, 4L * 4L); var defaultUploadingOverride = new MeshUploadingProgramDispatcher.Default(uploadingProgramKey, 5L * 4L); this.vertexFormat = vertexFormat; this.layout = new VertexLayout(vertexFormat); this.shaderProgramOverrides = ModLoader.postEventWithReturn(new LoadShaderProgramOverridesEvent (this.vertexFormat)).getOverrides (defaultTransformOverride, defaultUploadingOverride); this.cullingProgramSelector = ModLoader.postEventWithReturn(new LoadCullingProgramSelectorEvent (this.vertexFormat)).getSelector (); this.polygonProcessor = ModLoader.postEventWithReturn(new LoadPolygonProcessorEvent (this.vertexFormat)).getProcessor (); this.meshUploadingProgramDispatcher = new MeshUploadingProgramDispatcher(); this.transformProgramDispatcher = new TransformProgramDispatcher (); } @Override public void setupBufferState() { vertexFormat.setupBufferState(); } @Override public Set getVertexFormats() { return Set.of(vertexFormat); } @Override public VertexLayout getLayout() { return layout; } @Override public IServerBuffer getImmediateMeshBuffer() { return ServerMesh.Builder.BUFFERS.get(layout).getFirst(); } @Override public ITransformShaderProgramOverride getTransformProgramOverride(RenderType renderType) { return shaderProgramOverrides.getTransformOverrides().get(renderType); } @Override public IUploadingShaderProgramOverride getUploadingProgramOverride(RenderType renderType) { return shaderProgramOverrides.getUploadingOverrides().get(renderType); } @Override public MeshUploadingProgramDispatcher selectMeshUploadingProgramDispatcher() { return meshUploadingProgramDispatcher; } @Override public TransformProgramDispatcher selectTransformProgramDispatcher() { return transformProgramDispatcher; } @Override public ICullingProgramDispatcher selectCullingProgramDispatcher(RenderType renderType) { return cullingProgramSelector.select(renderType); } @Override public IPolygonProgramDispatcher selectProcessingProgramDispatcher(VertexFormat.Mode mode) { return polygonProcessor.select(mode); } @Override public boolean isAccelerated(VertexFormat vertexFormat) { return this.vertexFormat == vertexFormat; } @Override public int getVertexSize() { return vertexFormat.getVertexSize(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/memory/IMemoryInterface.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.memory; import org.joml.Matrix3f; import org.joml.Matrix4f; public interface IMemoryInterface { void putByte (long address, byte value); void putShort (long address, short value); void putInt (long address, int value); void putInt (long address, long value); void putFloat (long address, float value); void putNormal (long address, float value); void putMatrix4f (long address, Matrix4f value); void putMatrix3f (long address, Matrix3f value); IMemoryInterface at (int index); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/memory/IMemoryLayout.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.memory; public interface IMemoryLayout { IMemoryInterface getElement (T element); int getElementOffset(T element); boolean containsElement (T element); long getSize (); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/memory/NullMemoryInterface.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.memory; import org.joml.Matrix3f; import org.joml.Matrix4f; public class NullMemoryInterface implements IMemoryInterface { public static final NullMemoryInterface INSTANCE = new NullMemoryInterface(); @Override public void putByte(long address, byte value) { } @Override public void putShort(long address, short value) { } @Override public void putInt(long address, int value) { } @Override public void putInt(long address, long value) { } @Override public void putFloat(long address, float value) { } @Override public void putNormal(long address, float value) { } @Override public void putMatrix4f(long address, Matrix4f value) { } @Override public void putMatrix3f(long address, Matrix3f value) { } @Override public IMemoryInterface at(int index) { return INSTANCE; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/memory/SimpleDynamicMemoryInterface.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.memory; import com.github.argon4w.acceleratedrendering.core.utils.MemUtils; import lombok.AllArgsConstructor; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.lwjgl.system.MemoryUtil; import java.util.function.LongSupplier; @AllArgsConstructor public class SimpleDynamicMemoryInterface implements IMemoryInterface { private final long offset; private final LongSupplier size; @Override public void putByte(long address, byte value) { MemoryUtil.memPutByte(address + offset, value); } @Override public void putShort(long address, short value) { MemoryUtil.memPutShort(address + offset, value); } @Override public void putInt(long address, int value) { MemoryUtil.memPutInt(address + offset, value); } @Override public void putInt(long address, long value) { MemoryUtil.memPutInt(address + offset, (int) value); } @Override public void putFloat(long address, float value) { MemoryUtil.memPutFloat(address + offset, value); } @Override public void putNormal(long address, float value) { MemUtils.putNormal(address + offset, value); } @Override public void putMatrix4f(long address, Matrix4f value) { MemUtils.putMatrix4f(address + offset, value); } @Override public void putMatrix3f(long address, Matrix3f value) { MemUtils.putMatrix3f(address + offset, value); } @Override public IMemoryInterface at(int index) { return new SimpleDynamicMemoryInterface(index * size.getAsLong() + offset, size); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/memory/SimpleMemoryInterface.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.memory; import com.github.argon4w.acceleratedrendering.core.utils.MemUtils; import lombok.AllArgsConstructor; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.lwjgl.system.MemoryUtil; @AllArgsConstructor public class SimpleMemoryInterface implements IMemoryInterface { private final long offset; private final long size; @Override public void putByte(long address, byte value) { MemoryUtil.memPutByte(address + offset, value); } @Override public void putShort(long address, short value) { MemoryUtil.memPutShort(address + offset, value); } @Override public void putInt(long address, int value) { MemoryUtil.memPutInt(address + offset, value); } @Override public void putInt(long address, long value) { MemoryUtil.memPutInt(address + offset, (int) value); } @Override public void putFloat(long address, float value) { MemoryUtil.memPutFloat(address + offset, value); } @Override public void putNormal(long address, float value) { MemUtils.putNormal(address + offset, value); } @Override public void putMatrix4f(long address, Matrix4f value) { MemUtils.putMatrix4f(address + offset, value); } @Override public void putMatrix3f(long address, Matrix3f value) { MemUtils.putMatrix3f(address + offset, value); } @Override public IMemoryInterface at(int index) { return new SimpleMemoryInterface(index * size + offset, size); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/buffers/memory/VertexLayout.java ================================================ package com.github.argon4w.acceleratedrendering.core.buffers.memory; import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormatElement; public class VertexLayout implements IMemoryLayout { private final long size; private final int mask; private final int [] offsets; private final IMemoryInterface [] interfaces; public VertexLayout(VertexFormat vertexFormat) { var offsets = vertexFormat .getOffsetsByElement(); var count = offsets .length; this.size = vertexFormat.getVertexSize (); this.mask = vertexFormat.getElementsMask(); this.offsets = new int [count]; this.interfaces = new IMemoryInterface [count]; for (var i = 0; i < count; i ++) { var offset = offsets[i]; this.interfaces [i] = offset == -1 ? NullMemoryInterface.INSTANCE : new SimpleMemoryInterface(offset, size); this.offsets [i] = offset; } } @Override public IMemoryInterface getElement(VertexFormatElement element) { return interfaces[element.id()]; } @Override public int getElementOffset(VertexFormatElement element) { return offsets[element.id()]; } @Override public boolean containsElement(VertexFormatElement element) { return (mask & element.mask()) != 0; } @Override public long getSize() { return size; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/ClientMesh.java ================================================ package com.github.argon4w.acceleratedrendering.core.meshes; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.core.meshes.collectors.IMeshCollector; import com.github.argon4w.acceleratedrendering.core.meshes.data.cache.MeshDataCaches; import com.mojang.blaze3d.vertex.ByteBufferBuilder; import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet; import lombok.AllArgsConstructor; import java.nio.ByteBuffer; import java.util.Set; @AllArgsConstructor public class ClientMesh implements IMesh { private final int size; private final ByteBuffer vertexBuffer; @Override public void write( IAcceleratedVertexConsumer extension, int color, int light, int overlay ) { extension.addClientMesh( vertexBuffer, size, color, light, overlay ); } public static class Builder implements IMesh.Builder { public static final Builder INSTANCE = new Builder(); private final Set builders; private Builder() { this.builders = new ReferenceLinkedOpenHashSet<>(); } @Override public IMesh build(IMeshCollector collector) { var vertexCount = collector.getVertexCount(); if (vertexCount == 0) { return EmptyMesh.INSTANCE; } var builder = collector .getBuffer (); var layout = collector .getLayout (); var data = collector .getData (); var mesh = MeshDataCaches.CLIENT .get (layout, data); if (mesh != null) { builder.discard (); builder.clear (); return mesh; } var result = builder.build(); if (result == null) { builder.discard (); builder.close (); return EmptyMesh.INSTANCE; } builders.add(builder); mesh = new ClientMesh(vertexCount, result.byteBuffer()); MeshDataCaches.CLIENT.set( layout, data, mesh ); return mesh; } @Override public IMesh build(IMeshCollector collector, boolean forceDense) { return build(collector); } @Override public void delete() { for (var builder : builders) { builder.discard (); builder.close (); } } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/EmptyMesh.java ================================================ package com.github.argon4w.acceleratedrendering.core.meshes; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; public class EmptyMesh implements IMesh { public static final EmptyMesh INSTANCE = new EmptyMesh(); @Override public void write( IAcceleratedVertexConsumer extension, int color, int light, int overlay ) { } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/IMesh.java ================================================ package com.github.argon4w.acceleratedrendering.core.meshes; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.core.meshes.collectors.IMeshCollector; public interface IMesh { void write(IAcceleratedVertexConsumer extension, int color, int light, int overlay); interface Builder { IMesh build (IMeshCollector collector); IMesh build (IMeshCollector collector, boolean forceDense); void delete (); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/MeshType.java ================================================ package com.github.argon4w.acceleratedrendering.core.meshes; import lombok.Getter; @Getter public enum MeshType { SERVER(ServerMesh.Builder.INSTANCE), CLIENT(ClientMesh.Builder.INSTANCE); private final IMesh.Builder builder; MeshType(IMesh.Builder builder) { this.builder = builder; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/ServerMesh.java ================================================ package com.github.argon4w.acceleratedrendering.core.meshes; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.backends.GLConstants; import com.github.argon4w.acceleratedrendering.core.backends.buffers.EmptyServerBuffer; import com.github.argon4w.acceleratedrendering.core.backends.buffers.IServerBuffer; import com.github.argon4w.acceleratedrendering.core.backends.buffers.MappedBuffer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout; import com.github.argon4w.acceleratedrendering.core.meshes.collectors.IMeshCollector; import com.github.argon4w.acceleratedrendering.core.meshes.data.cache.MeshDataCaches; import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ReferenceArrayList; import it.unimi.dsi.fastutil.objects.ReferenceLists; import net.minecraft.CrashReport; import net.minecraft.ReportedException; import org.lwjgl.system.MemoryUtil; import java.util.List; public record ServerMesh( int size, long offset, boolean forceDense, IServerBuffer meshBuffer ) implements IMesh { @Override public void write( IAcceleratedVertexConsumer extension, int color, int light, int overlay ) { extension.addServerMesh( this, color, light, overlay ); } public static class Builder implements IMesh.Builder { public static final Builder INSTANCE; public static final Reference2ObjectMap> BUFFERS; static { INSTANCE = new Builder (); BUFFERS = new Reference2ObjectOpenHashMap<> (); BUFFERS.defaultReturnValue (ReferenceLists.singleton(EmptyServerBuffer.INSTANCE)); } private Builder() { } @Override public IMesh build(IMeshCollector collector, boolean forceDense) { var vertexCount = collector.getVertexCount (); if (vertexCount == 0) { return EmptyMesh.INSTANCE; } var builder = collector .getBuffer (); var layout = collector .getLayout (); var data = collector .getData (); var mesh = MeshDataCaches.SERVER .get (layout, data); if (mesh != null) { builder.discard (); builder.close (); return mesh; } var builderResult = builder.build(); if (builderResult == null) { builder.discard (); builder.close (); return EmptyMesh.INSTANCE; } var byteBuffer = builderResult .byteBuffer (); var capacity = byteBuffer .capacity (); var meshBuffers = BUFFERS .getOrDefault (layout, null); var meshBuffer = (MappedBuffer) null; if (meshBuffers == null) { meshBuffers = new ReferenceArrayList<> (); meshBuffer = new MappedBuffer (64L); meshBuffers .add (meshBuffer); BUFFERS .put (layout, meshBuffers); } else { meshBuffer = (MappedBuffer) meshBuffers.getLast(); } if (meshBuffer.getPosition() + capacity >= GLConstants.MAX_SHADER_STORAGE_BLOCK_SIZE) { if (CoreFeature.shouldUploadMeshImmediately()) { collector .getBuffer () .close (); var crashReport = CrashReport .forThrowable (new OutOfMemoryError("Mesh buffer size exceeds limits."), "Exception in building meshes."); var category = crashReport .addCategory ("Mesh being built"); category.setDetail("Mesh type", "Server side mesh"); category.setDetail("Mesh layout size (bytes)", collector.getLayout() .getSize ()); category.setDetail("Mesh size (vertices)", collector .getVertexCount ()); category.setDetail("Mesh buffer limits (bytes)", GLConstants .MAX_SHADER_STORAGE_BLOCK_SIZE); throw new ReportedException(crashReport); } meshBuffer = new MappedBuffer (64L); meshBuffers.add (meshBuffer); } var position = meshBuffer.getPosition(); var srcAddress = MemoryUtil.memAddress0(byteBuffer); var destAddress = meshBuffer.reserve (capacity); MemoryUtil.memCopy( srcAddress, destAddress, capacity ); builder.discard (); builder.close (); mesh = new ServerMesh( vertexCount, position / layout.getSize(), forceDense, meshBuffer ); MeshDataCaches.SERVER.set( layout, data, mesh ); return mesh; } @Override public IMesh build(IMeshCollector collector) { return build(collector, false); } @Override public void delete() { for ( var buffers : BUFFERS.values()) { for ( var buffer : buffers) { buffer.delete(); } } } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/collectors/CulledMeshCollector.java ================================================ package com.github.argon4w.acceleratedrendering.core.meshes.collectors; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout; import com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData; import com.github.argon4w.acceleratedrendering.core.utils.CullerUtils; import com.github.argon4w.acceleratedrendering.core.utils.Vertex; import com.mojang.blaze3d.platform.NativeImage; import com.mojang.blaze3d.vertex.ByteBufferBuilder; import com.mojang.blaze3d.vertex.VertexConsumer; import net.minecraft.client.renderer.texture.OverlayTexture; public class CulledMeshCollector implements VertexConsumer, IMeshCollector { private final int polygonSize; private final NativeImage texture; private final VertexLayout layout; private final SimpleMeshCollector meshCollector; private final Vertex[] polygon; private int vertexIndex; public CulledMeshCollector(IAcceleratedVertexConsumer vertexConsumer) { this.polygonSize = vertexConsumer .getPolygonSize (); this.texture = vertexConsumer .downloadTexture(); this.layout = vertexConsumer .getLayout (); this.meshCollector = new SimpleMeshCollector (this.layout); this.polygon = new Vertex [this.polygonSize]; this.vertexIndex = -1; } @Override public void flush() { if (vertexIndex >= polygonSize - 1) { vertexIndex = -1; if (!CullerUtils.shouldCull(polygon, texture)) { for (var vertex : polygon) { var vertexPosition = vertex.getPosition(); var vertexUV = vertex.getUv (); var vertexNormal = vertex.getNormal (); meshCollector.addVertex( vertexPosition .x, vertexPosition .y, vertexPosition .z, vertex .getPackedColor(), vertexUV .x, vertexUV .y, OverlayTexture .NO_OVERLAY, vertex .getPackedLight(), vertexNormal .x, vertexNormal .y, vertexNormal .z ); } } } } @Override public VertexConsumer addVertex( float pX, float pY, float pZ ) { flush(); polygon[++ vertexIndex] = new Vertex(); polygon[vertexIndex].getPosition().x = pX; polygon[vertexIndex].getPosition().y = pY; polygon[vertexIndex].getPosition().z = pZ; return this; } @Override public VertexConsumer setColor( int pRed, int pGreen, int pBlue, int pAlpha ) { if (vertexIndex < 0) { throw new IllegalStateException("Vertex not building!"); } polygon[vertexIndex].getColor().x = pRed; polygon[vertexIndex].getColor().y = pGreen; polygon[vertexIndex].getColor().z = pBlue; polygon[vertexIndex].getColor().w = pAlpha; return this; } @Override public VertexConsumer setUv(float pU, float pV) { if (vertexIndex < 0) { throw new IllegalStateException("Vertex not building!"); } polygon[vertexIndex].getUv().x = pU; polygon[vertexIndex].getUv().y = pV; return this; } @Override public VertexConsumer setUv1(int pU, int pV) { return this; } @Override public VertexConsumer setUv2(int pU, int pV) { if (vertexIndex < 0) { throw new IllegalStateException("Vertex not building!"); } polygon[vertexIndex].getLight().x = pU; polygon[vertexIndex].getLight().y = pV; return this; } @Override public VertexConsumer setNormal( float pNormalX, float pNormalY, float pNormalZ ) { if (vertexIndex < 0) { throw new IllegalStateException("Vertex not building!"); } polygon[vertexIndex].getNormal().x = pNormalX; polygon[vertexIndex].getNormal().y = pNormalY; polygon[vertexIndex].getNormal().z = pNormalZ; return this; } @Override public MeshData getData() { return meshCollector.getData(); } @Override public ByteBufferBuilder getBuffer() { return meshCollector.getBuffer(); } @Override public VertexLayout getLayout() { return meshCollector.getLayout(); } @Override public int getVertexCount() { return meshCollector.getVertexCount(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/collectors/IMeshCollector.java ================================================ package com.github.argon4w.acceleratedrendering.core.meshes.collectors; import com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout; import com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData; import com.mojang.blaze3d.vertex.ByteBufferBuilder; public interface IMeshCollector { MeshData getData (); ByteBufferBuilder getBuffer (); VertexLayout getLayout (); int getVertexCount (); void flush (); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/collectors/SimpleMeshCollector.java ================================================ package com.github.argon4w.acceleratedrendering.core.meshes.collectors; import com.github.argon4w.acceleratedrendering.core.buffers.memory.IMemoryInterface; import com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout; import com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData; import com.github.argon4w.acceleratedrendering.core.utils.PackedVector2i; import com.mojang.blaze3d.vertex.ByteBufferBuilder; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexFormatElement; import lombok.Getter; import net.minecraft.util.FastColor; public class SimpleMeshCollector implements VertexConsumer, IMeshCollector { @Getter private final VertexLayout layout; @Getter private final ByteBufferBuilder buffer; private final long vertexSize; private final IMemoryInterface posOffset; private final IMemoryInterface colorOffset; private final IMemoryInterface uv0Offset; private final IMemoryInterface uv2Offset; private final IMemoryInterface normalOffset; private final MeshData.Builder builder; private MeshData meshData; @Getter private long vertexAddress; @Getter private int vertexCount; public SimpleMeshCollector(VertexLayout layout) { this.layout = layout; this.buffer = new ByteBufferBuilder (1024); this.vertexSize = this.layout .getSize (); this.posOffset = this.layout .getElement (VertexFormatElement.POSITION); this.colorOffset = this.layout .getElement (VertexFormatElement.COLOR); this.uv0Offset = this.layout .getElement (VertexFormatElement.UV); this.uv2Offset = this.layout .getElement (VertexFormatElement.UV2); this.normalOffset = this.layout .getElement (VertexFormatElement.NORMAL); this.builder = MeshData .builder (); this.vertexAddress = -1L; this.vertexCount = 0; } @Override public void flush() { builder.addVertex(); } @Override public VertexConsumer addVertex( float pX, float pY, float pZ ) { if (vertexCount != 0) { builder.addVertex(); } vertexCount ++; vertexAddress = buffer.reserve((int) vertexSize); posOffset.putFloat(vertexAddress + 0L, pX); posOffset.putFloat(vertexAddress + 4L, pY); posOffset.putFloat(vertexAddress + 8L, pZ); builder.setPosition( pX, pY, pZ ); return this; } @Override public VertexConsumer setColor( int pRed, int pGreen, int pBlue, int pAlpha ) { if (vertexAddress == -1) { throw new IllegalStateException("Vertex not building!"); } colorOffset.putByte(vertexAddress + 0L, (byte) pRed); colorOffset.putByte(vertexAddress + 1L, (byte) pGreen); colorOffset.putByte(vertexAddress + 2L, (byte) pBlue); colorOffset.putByte(vertexAddress + 3L, (byte) pAlpha); builder.setColor( pRed, pGreen, pBlue, pAlpha ); return this; } @Override public VertexConsumer setUv(float pU, float pV) { if (vertexAddress == -1) { throw new IllegalStateException("Vertex not building!"); } uv0Offset.putFloat(vertexAddress + 0L, pU); uv0Offset.putFloat(vertexAddress + 4L, pV); builder.setUv(pU, pV); return this; } @Override public VertexConsumer setUv1(int pU, int pV) { return this; } @Override public VertexConsumer setUv2(int pU, int pV) { if (vertexAddress == -1) { throw new IllegalStateException("Vertex not building!"); } uv2Offset.putShort(vertexAddress + 0L, (short) pU); uv2Offset.putShort(vertexAddress + 2L, (short) pV); builder.setUv2(pU, pV); return this; } @Override public VertexConsumer setNormal( float pNormalX, float pNormalY, float pNormalZ ) { if (vertexAddress == -1) { throw new IllegalStateException("Vertex not building!"); } normalOffset.putNormal(vertexAddress + 0L, pNormalX); normalOffset.putNormal(vertexAddress + 1L, pNormalY); normalOffset.putNormal(vertexAddress + 2L, pNormalZ); builder.setNormal( pNormalX, pNormalY, pNormalZ ); return this; } @Override public void addVertex( float pX, float pY, float pZ, int pColor, float pU, float pV, int pPackedOverlay, int pPackedLight, float pNormalX, float pNormalY, float pNormalZ ) { vertexCount++; vertexAddress = buffer.reserve((int) vertexSize); posOffset .putFloat (vertexAddress + 0L, pX); posOffset .putFloat (vertexAddress + 4L, pY); posOffset .putFloat (vertexAddress + 8L, pZ); colorOffset .putInt (vertexAddress, FastColor.ABGR32.fromArgb32(pColor)); uv0Offset .putFloat (vertexAddress + 0L, pU); uv0Offset .putFloat (vertexAddress + 4L, pV); uv2Offset .putInt (vertexAddress, pPackedLight); normalOffset.putNormal (vertexAddress + 0L, pNormalX); normalOffset.putNormal (vertexAddress + 1L, pNormalY); normalOffset.putNormal (vertexAddress + 2L, pNormalZ); builder.addVertex( pX, pY, pZ, pU, pV, FastColor.ARGB32.red (pColor), FastColor.ARGB32.green (pColor), FastColor.ARGB32.blue (pColor), FastColor.ARGB32.alpha (pColor), PackedVector2i .unpackU(pPackedLight), PackedVector2i .unpackV(pPackedLight), pNormalX, pNormalY, pNormalZ ); } @Override public MeshData getData() { if (meshData == null) { meshData = builder.build(); } return meshData; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/data/MeshData.java ================================================ package com.github.argon4w.acceleratedrendering.core.meshes.data; import com.github.argon4w.acceleratedrendering.core.utils.Vertex; import it.unimi.dsi.fastutil.objects.ReferenceArrayList; import lombok.EqualsAndHashCode; import java.util.List; //@EqualsAndHashCode public class MeshData { private final int[] data; private MeshData(int[] data) { this.data = data; } public static Builder builder() { return new Builder(); } public static class Builder { private final List vertices; private final Vertex scratch; public Builder() { this.vertices = new ReferenceArrayList<> (); this.scratch = new Vertex (); } public Builder setPosition( float positionX, float positionY, float positionZ ) { scratch.getPosition().set( positionX, positionY, positionZ ); return this; } public Builder setColor( int colorRed, int colorGreen, int colorBlue, int colorAlpha ) { scratch.getColor().set( colorRed, colorGreen, colorBlue, colorAlpha ); return this; } public Builder setNormal( float normalX, float normalY, float normalZ ) { scratch.getNormal().set( normalX, normalY, normalZ ); return this; } public Builder setUv(float u, float v) { scratch.getUv().set(u, v); return this; } public Builder setUv2(int u, int v) { scratch.getLight().set(u, v); return this; } public Builder addVertex() { vertices.add(new Vertex(scratch)); return this; } public Builder addVertex( float posX, float posY, float posZ, float texU, float texV, int colorR, int colorG, int colorB, int colorA, int lightU, int lightV, float normalX, float normalY, float normalZ ) { var vertex = new Vertex(); vertex.getPosition().x = posX; vertex.getPosition().y = posY; vertex.getPosition().z = posZ; vertex.getUv() .x = texU; vertex.getUv() .y = texV; vertex.getColor() .w = colorA; vertex.getColor() .x = colorR; vertex.getColor() .y = colorG; vertex.getColor() .z = colorB; vertex.getLight() .x = lightU; vertex.getLight() .y = lightV; vertex.getNormal() .x = normalX; vertex.getNormal() .y = normalY; vertex.getNormal() .z = normalZ; vertices.add(vertex); return this; } public MeshData build() { var data = new int[vertices.size() * 8]; for (var i = 0; i < vertices.size(); i++) { var vertex = vertices.get(i); data[i * 8 + 0] = Float .floatToRawIntBits (vertex.getPosition().x); data[i * 8 + 1] = Float .floatToRawIntBits (vertex.getPosition().y); data[i * 8 + 2] = Float .floatToRawIntBits (vertex.getPosition().z); data[i * 8 + 3] = vertex.getPackedColor (); data[i * 8 + 4] = Float .floatToRawIntBits (vertex.getUv().x); data[i * 8 + 5] = Float .floatToRawIntBits (vertex.getUv().y); data[i * 8 + 6] = vertex.getPackedLight (); data[i * 8 + 7] = vertex.getPackedNormal (); } return new MeshData(data); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/data/cache/IMeshDataCache.java ================================================ package com.github.argon4w.acceleratedrendering.core.meshes.data.cache; import com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout; import com.github.argon4w.acceleratedrendering.core.meshes.IMesh; import com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData; public interface IMeshDataCache { void set (VertexLayout layout, MeshData data, IMesh mesh); IMesh get (VertexLayout layout, MeshData data); int count (VertexLayout layout, MeshData data); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/data/cache/IgnoreMeshDataCache.java ================================================ package com.github.argon4w.acceleratedrendering.core.meshes.data.cache; import com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout; import com.github.argon4w.acceleratedrendering.core.meshes.IMesh; import com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData; public class IgnoreMeshDataCache implements IMeshDataCache { @Override public void set( VertexLayout layout, MeshData data, IMesh mesh ) { } @Override public IMesh get(VertexLayout layout, MeshData meshData) { return null; } @Override public int count(VertexLayout layout, MeshData data) { return 0; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/data/cache/MeshDataCacheType.java ================================================ package com.github.argon4w.acceleratedrendering.core.meshes.data.cache; public enum MeshDataCacheType { IGNORED, MERGED; public IMeshDataCache create() { return create(this); } public static IMeshDataCache create(MeshDataCacheType type) { return switch (type) { case IGNORED -> new IgnoreMeshDataCache(); case MERGED -> new SimpleMeshDataCache(); }; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/data/cache/MeshDataCaches.java ================================================ package com.github.argon4w.acceleratedrendering.core.meshes.data.cache; import com.github.argon4w.acceleratedrendering.core.CoreFeature; public class MeshDataCaches { public static final IMeshDataCache SERVER = CoreFeature.createMeshDataCache(); public static final IMeshDataCache CLIENT = CoreFeature.createMeshDataCache(); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/meshes/data/cache/SimpleMeshDataCache.java ================================================ package com.github.argon4w.acceleratedrendering.core.meshes.data.cache; import com.github.argon4w.acceleratedrendering.core.buffers.memory.VertexLayout; import com.github.argon4w.acceleratedrendering.core.meshes.IMesh; import com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData; import it.unimi.dsi.fastutil.objects.*; public class SimpleMeshDataCache implements IMeshDataCache { private final Object2ReferenceMap> meshes; private final Object2ReferenceMap> counts; public SimpleMeshDataCache() { this.meshes = new Object2ReferenceOpenHashMap<>(); this.counts = new Object2ReferenceOpenHashMap<>(); this.meshes.defaultReturnValue(Object2ReferenceMaps .emptyMap()); this.counts.defaultReturnValue(Object2IntMaps .emptyMap()); } @Override public void set( VertexLayout layout, MeshData data, IMesh mesh ) { var meshCache = meshes.getOrDefault(layout, null); var countCache = counts.getOrDefault(layout, null); if (meshCache == null) { meshCache = new Object2ReferenceOpenHashMap <>(); countCache = new Object2IntOpenHashMap <>(); meshes.put(layout, meshCache); counts.put(layout, countCache); } meshCache .putIfAbsent(data, mesh); countCache .put (data, countCache.getInt(data) + 1); } @Override public IMesh get(VertexLayout layout, MeshData meshData) { return meshes.get(layout).get(meshData); } @Override public int count(VertexLayout layout, MeshData data) { return counts.get(layout).getInt(data); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/GameRendererMixin.java ================================================ package com.github.argon4w.acceleratedrendering.core.mixins; import com.github.argon4w.acceleratedrendering.core.CoreBuffers; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.CoreStates; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType; import net.minecraft.client.Camera; import net.minecraft.client.renderer.GameRenderer; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(GameRenderer.class) public class GameRendererMixin { @Inject( method = "renderItemInHand", at = @At( value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;renderHandsWithItems(FLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/player/LocalPlayer;I)V", shift = At.Shift.BEFORE ) ) public void startRenderItemInHandsFast( Camera camera, float partialTick, Matrix4f projectionMatrix, CallbackInfo ci ) { CoreFeature.setRenderingHand(); } @Inject( method = "renderItemInHand", at = @At( value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;renderHandsWithItems(FLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/player/LocalPlayer;I)V", shift = At.Shift.AFTER ) ) public void stopRenderItemInHandsFast( Camera camera, float partialTick, Matrix4f projectionMatrix, CallbackInfo ci ) { CoreFeature .resetRenderingHand (); CoreStates .recordBuffers (); CoreBuffers.ENTITY .prepareBuffers (); CoreBuffers.BLOCK .prepareBuffers (); CoreBuffers.POS .prepareBuffers (); CoreBuffers.POS_COLOR .prepareBuffers (); CoreBuffers.POS_TEX .prepareBuffers (); CoreBuffers.POS_TEX_COLOR .prepareBuffers (); CoreBuffers.POS_COLOR_TEX_LIGHT .prepareBuffers (); CoreStates .restoreBuffers (); CoreBuffers.ENTITY .drawBuffers (LayerDrawType.ALL); CoreBuffers.BLOCK .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_COLOR .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_TEX .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_TEX_COLOR .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_COLOR_TEX_LIGHT .drawBuffers (LayerDrawType.ALL); CoreBuffers.ENTITY .clearBuffers (); CoreBuffers.BLOCK .clearBuffers (); CoreBuffers.POS .clearBuffers (); CoreBuffers.POS_COLOR .clearBuffers (); CoreBuffers.POS_TEX .clearBuffers (); CoreBuffers.POS_TEX_COLOR .clearBuffers (); CoreBuffers.POS_COLOR_TEX_LIGHT .clearBuffers (); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/LevelRendererMixin.java ================================================ package com.github.argon4w.acceleratedrendering.core.mixins; import com.github.argon4w.acceleratedrendering.core.CoreBuffers; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.CoreStates; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType; import com.github.argon4w.acceleratedrendering.core.meshes.ClientMesh; import com.github.argon4w.acceleratedrendering.core.meshes.ServerMesh; import com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderProgramLoader; import com.github.argon4w.acceleratedrendering.features.items.gui.GuiBatchingController; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.client.Camera; import net.minecraft.client.DeltaTracker; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin( value = LevelRenderer.class, priority = 998 ) public class LevelRendererMixin { @Inject( method = "renderLevel", at = @At("HEAD") ) public void startRenderLevel( DeltaTracker deltaTracker, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f frustumMatrix, Matrix4f projectionMatrix, CallbackInfo ci ) { CoreFeature.setRenderingLevel(); } @Inject( method = "renderLevel", at = @At("RETURN") ) public void stopRenderLevel( DeltaTracker deltaTracker, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f frustumMatrix, Matrix4f projectionMatrix, CallbackInfo ci ) { CoreFeature.resetRenderingLevel(); } @Inject( method = "renderLevel", at = @At( value = "INVOKE", target = "Lnet/minecraft/client/renderer/OutlineBufferSource;endOutlineBatch()V" ) ) public void endOutlineBatches( DeltaTracker pDeltaTracker, boolean pRenderBlockOutline, Camera pCamera, GameRenderer pGameRenderer, LightTexture pLightTexture, Matrix4f pFrustumMatrix, Matrix4f pProjectionMatrix, CallbackInfo ci ) { CoreStates .recordBuffers (); CoreBuffers.POS_TEX_COLOR_OUTLINE .prepareBuffers (); CoreStates .restoreBuffers (); CoreBuffers.POS_TEX_COLOR_OUTLINE .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_TEX_COLOR_OUTLINE .clearBuffers (); } @WrapOperation( method = "renderLevel", at = @At( value = "INVOKE", target = "Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;endLastBatch()V" ) ) public void drawCoreBuffers(MultiBufferSource.BufferSource instance, Operation original) { CoreStates .recordBuffers (); CoreBuffers.ENTITY .prepareBuffers (); CoreBuffers.BLOCK .prepareBuffers (); CoreBuffers.POS .prepareBuffers (); CoreBuffers.POS_COLOR .prepareBuffers (); CoreBuffers.POS_TEX .prepareBuffers (); CoreBuffers.POS_TEX_COLOR .prepareBuffers (); CoreBuffers.POS_COLOR_TEX_LIGHT .prepareBuffers (); CoreStates .restoreBuffers (); CoreBuffers.ENTITY .drawBuffers (LayerDrawType.ALL); CoreBuffers.BLOCK .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_COLOR .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_TEX .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_TEX_COLOR .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_COLOR_TEX_LIGHT .drawBuffers (LayerDrawType.ALL); CoreBuffers.ENTITY .clearBuffers (); CoreBuffers.BLOCK .clearBuffers (); CoreBuffers.POS .clearBuffers (); CoreBuffers.POS_COLOR .clearBuffers (); CoreBuffers.POS_TEX .clearBuffers (); CoreBuffers.POS_TEX_COLOR .clearBuffers (); CoreBuffers.POS_COLOR_TEX_LIGHT .clearBuffers (); original.call(instance); } @Inject( method = "close", at = @At("TAIL") ) public void deleteBuffers(CallbackInfo ci) { CoreBuffers.ENTITY .delete(); CoreBuffers.BLOCK .delete(); CoreBuffers.POS .delete(); CoreBuffers.POS_COLOR .delete(); CoreBuffers.POS_TEX .delete(); CoreBuffers.POS_TEX_COLOR .delete(); CoreBuffers.POS_COLOR_TEX_LIGHT .delete(); CoreStates .delete(); GuiBatchingController.INSTANCE .delete(); ComputeShaderProgramLoader .delete(); ServerMesh.Builder.INSTANCE .delete(); ClientMesh.Builder.INSTANCE .delete(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/BufferBuilderMixin.java ================================================ package com.github.argon4w.acceleratedrendering.core.mixins.buffers; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.buffers.EmptyAcceleratedBufferSources; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAcceleratedBufferSource; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAccelerationHolder; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.VertexConsumer; import net.minecraft.client.renderer.RenderType; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import java.util.function.Supplier; @Mixin(BufferBuilder.class) public class BufferBuilderMixin implements IAccelerationHolder, IAcceleratedVertexConsumer { @Unique private IAcceleratedBufferSource bufferSources = EmptyAcceleratedBufferSources.INSTANCE; @Unique private RenderType renderType; @Unique private AcceleratedBufferBuilder acceleration; @Unique @Override public VertexConsumer initAcceleration(RenderType renderType, Supplier bufferSource) { if (CoreFeature.isLoaded()) { this.bufferSources = bufferSource.get(); this.renderType = renderType; this.acceleration = null; } return (VertexConsumer) this; } @Unique @Override public boolean isAccelerated() { return bufferSources != EmptyAcceleratedBufferSources.INSTANCE && getAccelerated() != null; } @Unique @Override public void doRender( IAcceleratedRenderer renderer, T context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { getAccelerated().doRender( renderer, context, transform, normal, light, overlay, color ); } @Unique @Override public AcceleratedBufferBuilder getAccelerated() { if ( acceleration == null || acceleration.isOutdated() ) { acceleration = bufferSources.getBuffer( renderType, CoreFeature.getDefaultLayerBeforeFunction (), CoreFeature.getDefaultLayerAfterFunction (), CoreFeature.getDefaultLayer () ); } return acceleration; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/BufferSourceMixin.java ================================================ package com.github.argon4w.acceleratedrendering.core.mixins.buffers; import com.github.argon4w.acceleratedrendering.core.CoreBuffersProvider; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAcceleratedBufferSource; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratableBufferSource; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.llamalad7.mixinextras.injector.ModifyReturnValue; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import java.util.function.Supplier; @ExtensionMethod(VertexConsumerExtension .class) @Mixin (MultiBufferSource.BufferSource .class) public class BufferSourceMixin implements IAcceleratableBufferSource { @Unique private Supplier bufferSource = CoreBuffersProvider.EMPTY; @Unique @Override public Supplier getBoundAcceleratedBufferSource() { return bufferSource; } @Override public boolean isBufferSourceAcceleratable() { return bufferSource != CoreBuffersProvider.EMPTY; } @Unique @Override public void bindAcceleratedBufferSource(Supplier bufferSource) { this.bufferSource = bufferSource; } @ModifyReturnValue( method = "getBuffer", at = @At("RETURN") ) public VertexConsumer initAcceleration(VertexConsumer original, RenderType renderType) { return original .getHolder () .initAcceleration (renderType, bufferSource); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/EntityOutlineGeneratorMixin.java ================================================ package com.github.argon4w.acceleratedrendering.core.mixins.buffers; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedEntityOutlineGenerator; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.DecoratedRenderer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.OutlineBufferSource; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @ExtensionMethod(VertexConsumerExtension .class) @Mixin (OutlineBufferSource.EntityOutlineGenerator .class) public class EntityOutlineGeneratorMixin implements IAcceleratedVertexConsumer { @Shadow @Final private VertexConsumer delegate; @Shadow @Final private int color; @Unique @Override public VertexConsumer decorate(VertexConsumer buffer) { return new AcceleratedEntityOutlineGenerator(buffer, color); } @Unique @Override public boolean isAccelerated() { return delegate .getAccelerated () .isAccelerated (); } @Unique @Override public void doRender( IAcceleratedRenderer renderer, T context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { delegate .getAccelerated () .doRender ( new DecoratedRenderer<>(renderer, this), context, transform, normal, light, overlay, color ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/MinecraftMixin.java ================================================ package com.github.argon4w.acceleratedrendering.core.mixins.buffers; import com.github.argon4w.acceleratedrendering.core.CoreBuffersProvider; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.BufferSourceExtension; import lombok.experimental.ExtensionMethod; import net.minecraft.client.Minecraft; import net.minecraft.client.main.GameConfig; import net.minecraft.client.renderer.RenderBuffers; import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @ExtensionMethod(BufferSourceExtension .class) @Mixin (Minecraft .class) public class MinecraftMixin { @Shadow @Final private RenderBuffers renderBuffers; @Inject( method = "", at = @At( value = "FIELD", target = "Lnet/minecraft/client/Minecraft;renderBuffers:Lnet/minecraft/client/renderer/RenderBuffers;", opcode = Opcodes.PUTFIELD, shift = At.Shift.AFTER ) ) public void bindAcceleratedBufferSources(GameConfig gameConfig, CallbackInfo ci) { CoreBuffersProvider.bindAcceleratedBufferSources(renderBuffers); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/OutlineBufferSourceMixin.java ================================================ package com.github.argon4w.acceleratedrendering.core.mixins.buffers; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.IAcceleratedBufferSource; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.BufferSourceExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratableBufferSource; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.OutlineBufferSource; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import java.util.function.Supplier; @ExtensionMethod(BufferSourceExtension.class) @Mixin (OutlineBufferSource .class) public class OutlineBufferSourceMixin implements IAcceleratableBufferSource { @Shadow @Final private MultiBufferSource.BufferSource outlineBufferSource; @Unique @Override public Supplier getBoundAcceleratedBufferSource() { return outlineBufferSource .getAcceleratable () .getBoundAcceleratedBufferSource(); } @Unique @Override public boolean isBufferSourceAcceleratable() { return outlineBufferSource .getAcceleratable () .isBufferSourceAcceleratable(); } @Unique @Override public void bindAcceleratedBufferSource(Supplier supplier) { outlineBufferSource .getAcceleratable () .bindAcceleratedBufferSource(supplier); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/SheetedDecalTextureGeneratorMixin.java ================================================ package com.github.argon4w.acceleratedrendering.core.mixins.buffers; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.SheetedDecalTextureRenderer; import com.mojang.blaze3d.vertex.SheetedDecalTextureGenerator; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.experimental.ExtensionMethod; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @ExtensionMethod(VertexConsumerExtension .class) @Mixin (SheetedDecalTextureGenerator .class) public class SheetedDecalTextureGeneratorMixin implements IAcceleratedVertexConsumer { @Shadow @Final private VertexConsumer delegate; @Shadow @Final private Matrix4f cameraInversePose; @Shadow @Final private Matrix3f normalInversePose; @Shadow @Final private float textureScale; @Unique @Override public boolean isAccelerated() { return delegate .getAccelerated() .isAccelerated(); } @Unique @Override public void doRender( IAcceleratedRenderer renderer, T context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { delegate .getAccelerated () .doRender ( new SheetedDecalTextureRenderer<>( renderer, cameraInversePose, normalInversePose, textureScale ), context, transform, normal, light, overlay, color ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/SpriteCoordinateExpanderMixin.java ================================================ package com.github.argon4w.acceleratedrendering.core.mixins.buffers; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedSpriteCoordinateExpander; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.DecoratedRenderer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.SpriteCoordinateExpander; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @ExtensionMethod(VertexConsumerExtension .class) @Mixin (SpriteCoordinateExpander .class) public class SpriteCoordinateExpanderMixin implements IAcceleratedVertexConsumer { @Shadow @Final private VertexConsumer delegate; @Shadow @Final private TextureAtlasSprite sprite; @Unique @Override public VertexConsumer decorate(VertexConsumer buffer) { return new AcceleratedSpriteCoordinateExpander(buffer, sprite); } @Unique @Override public boolean isAccelerated() { return delegate .getAccelerated () .isAccelerated (); } @Unique @Override public void doRender( IAcceleratedRenderer renderer, T context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { delegate .getAccelerated () .doRender ( new DecoratedRenderer<>(renderer, this), context, transform, normal, light, overlay, color ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/VertexConsumerMixin.java ================================================ package com.github.argon4w.acceleratedrendering.core.mixins.buffers; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.mojang.blaze3d.vertex.VertexConsumer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @Mixin(VertexConsumer.class) public interface VertexConsumerMixin extends IAcceleratedVertexConsumer { @Unique @Override default boolean isAccelerated() { return false; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/VertexDoubleConsumerMixin.java ================================================ package com.github.argon4w.acceleratedrendering.core.mixins.buffers; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.experimental.ExtensionMethod; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @ExtensionMethod(VertexConsumerExtension.class) @Mixin (targets = "com.mojang.blaze3d.vertex.VertexMultiConsumer$Double") public class VertexDoubleConsumerMixin implements IAcceleratedVertexConsumer { @Shadow @Final private VertexConsumer first; @Shadow @Final private VertexConsumer second; @Unique @Override public boolean isAccelerated() { return first .getAccelerated().isAccelerated() && second .getAccelerated().isAccelerated(); } @Unique @Override public void doRender( IAcceleratedRenderer renderer, T context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { first .getAccelerated () .doRender ( renderer, context, transform, normal, light, overlay, color ); second .getAccelerated () .doRender ( renderer, context, transform, normal, light, overlay, color ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/buffers/VertexMultipleConsumerMixin.java ================================================ package com.github.argon4w.acceleratedrendering.core.mixins.buffers; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.experimental.ExtensionMethod; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @ExtensionMethod(VertexConsumerExtension.class) @Mixin (targets = "com.mojang.blaze3d.vertex.VertexMultiConsumer$Multiple") public class VertexMultipleConsumerMixin implements IAcceleratedVertexConsumer { @Shadow @Final private VertexConsumer[] delegates; @Unique private boolean accelerated = true; @Inject( method = "", at = @At("TAIL") ) public void constructor(VertexConsumer[] delegates, CallbackInfo ci) { for (var delegate : delegates) { accelerated = accelerated && delegate .getAccelerated () .isAccelerated (); } } @Unique @Override public boolean isAccelerated() { return accelerated; } @Unique @Override public void doRender( IAcceleratedRenderer renderer, T context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { for (var delegate : delegates) { delegate .getAccelerated () .doRender ( renderer, context, transform, normal, light, overlay, color ); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/compatibility/MinecraftMixin.java ================================================ package com.github.argon4w.acceleratedrendering.core.mixins.compatibility; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.backends.DebugOutput; import net.minecraft.client.Minecraft; import net.minecraft.client.main.GameConfig; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(Minecraft.class) public class MinecraftMixin { @Inject( method = "", at = @At("TAIL") ) public void setDebugContext(GameConfig gameConfig, CallbackInfo ci) { if ( CoreFeature.isConfigLoaded () && CoreFeature.isDebugContextEnabled () ) { DebugOutput.enable(); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/compatibility/ParticleEngineMixin.java ================================================ package com.github.argon4w.acceleratedrendering.core.mixins.compatibility; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature; import com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature; import net.minecraft.client.Camera; import net.minecraft.client.particle.ParticleEngine; import net.minecraft.client.particle.ParticleRenderType; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.culling.Frustum; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.function.Predicate; @Mixin(ParticleEngine.class) public class ParticleEngineMixin { @Inject( method = "render(Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/culling/Frustum;Ljava/util/function/Predicate;)V", at = @At("HEAD") ) public void disableParticleAcceleration( LightTexture lightTexture, Camera camera, float partialTick, Frustum frustum, Predicate renderTypePredicate, CallbackInfo ci ) { AcceleratedEntityRenderingFeature .useVanillaPipeline(); AcceleratedItemRenderingFeature .useVanillaPipeline(); AcceleratedTextRenderingFeature .useVanillaPipeline(); } @Inject( method = "render(Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/culling/Frustum;Ljava/util/function/Predicate;)V", at = @At("RETURN") ) public void resetParticleAcceleration( LightTexture lightTexture, Camera camera, float partialTick, Frustum frustum, Predicate renderTypePredicate, CallbackInfo ci ) { AcceleratedEntityRenderingFeature .resetPipeline(); AcceleratedItemRenderingFeature .resetPipeline(); AcceleratedTextRenderingFeature .resetPipeline(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/compatibility/RenderTypeMixin.java ================================================ package com.github.argon4w.acceleratedrendering.core.mixins.compatibility; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.mojang.datafixers.util.Pair; import net.minecraft.client.renderer.RenderType; import net.minecraft.resources.ResourceLocation; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @Mixin(RenderType.class) public class RenderTypeMixin { @Unique private static final Map, RenderType> ENERGY_SWIRL = new ConcurrentHashMap<>(); @Unique private static final Map, RenderType> BREEZE_WIND = new ConcurrentHashMap<>(); @WrapMethod(method = "energySwirl") private static RenderType cacheEnergySwirl( ResourceLocation location, float u, float v, Operation original ) { return ENERGY_SWIRL.computeIfAbsent(Pair.of(location, CoreFeature.packDynamicUV(u, v)), pair -> original.call( location, CoreFeature.unpackDynamicU(pair.getSecond()), CoreFeature.unpackDynamicV(pair.getSecond()) )); } @WrapMethod(method = "breezeWind") private static RenderType cacheBreezeWind( ResourceLocation location, float u, float v, Operation original ) { return BREEZE_WIND.computeIfAbsent(Pair.of(location, CoreFeature.packDynamicUV(u, v)), pair -> original.call( location, CoreFeature.unpackDynamicU(pair.getSecond()), CoreFeature.unpackDynamicV(pair.getSecond()) )); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/mixins/compatibility/WindowMixin.java ================================================ package com.github.argon4w.acceleratedrendering.core.mixins.compatibility; import com.mojang.blaze3d.platform.Window; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.Constant; import org.spongepowered.asm.mixin.injection.ModifyConstant; @Mixin(Window.class) public class WindowMixin { @ModifyConstant( method = "", constant = @Constant( intValue = 3, ordinal = 0 ) ) public int modifyGlMajorVersion(int value) { return 4; } @ModifyConstant( method = "", constant = @Constant( intValue = 2, ordinal = 0 ) ) public int modifyGlMinorVersion(int value) { return 6; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/ComputeShaderDefinition.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs; import net.minecraft.resources.ResourceLocation; public record ComputeShaderDefinition(ResourceLocation location, int barrierFlags) { } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/ComputeShaderProgramLoader.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs; import com.github.argon4w.acceleratedrendering.core.backends.programs.ComputeProgram; import com.github.argon4w.acceleratedrendering.core.backends.programs.ComputeShader; import com.mojang.blaze3d.systems.RenderSystem; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.CrashReport; import net.minecraft.ReportedException; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.SimplePreparableReloadListener; import net.minecraft.util.profiling.ProfilerFiller; import net.neoforged.fml.ModLoader; import org.apache.commons.io.IOUtils; import java.nio.charset.StandardCharsets; import java.util.Map; public class ComputeShaderProgramLoader extends SimplePreparableReloadListener> { public static final ComputeShaderProgramLoader INSTANCE = new ComputeShaderProgramLoader(); private static final Map COMPUTE_SHADERS = new Object2ObjectOpenHashMap<>(); private static boolean LOADED = false; @Override protected Map prepare(ResourceManager resourceManager, ProfilerFiller profiler) { try { var shaderSources = new Object2ObjectOpenHashMap (); var shaderLocations = ModLoader.postEventWithReturn(new LoadComputeShaderEvent()).build (); for (ResourceLocation key : shaderLocations.keySet()) { var definition = shaderLocations .get (key); var resourceLocation = definition .location (); var barrierFlags = definition .barrierFlags (); if (resourceLocation == null) { throw new IllegalStateException("Found empty shader location on: \"" + key + "\""); } var resource = resourceManager.getResource(resourceLocation); if (resource.isEmpty()) { throw new IllegalStateException("Cannot found compute shader: \"" + resourceLocation + "\""); } try (var stream = resource.get().open()) { shaderSources.put(key, new ShaderSource(IOUtils.toString(stream, StandardCharsets.UTF_8), barrierFlags)); } } return shaderSources; } catch (Exception e) { throw new ReportedException(CrashReport.forThrowable(e, "Exception while loading compute shader")); } } @Override protected void apply( Map shaderSources, ResourceManager resourceManager, ProfilerFiller profiler ) { RenderSystem.recordRenderCall(() -> { try { for (var key : shaderSources.keySet()) { var source = shaderSources .get(key); var shaderSource = source .source; var barrierFlags = source .barrierFlags; var program = new ComputeProgram(barrierFlags); var computeShader = new ComputeShader (); computeShader.setShaderSource (shaderSource); computeShader.compileShader (); if (!computeShader.isCompiled()) { throw new IllegalStateException("Shader \"" + key + "\" failed to compile because of the following errors: " + computeShader.getInfoLog()); } program.attachShader(computeShader); program.linkProgram (); if (!program.isLinked()) { throw new IllegalStateException("Program \"" + key + "\" failed to link because of the following errors: " + program.getInfoLog()); } computeShader .delete (); COMPUTE_SHADERS .put (key, program); } } catch (Exception e) { throw new ReportedException(CrashReport.forThrowable(e, "Exception while compiling/linking compute shader")); } finally { LOADED = true; } }); } public static ComputeProgram getProgram(ResourceLocation resourceLocation) { var program = COMPUTE_SHADERS.get(resourceLocation); if (program == null) { throw new IllegalStateException("Get shader program \""+ resourceLocation + "\" too early! Program is not loaded yet!"); } return program; } public static void delete() { for (var program : COMPUTE_SHADERS.values()) { program.delete(); } LOADED = false; } public static boolean isProgramsLoaded() { return LOADED; } public record ShaderSource(String source, int barrierFlags) { } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/ComputeShaderPrograms.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs; import com.github.argon4w.acceleratedrendering.AcceleratedRenderingModEntry; import com.github.argon4w.acceleratedrendering.core.backends.programs.BarrierFlags; import com.github.argon4w.acceleratedrendering.core.utils.ResourceLocationUtils; import net.minecraft.resources.ResourceLocation; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.neoforge.client.event.RegisterClientReloadListenersEvent; @EventBusSubscriber( modid = AcceleratedRenderingModEntry .MOD_ID, bus = EventBusSubscriber.Bus .MOD, value = Dist .CLIENT ) public class ComputeShaderPrograms { public static final ResourceLocation CORE_BLOCK_VERTEX_TRANSFORM_KEY = ResourceLocationUtils.create("core_block_vertex_transform"); public static final ResourceLocation CORE_ENTITY_VERTEX_TRANSFORM_KEY = ResourceLocationUtils.create("core_entity_vertex_transform"); public static final ResourceLocation CORE_POS_VERTEX_TRANSFORM_KEY = ResourceLocationUtils.create("core_pos_vertex_transform"); public static final ResourceLocation CORE_POS_COLOR_VERTEX_TRANSFORM_KEY = ResourceLocationUtils.create("core_pos_color_vertex_transform"); public static final ResourceLocation CORE_POS_TEX_VERTEX_TRANSFORM_KEY = ResourceLocationUtils.create("core_pos_tex_vertex_transform"); public static final ResourceLocation CORE_POS_TEX_COLOR_VERTEX_TRANSFORM_KEY = ResourceLocationUtils.create("core_pos_tex_color_vertex_transform"); public static final ResourceLocation CORE_POS_COLOR_TEX_LIGHT_VERTEX_TRANSFORM_KEY = ResourceLocationUtils.create("core_pos_color_tex_light_vertex_transform"); public static final ResourceLocation CORE_PASS_THROUGH_QUAD_CULLING_KEY = ResourceLocationUtils.create("core_pass_through_quad_culling"); public static final ResourceLocation CORE_PASS_THROUGH_TRIANGLE_CULLING_KEY = ResourceLocationUtils.create("core_pass_through_triangle_culling"); public static final ResourceLocation CORE_BLOCK_MESH_UPLOADING_KEY = ResourceLocationUtils.create("core_block_mesh_uploading_key"); public static final ResourceLocation CORE_ENTITY_MESH_UPLOADING_KEY = ResourceLocationUtils.create("core_entity_mesh_uploading"); public static final ResourceLocation CORE_POS_MESH_UPLOADING_KEY = ResourceLocationUtils.create("core_pos_mesh_uploading"); public static final ResourceLocation CORE_POS_COLOR_MESH_UPLOADING_KEY = ResourceLocationUtils.create("core_pos_color_mesh_uploading"); public static final ResourceLocation CORE_POS_TEX_MESH_UPLOADING_KEY = ResourceLocationUtils.create("core_pos_tex_mesh_uploading"); public static final ResourceLocation CORE_POS_TEX_COLOR_MESH_UPLOADING_KEY = ResourceLocationUtils.create("core_pos_tex_color_mesh_uploading"); public static final ResourceLocation CORE_POS_COLOR_TEX_LIGHT_MESH_UPLOADING_KEY = ResourceLocationUtils.create("core_pos_color_tex_light_mesh_uploading"); @SubscribeEvent public static void onLoadComputeShaders(LoadComputeShaderEvent event) { event.loadComputeShader( CORE_BLOCK_VERTEX_TRANSFORM_KEY, ResourceLocationUtils .create("shaders/core/transform/block_vertex_transform_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( CORE_ENTITY_VERTEX_TRANSFORM_KEY, ResourceLocationUtils .create("shaders/core/transform/entity_vertex_transform_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( CORE_POS_VERTEX_TRANSFORM_KEY, ResourceLocationUtils .create("shaders/core/transform/pos_vertex_transform_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( CORE_POS_COLOR_VERTEX_TRANSFORM_KEY, ResourceLocationUtils .create("shaders/core/transform/pos_color_vertex_transform_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( CORE_POS_TEX_VERTEX_TRANSFORM_KEY, ResourceLocationUtils .create("shaders/core/transform/pos_tex_vertex_transform_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( CORE_POS_TEX_COLOR_VERTEX_TRANSFORM_KEY, ResourceLocationUtils .create("shaders/core/transform/pos_tex_color_vertex_transform_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( CORE_POS_COLOR_TEX_LIGHT_VERTEX_TRANSFORM_KEY, ResourceLocationUtils .create("shaders/core/transform/pos_color_tex_light_vertex_transform_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( CORE_PASS_THROUGH_QUAD_CULLING_KEY, ResourceLocationUtils .create("shaders/core/culling/pass_through_quad_culling_shader.compute"), BarrierFlags .SHADER_STORAGE, BarrierFlags .ATOMIC_COUNTER ); event.loadComputeShader( CORE_PASS_THROUGH_TRIANGLE_CULLING_KEY, ResourceLocationUtils .create("shaders/core/culling/pass_through_triangle_culling_shader.compute"), BarrierFlags .SHADER_STORAGE, BarrierFlags .ATOMIC_COUNTER ); event.loadComputeShader( CORE_BLOCK_MESH_UPLOADING_KEY, ResourceLocationUtils .create("shaders/core/uploading/block_mesh_uploading_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( CORE_ENTITY_MESH_UPLOADING_KEY, ResourceLocationUtils .create("shaders/core/uploading/entity_mesh_uploading_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( CORE_POS_MESH_UPLOADING_KEY, ResourceLocationUtils .create("shaders/core/uploading/pos_mesh_uploading_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( CORE_POS_COLOR_MESH_UPLOADING_KEY, ResourceLocationUtils .create("shaders/core/uploading/pos_color_mesh_uploading_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( CORE_POS_TEX_MESH_UPLOADING_KEY, ResourceLocationUtils .create("shaders/core/uploading/pos_tex_mesh_uploading_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( CORE_POS_TEX_COLOR_MESH_UPLOADING_KEY, ResourceLocationUtils .create("shaders/core/uploading/pos_tex_color_mesh_uploading_shader.compute"), BarrierFlags .SHADER_STORAGE ); event.loadComputeShader( CORE_POS_COLOR_TEX_LIGHT_MESH_UPLOADING_KEY, ResourceLocationUtils .create("shaders/core/uploading/pos_color_tex_light_mesh_uploading_shader.compute"), BarrierFlags .SHADER_STORAGE ); } @SubscribeEvent public static void onRegisterResourceReloadListeners(RegisterClientReloadListenersEvent event) { event.registerReloadListener(ComputeShaderProgramLoader.INSTANCE); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/LoadComputeShaderEvent.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs; import com.github.argon4w.acceleratedrendering.core.backends.programs.BarrierFlags; import com.google.common.collect.ImmutableMap; import net.minecraft.resources.ResourceLocation; import net.neoforged.bus.api.Event; import net.neoforged.fml.event.IModBusEvent; import java.util.Map; public class LoadComputeShaderEvent extends Event implements IModBusEvent { private final ImmutableMap.Builder shaderLocations; public LoadComputeShaderEvent() { this.shaderLocations = ImmutableMap.builder(); } public void loadComputeShader( ResourceLocation key, ResourceLocation location, BarrierFlags... barrierFlags ) { shaderLocations.put(key, new ComputeShaderDefinition(location, BarrierFlags.getFlags(barrierFlags))); } public Map build() { return shaderLocations.build(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/culling/ICullingProgramDispatcher.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs.culling; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder; public interface ICullingProgramDispatcher { int dispatch (AcceleratedBufferBuilder builder); boolean shouldCull (); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/culling/ICullingProgramSelector.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs.culling; import net.minecraft.client.renderer.RenderType; public interface ICullingProgramSelector { ICullingProgramDispatcher select(RenderType renderType); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/culling/LoadCullingProgramSelectorEvent.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs.culling; import com.mojang.blaze3d.vertex.VertexFormat; import lombok.Getter; import net.neoforged.bus.api.Event; import net.neoforged.fml.event.IModBusEvent; import java.util.function.UnaryOperator; public class LoadCullingProgramSelectorEvent extends Event implements IModBusEvent { private final VertexFormat vertexFormat; @Getter private ICullingProgramSelector selector; public LoadCullingProgramSelectorEvent(VertexFormat vertexFormat) { this.vertexFormat = vertexFormat; this.selector = PassThroughCullingProgramSelector.INSTANCE; } public void loadFor(VertexFormat vertexFormat, UnaryOperator selector) { if (this.vertexFormat == vertexFormat) { this.selector = selector.apply(this.selector); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/culling/PassThroughCullingProgramDispatcher.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs.culling; import com.github.argon4w.acceleratedrendering.core.backends.programs.ComputeProgram; import com.github.argon4w.acceleratedrendering.core.backends.programs.Uniform; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder; import com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderProgramLoader; import com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderPrograms; import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.resources.ResourceLocation; public class PassThroughCullingProgramDispatcher implements ICullingProgramDispatcher { public static final PassThroughCullingProgramDispatcher QUAD = new PassThroughCullingProgramDispatcher(VertexFormat.Mode.QUADS, ComputeShaderPrograms.CORE_PASS_THROUGH_QUAD_CULLING_KEY); public static final PassThroughCullingProgramDispatcher TRIANGLE = new PassThroughCullingProgramDispatcher(VertexFormat.Mode.TRIANGLES, ComputeShaderPrograms.CORE_PASS_THROUGH_TRIANGLE_CULLING_KEY); private static final int GROUP_SIZE = 128; private static final int DISPATCH_COUNT_Y_Z = 1; private final VertexFormat.Mode mode; private final ComputeProgram program; private final Uniform polygonCountUniform; private final Uniform vertexOffsetUniform; public PassThroughCullingProgramDispatcher(VertexFormat.Mode mode, ResourceLocation key) { this.mode = mode; this.program = ComputeShaderProgramLoader.getProgram(key); this.polygonCountUniform = program .getUniform("polygonCount"); this.vertexOffsetUniform = program .getUniform("vertexOffset"); } @Override public int dispatch(AcceleratedBufferBuilder builder) { var vertexCount = builder .getTotalVertexCount(); var polygonCount = vertexCount / mode.primitiveLength; polygonCountUniform.uploadUnsignedInt(polygonCount); vertexOffsetUniform.uploadUnsignedInt((int) (builder.getVertexBuffer().getOffset() / builder.getVertexSize())); program.useProgram (); program.dispatch ( (polygonCount + GROUP_SIZE - 1) / GROUP_SIZE, DISPATCH_COUNT_Y_Z, DISPATCH_COUNT_Y_Z ); return program.getBarrierFlags(); } @Override public boolean shouldCull() { return false; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/culling/PassThroughCullingProgramSelector.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs.culling; import net.minecraft.client.renderer.RenderType; public class PassThroughCullingProgramSelector implements ICullingProgramSelector { public static final ICullingProgramSelector INSTANCE = new PassThroughCullingProgramSelector(); @Override public ICullingProgramDispatcher select(RenderType renderType) { return switch (renderType.mode) { case QUADS -> PassThroughCullingProgramDispatcher.QUAD; case TRIANGLES -> PassThroughCullingProgramDispatcher.TRIANGLE; default -> throw new IllegalArgumentException("Unsupported mode: " + renderType.mode); }; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/dispatchers/EmptyProgramDispatcher.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs.dispatchers; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder; public class EmptyProgramDispatcher implements IPolygonProgramDispatcher { public static final EmptyProgramDispatcher INSTANCE = new EmptyProgramDispatcher(); @Override public int dispatch(AcceleratedBufferBuilder builder) { return 0; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/dispatchers/FixedPolygonProgramDispatcher.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs.dispatchers; import com.github.argon4w.acceleratedrendering.core.backends.programs.ComputeProgram; import com.github.argon4w.acceleratedrendering.core.backends.programs.Uniform; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder; import com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderProgramLoader; import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.resources.ResourceLocation; public class FixedPolygonProgramDispatcher implements IPolygonProgramDispatcher { private static final int GROUP_SIZE = 128; private static final int DISPATCH_COUNT_Y_Z = 1; private final VertexFormat.Mode mode; private final ComputeProgram program; private final Uniform polygonCountUniform; private final Uniform vertexOffsetUniform; public FixedPolygonProgramDispatcher(VertexFormat.Mode mode, ResourceLocation key) { this.mode = mode; this.program = ComputeShaderProgramLoader.getProgram(key); this.polygonCountUniform = this.program .getUniform("polygonCount"); this.vertexOffsetUniform = this.program .getUniform("vertexOffset"); } @Override public int dispatch(AcceleratedBufferBuilder builder) { var vertexCount = builder .getTotalVertexCount(); var polygonCount = vertexCount / mode.primitiveLength; polygonCountUniform.uploadUnsignedInt(polygonCount); vertexOffsetUniform.uploadUnsignedInt((int) (builder.getVertexBuffer().getOffset() / builder.getVertexSize())); program.useProgram (); program.dispatch ( (polygonCount + GROUP_SIZE - 1) / GROUP_SIZE, DISPATCH_COUNT_Y_Z, DISPATCH_COUNT_Y_Z ); return program.getBarrierFlags(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/dispatchers/IPolygonProgramDispatcher.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs.dispatchers; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder; public interface IPolygonProgramDispatcher { int dispatch(AcceleratedBufferBuilder builder); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/dispatchers/MeshUploadingProgramDispatcher.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs.dispatchers; import com.github.argon4w.acceleratedrendering.core.backends.buffers.IServerBuffer; import com.github.argon4w.acceleratedrendering.core.backends.programs.ComputeProgram; import com.github.argon4w.acceleratedrendering.core.backends.programs.Uniform; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.AcceleratedRingBuffers; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.meshes.MeshUploaderPool; import com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderProgramLoader; import com.github.argon4w.acceleratedrendering.core.programs.overrides.IUploadingShaderProgramOverride; import it.unimi.dsi.fastutil.objects.Reference2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.ReferenceArrayList; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.FastColor; import java.util.Collection; import java.util.List; import java.util.Map; import static org.lwjgl.opengl.GL46.*; public class MeshUploadingProgramDispatcher { private static final int GROUP_SIZE = 128; private static final int DISPATCH_COUNT_Y_Z = 1; public static final int SPARSE_MESH_BUFFER_INDEX = 5; public static final int MESH_BUFFER_INDEX = 7; private final Map> denseUploaders; private final Map> sparseUploaders; private IUploadingShaderProgramOverride lastOverride; private int lastBarriers; public MeshUploadingProgramDispatcher() { this.denseUploaders = new Reference2ObjectLinkedOpenHashMap<>(); this.sparseUploaders = new Reference2ObjectLinkedOpenHashMap<>(); this.lastOverride = null; this.lastBarriers = GL_SHADER_STORAGE_BARRIER_BIT; } public void dispatch(Collection builders, AcceleratedRingBuffers.Buffers buffer) { glMemoryBarrier(lastBarriers); lastOverride = null; var transform = buffer .getBufferEnvironment () .selectTransformProgramDispatcher (); for (var builder : builders) { var vertexBuffer = builder .getVertexBuffer (); var varyingBuffer = builder .getVaryingBuffer (); var meshVertexCount = builder .getMeshVertexCount (); vertexBuffer .reserve (meshVertexCount * builder.getVertexSize ()); varyingBuffer .reserve (meshVertexCount * builder.getVaryingSize ()); vertexBuffer .allocateOffset (); varyingBuffer .allocateOffset (); } buffer.prepare (); buffer.bindTransformBuffers (); for (var builder : builders) { var offset = 0; var sparseStart = 0; var vertexBuffer = builder .getVertexBuffer (); var varyingBuffer = builder .getVaryingBuffer (); var vertexCount = builder .getVertexCount (); var vertexAddress = vertexBuffer .getCurrent (); var varyingAddress = varyingBuffer .getCurrent (); var vertexOffset = vertexBuffer .getOffset () / builder.getVertexSize (); var varyingOffset = varyingBuffer .getOffset () / builder.getVaryingSize (); for (var uploader : builder .getMeshUploaders () .values () ) { var serverMesh = uploader .getServerMesh (); var meshCount = uploader.getMeshInfos() .getMeshCount (); var meshDense = serverMesh .forceDense () || meshCount >= 128; var meshBuffer = serverMesh .meshBuffer (); var dense = denseUploaders .get (meshBuffer); var sparse = sparseUploaders .get (meshBuffer); if (dense == null) { dense = new ReferenceArrayList<> (); sparse = new ReferenceArrayList<> (); denseUploaders .put (meshBuffer, dense); sparseUploaders .put (meshBuffer, sparse); } (meshDense ? dense : sparse).add(uploader); } for ( var meshBuffer : sparseUploaders.keySet()) { for ( var uploader : sparseUploaders.get (meshBuffer)) { var mesh = uploader .getServerMesh (); var meshInfos = uploader .getMeshInfos (); var meshCount = meshInfos .getMeshCount (); var meshSize = mesh .size (); for (var i = 0; i < meshCount; i ++) { builder.getColorOffset ().at(offset) .putInt (vertexAddress, FastColor.ABGR32.fromArgb32 (meshInfos.getColor(i))); builder.getUv1Offset ().at(offset) .putInt (vertexAddress, meshInfos .getOverlay (i)); builder.getUv2Offset ().at(offset) .putInt (vertexAddress, meshInfos .getLight (i)); builder.getVaryingSharing ().at(offset) .putInt (varyingAddress, meshInfos .getSharing (i)); builder.getVaryingMesh ().at(offset) .putInt (varyingAddress, mesh .offset ()); builder.getVaryingShouldCull().at(offset) .putInt (varyingAddress, meshInfos .getShouldCull (i)); builder.getTransformOverride() .uploadVarying (varyingAddress, offset); for (var offsetValue = 0; offsetValue < meshSize; offsetValue ++) { builder .getVaryingOffset () .at (offset) .at (offsetValue) .putInt (varyingAddress, offsetValue); } offset += meshSize; } } var count = offset - sparseStart; if (count != 0) { meshBuffer.bindBase(GL_SHADER_STORAGE_BUFFER, SPARSE_MESH_BUFFER_INDEX); lastOverride = null; lastBarriers |= transform.dispatch( builder, vertexBuffer, varyingBuffer, count, sparseStart + vertexCount + vertexOffset, sparseStart + vertexCount + varyingOffset ); } sparseStart = offset; } for (var meshBuffer : denseUploaders.keySet()) { meshBuffer.bindBase(GL_SHADER_STORAGE_BUFFER, MESH_BUFFER_INDEX); for (var uploader : denseUploaders.get(meshBuffer)) { var currentOverride = builder .getUploadingOverride (); var meshCount = uploader.getMeshInfos() .getMeshCount (); var mesh = uploader .getServerMesh (); var meshSize = mesh .size (); var uploadSize = meshCount * meshSize; if (lastOverride == null) { lastOverride = currentOverride; lastOverride.useProgram (); lastOverride.setupProgram (); } transform .resetOverride (); uploader .upload (); uploader .bindBuffers (); lastBarriers |= currentOverride .dispatchUploading ( uploadSize, meshCount, meshSize, (int) (offset + vertexCount + vertexOffset), (int) (offset + vertexCount + varyingOffset), (int) mesh.offset() ); offset += uploadSize; } } for (var meshBuffer : denseUploaders.keySet()) { denseUploaders .get(meshBuffer).clear(); sparseUploaders .get(meshBuffer).clear(); } } } public void resetOverride() { lastOverride = null; } public static class Default implements IUploadingShaderProgramOverride { private final long meshInfoSize; private final ComputeProgram program; private final Uniform meshCountUniform; private final Uniform meshSizeUniform; private final Uniform vertexOffsetUniform; private final Uniform varyingOffsetUniform; private final Uniform meshOffsetUniform; public Default(ResourceLocation key, long meshInfoSize) { this.meshInfoSize = meshInfoSize; this.program = ComputeShaderProgramLoader.getProgram(key); this.meshCountUniform = program .getUniform("meshCount"); this.meshSizeUniform = program .getUniform("meshSize"); this.vertexOffsetUniform = program .getUniform("vertexOffset"); this.varyingOffsetUniform = program .getUniform("varyingOffset"); this.meshOffsetUniform = program .getUniform("meshOffset"); } @Override public long getMeshInfoSize() { return meshInfoSize; } @Override public void useProgram() { program.useProgram(); } @Override public void setupProgram() { program.setup(); } @Override public void uploadMeshInfo(long meshInfoAddress, int meshInfoIndex) { } @Override public int dispatchUploading( int uploadSize, int meshCount, int meshSize, int vertexOffset, int varyingOffset, int meshOffset ) { meshCountUniform .uploadUnsignedInt (meshCount); meshSizeUniform .uploadUnsignedInt (meshSize); vertexOffsetUniform .uploadUnsignedInt (vertexOffset); varyingOffsetUniform.uploadUnsignedInt (varyingOffset); meshOffsetUniform .uploadUnsignedInt (meshOffset); program .dispatch ( (uploadSize + GROUP_SIZE - 1) / GROUP_SIZE, DISPATCH_COUNT_Y_Z, DISPATCH_COUNT_Y_Z ); return program.getBarrierFlags(); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/dispatchers/TransformProgramDispatcher.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs.dispatchers; import com.github.argon4w.acceleratedrendering.core.backends.programs.ComputeProgram; import com.github.argon4w.acceleratedrendering.core.backends.programs.Uniform; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.pools.StagingBufferPool; import com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderProgramLoader; import com.github.argon4w.acceleratedrendering.core.programs.overrides.ITransformShaderProgramOverride; import net.minecraft.resources.ResourceLocation; import java.util.Collection; import static org.lwjgl.opengl.GL46.*; public class TransformProgramDispatcher { public static final int VERTEX_BUFFER_IN_INDEX = 0; public static final int VARYING_BUFFER_IN_INDEX = 3; private static final int GROUP_SIZE = 128; private static final int DISPATCH_COUNT_Y_Z = 1; private ITransformShaderProgramOverride lastOverride; private int lastBarriers; public TransformProgramDispatcher() { this.lastOverride = null; this.lastBarriers = GL_SHADER_STORAGE_BARRIER_BIT; } public void dispatch(Collection builders) { glMemoryBarrier(lastBarriers); for (var builder : builders) { var currentOverride = builder .getTransformOverride (); var vertexCount = builder .getVertexCount (); var vertexBuffer = builder .getVertexBuffer (); var varyingBuffer = builder .getVaryingBuffer (); if (lastOverride != currentOverride) { lastOverride = currentOverride; lastOverride.useProgram (); lastOverride.setupProgram (); } if (vertexCount != 0) { vertexBuffer .bindBase (GL_SHADER_STORAGE_BUFFER, VERTEX_BUFFER_IN_INDEX); varyingBuffer .bindBase (GL_SHADER_STORAGE_BUFFER, VARYING_BUFFER_IN_INDEX); lastBarriers |= currentOverride .dispatchTransform ( vertexCount, (int) (vertexBuffer .getOffset() / builder.getVertexSize ()), (int) (varyingBuffer.getOffset() / builder.getVaryingSize ()) ); } } resetOverride (); glUseProgram (0); } public int dispatch( AcceleratedBufferBuilder builder, StagingBufferPool.StagingBuffer vertexBuffer, StagingBufferPool.StagingBuffer varyingBuffer, long vertexCount, long vertexOffset, long varyingOffset ) { var currentOverride = builder.getTransformOverride(); if (lastOverride != currentOverride) { lastOverride = currentOverride; lastOverride.useProgram (); lastOverride.setupProgram (); } vertexBuffer .bindBase(GL_SHADER_STORAGE_BUFFER, VERTEX_BUFFER_IN_INDEX); varyingBuffer .bindBase(GL_SHADER_STORAGE_BUFFER, VARYING_BUFFER_IN_INDEX); return currentOverride .dispatchTransform ( (int) vertexCount, (int) vertexOffset, (int) varyingOffset ); } public void resetOverride() { lastOverride = null; } public static class Default implements ITransformShaderProgramOverride { private final long varyingSize; private final ComputeProgram program; private final Uniform vertexCountUniform; private final Uniform vertexOffsetUniform; private final Uniform varyingOffsetUniform; public Default(ResourceLocation key, long varyingSize) { this.varyingSize = varyingSize; this.program = ComputeShaderProgramLoader.getProgram(key); this.vertexCountUniform = program .getUniform("vertexCount"); this.vertexOffsetUniform = program .getUniform("vertexOffset"); this.varyingOffsetUniform = program .getUniform("varyingOffset"); } @Override public long getVaryingSize() { return varyingSize; } @Override public void useProgram() { program.useProgram(); } @Override public void setupProgram() { program.setup(); } @Override public void uploadVarying(long varyingAddress, int offset) { } @Override public int dispatchTransform( int vertexCount, int vertexOffset, int varyingOffset ) { vertexCountUniform .uploadUnsignedInt (vertexCount); vertexOffsetUniform .uploadUnsignedInt (vertexOffset); varyingOffsetUniform .uploadUnsignedInt (varyingOffset); program .dispatch ( (vertexCount + GROUP_SIZE - 1) / GROUP_SIZE, DISPATCH_COUNT_Y_Z, DISPATCH_COUNT_Y_Z ); return program.getBarrierFlags(); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/overrides/IShaderProgramOverride.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs.overrides; public interface IShaderProgramOverride { void useProgram (); void setupProgram (); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/overrides/IShaderProgramOverrides.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs.overrides; import net.minecraft.client.renderer.RenderType; import java.util.Map; public interface IShaderProgramOverrides { Map getTransformOverrides(); Map getUploadingOverrides(); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/overrides/ITransformShaderProgramOverride.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs.overrides; public interface ITransformShaderProgramOverride extends IShaderProgramOverride { void uploadVarying (long varyingAddress, int offset); int dispatchTransform (int vertexCount, int vertexOffset, int varyingOffset); long getVaryingSize (); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/overrides/IUploadingShaderProgramOverride.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs.overrides; public interface IUploadingShaderProgramOverride extends IShaderProgramOverride { void uploadMeshInfo (long meshInfoAddress, int meshInfoIndex); int dispatchUploading (int meshCount, int meshSize, int vertexOffset, int varyingOffset, int meshOffset, int uploadSize); long getMeshInfoSize (); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/overrides/LoadShaderProgramOverridesEvent.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs.overrides; import com.mojang.blaze3d.vertex.VertexFormat; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Getter; import net.minecraft.client.renderer.RenderType; import net.neoforged.bus.api.Event; import net.neoforged.fml.event.IModBusEvent; public class LoadShaderProgramOverridesEvent extends Event implements IModBusEvent { private final VertexFormat vertexFormat; private final Object2ObjectOpenHashMap transformOverrides; private final Object2ObjectOpenHashMap uploadingOverrides; public LoadShaderProgramOverridesEvent(VertexFormat vertexFormat) { this.vertexFormat = vertexFormat; this.transformOverrides = new Object2ObjectOpenHashMap<>(); this.uploadingOverrides = new Object2ObjectOpenHashMap<>(); } public void loadFor( VertexFormat vertexFormat, RenderType renderType, IShaderProgramOverride override ) { if (this.vertexFormat == vertexFormat) { switch (override) { case ITransformShaderProgramOverride transform -> transformOverrides.put (renderType, transform); case IUploadingShaderProgramOverride uploading -> uploadingOverrides.put (renderType, uploading); default -> throw new UnsupportedOperationException ("Unsupported override type: " + override.getClass().getSimpleName()); } } } public IShaderProgramOverrides getOverrides(ITransformShaderProgramOverride defaultTransformOverride, IUploadingShaderProgramOverride defaultUploadingOverride) { return new ProgramOverrides( transformOverrides, uploadingOverrides, defaultTransformOverride, defaultUploadingOverride ); } @Getter public static class ProgramOverrides implements IShaderProgramOverrides { private final Object2ObjectOpenHashMap transformOverrides; private final Object2ObjectOpenHashMap uploadingOverrides; public ProgramOverrides( Object2ObjectOpenHashMap transformOverrides, Object2ObjectOpenHashMap uploadingOverrides, ITransformShaderProgramOverride defaultTransformOverride, IUploadingShaderProgramOverride defaultUploadingOverride ) { this.transformOverrides = transformOverrides; this.uploadingOverrides = uploadingOverrides; this.transformOverrides.defaultReturnValue(defaultTransformOverride); this.uploadingOverrides.defaultReturnValue(defaultUploadingOverride); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/overrides/OverrideProgramType.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs.overrides; public enum OverrideProgramType { TRANSFORM, UPLOADING } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/processing/EmptyPolygonProcessor.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs.processing; import com.github.argon4w.acceleratedrendering.core.programs.dispatchers.EmptyProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.programs.dispatchers.IPolygonProgramDispatcher; import com.mojang.blaze3d.vertex.VertexFormat; public class EmptyPolygonProcessor implements IPolygonProcessor { public static final EmptyPolygonProcessor INSTANCE = new EmptyPolygonProcessor(); @Override public IPolygonProgramDispatcher select(VertexFormat.Mode mode) { return EmptyProgramDispatcher.INSTANCE; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/processing/IPolygonProcessor.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs.processing; import com.github.argon4w.acceleratedrendering.core.programs.dispatchers.IPolygonProgramDispatcher; import com.mojang.blaze3d.vertex.VertexFormat; public interface IPolygonProcessor { IPolygonProgramDispatcher select(VertexFormat.Mode mode); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/programs/processing/LoadPolygonProcessorEvent.java ================================================ package com.github.argon4w.acceleratedrendering.core.programs.processing; import com.mojang.blaze3d.vertex.VertexFormat; import lombok.Getter; import net.neoforged.bus.api.Event; import net.neoforged.fml.event.IModBusEvent; import java.util.function.UnaryOperator; public class LoadPolygonProcessorEvent extends Event implements IModBusEvent { private final VertexFormat vertexFormat; @Getter private IPolygonProcessor processor; public LoadPolygonProcessorEvent(VertexFormat vertexFormat) { this.vertexFormat = vertexFormat; this.processor = EmptyPolygonProcessor.INSTANCE; } public void loadFor(VertexFormat vertexFormat, UnaryOperator selector) { if (this.vertexFormat == vertexFormat) { this.processor = selector.apply(this.processor); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/utils/CullerUtils.java ================================================ package com.github.argon4w.acceleratedrendering.core.utils; import com.mojang.blaze3d.platform.NativeImage; import net.minecraft.util.FastColor; import net.minecraft.util.Mth; import org.joml.Vector3f; public class CullerUtils { public static boolean shouldCull(Vertex[] vertices, NativeImage texture) { if (texture == null) { return false; } if (vertices.length == 4) { var vertex0 = new Vector3f(vertices[0].getPosition()); var vector1 = new Vector3f(vertices[1].getPosition()).sub(vertex0); var vector2 = new Vector3f(vertices[2].getPosition()).sub(vertex0); var vector3 = new Vector3f(vertices[3].getPosition()).sub(vertex0); var length1 = vector1.cross(vector2).length(); var length2 = vector1.cross(vector3).length(); if (length1 == 0 && length2 == 0) { return true; } } var minU = 1.0f; var minV = 1.0f; var maxU = 0.0f; var maxV = 0.0f; for (var vertex : vertices) { var uv = vertex.getUv(); var u = uv .x; var v = uv .y; minU = Math.min(minU, u); minV = Math.min(minV, v); maxU = Math.max(maxU, u); maxV = Math.max(maxV, v); } var width = texture.getWidth (); var height = texture.getHeight (); var minX = Mth.floor (minU * texture.getWidth ()); var minY = Mth.floor (minV * texture.getHeight ()); var maxX = Mth.ceil (maxU * texture.getWidth ()); var maxY = Mth.ceil (maxV * texture.getHeight ()); for ( var x = minX; x <= maxX; x ++) { for ( var y = minY; y <= maxY; y ++) { var clampedX = x % width; var clampedY = y % height; clampedX = clampedX < 0 ? width + clampedX : clampedX; clampedY = clampedY < 0 ? height + clampedY : clampedY; if (FastColor.ABGR32.alpha(texture.getPixelRGBA(clampedX, clampedY)) != 0) { return false; } } } return true; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/utils/DirectionUtils.java ================================================ package com.github.argon4w.acceleratedrendering.core.utils; import net.minecraft.core.Direction; public class DirectionUtils { public static final Direction[] FULL = new Direction[] { null, Direction.DOWN, Direction.UP, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST }; } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/utils/EmptyIterator.java ================================================ package com.github.argon4w.acceleratedrendering.core.utils; import java.util.Iterator; import java.util.NoSuchElementException; public class EmptyIterator implements Iterator { public static final EmptyIterator INSTANCE = new EmptyIterator<>(); @Override public boolean hasNext() { return false; } @Override public T next() { throw new NoSuchElementException(); } @SuppressWarnings("unchecked") public static Iterator of() { return (Iterator) INSTANCE; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/utils/FastColorUtils.java ================================================ package com.github.argon4w.acceleratedrendering.core.utils; public class FastColorUtils { public static int convert(int color) { return color & 0xFF00FF00 | ( color & 0x00FF0000) >> 16 | ( color & 0x000000FF) << 16; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/utils/FuzzyMatrix4f.java ================================================ package com.github.argon4w.acceleratedrendering.core.utils; import org.joml.Matrix4f; import org.joml.Matrix4fc; public class FuzzyMatrix4f extends Matrix4f { public FuzzyMatrix4f(Matrix4f matrix) { super(matrix); } public FuzzyMatrix4f() { super(); } @Override public int hashCode() { return 61; } @Override public boolean equals(Object obj) { return obj instanceof Matrix4fc matrix && equals(matrix, 1e-2f); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/utils/IntArrayHashStrategy.java ================================================ package com.github.argon4w.acceleratedrendering.core.utils; import it.unimi.dsi.fastutil.Hash; import java.util.Arrays; public class IntArrayHashStrategy implements Hash.Strategy { public static final IntArrayHashStrategy INSTANCE = new IntArrayHashStrategy(); @Override public int hashCode(int[] o) { return Arrays.hashCode(o); } @Override public boolean equals(int[] a, int[] b) { return Arrays.equals(a, b); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/utils/LoopResetPool.java ================================================ package com.github.argon4w.acceleratedrendering.core.utils; public abstract class LoopResetPool extends SimpleResetPool { public LoopResetPool(int size, C context) { super(size, context); } @Override @SuppressWarnings("unchecked") public T get(boolean force) { for (var i = 0; i < size; i++) { var t = (T) pool[i]; if (test(t)) { init(t); return t; } } return fail(force); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/utils/MemUtils.java ================================================ package com.github.argon4w.acceleratedrendering.core.utils; import net.minecraft.util.Mth; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.lwjgl.system.MemoryUtil; public class MemUtils { public static void putNormal(long address, float value) { MemoryUtil.memPutByte(address, (byte) ((int) (Mth.clamp(value, -1.0f, 1.0f) * 127.0f) & 0xFF)); } public static void putMatrix3f(long address, Matrix3f matrix) { MemoryUtil.memPutFloat(address + 0L * 4L, matrix.m00()); MemoryUtil.memPutFloat(address + 1L * 4L, matrix.m01()); MemoryUtil.memPutFloat(address + 2L * 4L, matrix.m02()); MemoryUtil.memPutFloat(address + 4L * 4L, matrix.m10()); MemoryUtil.memPutFloat(address + 5L * 4L, matrix.m11()); MemoryUtil.memPutFloat(address + 6L * 4L, matrix.m12()); MemoryUtil.memPutFloat(address + 8L * 4L, matrix.m20()); MemoryUtil.memPutFloat(address + 9L * 4L, matrix.m21()); MemoryUtil.memPutFloat(address + 10L * 4L, matrix.m22()); } public static void putMatrix4f(long address, Matrix4f matrix) { MemoryUtil.memPutFloat(address + 0L * 4L, matrix.m00()); MemoryUtil.memPutFloat(address + 1L * 4L, matrix.m01()); MemoryUtil.memPutFloat(address + 2L * 4L, matrix.m02()); MemoryUtil.memPutFloat(address + 3L * 4L, matrix.m03()); MemoryUtil.memPutFloat(address + 4L * 4L, matrix.m10()); MemoryUtil.memPutFloat(address + 5L * 4L, matrix.m11()); MemoryUtil.memPutFloat(address + 6L * 4L, matrix.m12()); MemoryUtil.memPutFloat(address + 7L * 4L, matrix.m13()); MemoryUtil.memPutFloat(address + 8L * 4L, matrix.m20()); MemoryUtil.memPutFloat(address + 9L * 4L, matrix.m21()); MemoryUtil.memPutFloat(address + 10L * 4L, matrix.m22()); MemoryUtil.memPutFloat(address + 11L * 4L, matrix.m23()); MemoryUtil.memPutFloat(address + 12L * 4L, matrix.m30()); MemoryUtil.memPutFloat(address + 13L * 4L, matrix.m31()); MemoryUtil.memPutFloat(address + 14L * 4L, matrix.m32()); MemoryUtil.memPutFloat(address + 15L * 4L, matrix.m33()); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/utils/MutableSize.java ================================================ package com.github.argon4w.acceleratedrendering.core.utils; import lombok.Getter; @Getter public class MutableSize { protected boolean resized; protected long size; public MutableSize(long initialSize) { this.resized = false; this.size = initialSize; } public void expand(long bytes) { if (bytes <= 0) { return; } beforeExpand(); onExpand (bytes); doExpand (size, bytes); resized = true; size += bytes; afterExpand(); } public void onExpand(long bytes) { } public void doExpand(long size, long bytes) { } public void beforeExpand() { } public void afterExpand() { } public void resize(long atLeast) { resizeTo(Long.highestOneBit(atLeast) << 1); } public void resizeTo(long newBufferSize) { expand(newBufferSize - size); } public void resetResized() { resized = false; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/utils/PackedVector2i.java ================================================ package com.github.argon4w.acceleratedrendering.core.utils; public class PackedVector2i { public static int pack(float u, float v) { return pack((int) u, (int) v); } public static int pack(int u, int v) { return (u & 0xFFFF) | (v & 0xFFFF) << 16; } public static int unpackU(int packed) { return packed & 0xFFFF; } public static int unpackV(int packed) { return packed >>> 16 & 0xFFFF; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/utils/PoseStackExtension.java ================================================ package com.github.argon4w.acceleratedrendering.core.utils; import com.mojang.blaze3d.vertex.PoseStack; import org.joml.Matrix3f; import org.joml.Matrix4f; public class PoseStackExtension { public static void setPose( PoseStack in, Matrix4f transform, Matrix3f normal ) { var last = in.last(); last.pose ().set(transform); last.normal ().set(normal); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/utils/RegistryFilter.java ================================================ package com.github.argon4w.acceleratedrendering.core.utils; import it.unimi.dsi.fastutil.objects.ReferenceArrayList; import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; import it.unimi.dsi.fastutil.objects.ReferenceSets; import net.minecraft.core.Registry; import java.util.List; import java.util.Set; import java.util.regex.Pattern; public class RegistryFilter { public static Set filterValues(Registry registry, List values) { if (values.isEmpty()) { return ReferenceSets.emptySet(); } var patterns = new ReferenceArrayList (); var filtered = new ReferenceOpenHashSet (); for (var pattern : values) { patterns.add(Pattern.compile(pattern)); } for (var key : registry.keySet()) { for (var pattern : patterns) { if (pattern .matcher(key.toString()) .matches() ) { filtered.add(registry.get(key)); break; } } } return filtered; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/utils/RenderTypeUtils.java ================================================ package com.github.argon4w.acceleratedrendering.core.utils; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.client.renderer.RenderStateShard; import net.minecraft.client.renderer.RenderType; import net.minecraft.resources.ResourceLocation; import org.lwjgl.opengl.GL11; import java.util.Map; public class RenderTypeUtils { public static final Map WITH_DEPTH_CACHE = new Object2ObjectOpenHashMap<>(); public static ResourceLocation getTextureLocation(RenderType renderType) { if (renderType == null) { return null; } if (!(renderType instanceof RenderType.CompositeRenderType composite)) { return null; } return composite .state .textureState .cutoutTexture() .orElse(null); } public static boolean isCulled(RenderType renderType) { if (renderType == null) { return false; } if (!(renderType instanceof RenderType.CompositeRenderType composite)) { return false; } return composite .state .cullState .enabled; } public static boolean isDynamic(RenderType renderType) { if (renderType == null) { return false; } if (!(renderType instanceof RenderType.CompositeRenderType composite)) { return false; } return composite .state .texturingState instanceof RenderStateShard.OffsetTexturingStateShard; } public static boolean hasDepth(RenderType renderType) { if (renderType == null) { return false; } if (!(renderType instanceof RenderType.CompositeRenderType composite)) { return false; } return composite .state .depthTestState != RenderStateShard.NO_DEPTH_TEST; } public static RenderType withDepth(RenderType renderType) { if (renderType == null) { return null; } if (hasDepth(renderType)) { return null; } if (!(renderType instanceof RenderType.CompositeRenderType composite)) { return null; } var result = WITH_DEPTH_CACHE.get(renderType); if (result != null) { return result; } var state = composite.state; result = RenderType.create( renderType.name, renderType.format, renderType.mode, renderType.bufferSize, renderType.affectsCrumbling, renderType.sortOnUpload, RenderType.CompositeState .builder () .setDepthTestState (RenderStateShard .LEQUAL_DEPTH_TEST) .setWriteMaskState (state .writeMaskState.writeColor ? RenderStateShard.COLOR_DEPTH_WRITE : RenderStateShard.DEPTH_WRITE) .setTextureState (state .textureState) .setShaderState (state .shaderState) .setTransparencyState (state .transparencyState) .setCullState (state .cullState) .setLightmapState (state .lightmapState) .setOverlayState (state .overlayState) .setLayeringState (state .layeringState) .setOutputState (state .outputState) .setTexturingState (state .texturingState) .setLineState (state .lineState) .setColorLogicState (state .colorLogicState) .createCompositeState (state .outlineProperty) ); return result; } public static LayerDrawType getDrawType(RenderType renderType) { return renderType.sortOnUpload ? LayerDrawType.TRANSLUCENT : LayerDrawType.OPAQUE; } public static boolean isTranslucent(RenderType renderType) { return renderType.sortOnUpload; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/utils/ResourceLocationUtils.java ================================================ package com.github.argon4w.acceleratedrendering.core.utils; import com.github.argon4w.acceleratedrendering.AcceleratedRenderingModEntry; import net.minecraft.resources.ResourceLocation; public class ResourceLocationUtils { public static ResourceLocation create(String path) { return ResourceLocation.fromNamespaceAndPath(AcceleratedRenderingModEntry.MOD_ID, path); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/utils/SimpleCachedArray.java ================================================ package com.github.argon4w.acceleratedrendering.core.utils; import java.util.function.IntFunction; public class SimpleCachedArray extends SimpleResetPool> { public SimpleCachedArray(int size, IntFunction initializer) { super(size, initializer); } @Override protected T create(IntFunction context, int i) { return context.apply(i); } @Override protected void reset(T t) { t.reset(); } @Override protected void delete(T t) { t.delete(); } @Override public T fail() { expand(); return get(); } public interface Element { void reset (); void delete (); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/utils/SimpleResetPool.java ================================================ package com.github.argon4w.acceleratedrendering.core.utils; import lombok.Getter; import java.util.Arrays; public abstract class SimpleResetPool { @Getter protected final C context; @Getter protected Object[] pool; @Getter protected int cursor; protected int size; public SimpleResetPool(int size, C context) { this.size = size; this.pool = new Object[size]; this.context = context; this.cursor = 0; for (var i = 0; i < this.size; i++) { this.pool[i] = create(this.context, i); } } protected abstract T create (C context, int i); protected abstract void reset (T t); protected abstract void delete (T t); @SuppressWarnings("unchecked") public T get(boolean force) { if (cursor < size) { var t = (T) pool[cursor ++]; if (test(t)) { init(t); return t; } } return fail(force); } @SuppressWarnings("unchecked") public void reset() { for (var i = 0; i < cursor; i++) { reset((T) pool[i]); } cursor = 0; } @SuppressWarnings("unchecked") public void delete() { for (var i = 0; i < size; i++) { delete((T) pool[i]); } } protected void expand() { var old = size; size = old * 2; pool = Arrays.copyOf(pool, size); for (var i = old; i < size; i ++) { pool[i] = create(context, i); } } @SuppressWarnings("unchecked") public T at(int index) { return (T) pool[index]; } public T get() { return get(false); } public void init(T t) { } protected T fail(boolean force) { return fail(); } public T fail() { return null; } protected boolean test(T t) { return true; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/utils/SimpleTextureTarget.java ================================================ package com.github.argon4w.acceleratedrendering.core.utils; import com.mojang.blaze3d.pipeline.TextureTarget; import net.minecraft.client.Minecraft; public class SimpleTextureTarget extends TextureTarget { public SimpleTextureTarget(boolean useDepth) { super( Minecraft.getInstance().getWindow().getWidth (), Minecraft.getInstance().getWindow().getHeight (), useDepth, Minecraft.ON_OSX ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/utils/TextureUtils.java ================================================ package com.github.argon4w.acceleratedrendering.core.utils; import com.github.argon4w.acceleratedrendering.AcceleratedRenderingModEntry; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.mojang.blaze3d.platform.NativeImage; import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.ResourceManagerReloadListener; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.neoforge.client.event.RegisterClientReloadListenersEvent; import org.lwjgl.system.MemoryStack; import static org.lwjgl.opengl.GL46.*; @EventBusSubscriber( modid = AcceleratedRenderingModEntry .MOD_ID, bus = EventBusSubscriber.Bus .MOD, value = Dist .CLIENT ) public class TextureUtils implements ResourceManagerReloadListener { private static final TextureUtils INSTANCE = new TextureUtils (); private static final Object2ObjectLinkedOpenHashMap IMAGE_CACHE = new Object2ObjectLinkedOpenHashMap<> (); @Override public void onResourceManagerReload(ResourceManager resourceManager) { IMAGE_CACHE.clear(); } @SubscribeEvent public static void onRegisterClientReloadListener(RegisterClientReloadListenersEvent event) { event.registerReloadListener(INSTANCE); } public static NativeImage downloadTexture(RenderType renderType, int mipmapLevel) { var textureLocation = RenderTypeUtils.getTextureLocation(renderType); if (textureLocation == null) { return null; } var image = IMAGE_CACHE.getAndMoveToFirst(textureLocation); if (image != null) { return image; } Minecraft .getInstance () .getTextureManager () .getTexture (textureLocation) .bind (); try (var stack = MemoryStack.stackPush()) { var widthBuffer = stack.callocInt(1); var heightBuffer = stack.callocInt(1); glGetTexLevelParameteriv( GL_TEXTURE_2D, mipmapLevel, GL_TEXTURE_WIDTH, widthBuffer ); glGetTexLevelParameteriv( GL_TEXTURE_2D, mipmapLevel, GL_TEXTURE_HEIGHT, heightBuffer ); var width = widthBuffer .get(0); var height = heightBuffer .get(0); if (width == 0 || height == 0) { return null; } var nativeImage = new NativeImage( width, height, false ); nativeImage .downloadTexture (mipmapLevel, false); IMAGE_CACHE .putAndMoveToFirst (textureLocation, nativeImage); if (IMAGE_CACHE.size() > CoreFeature.getCachedImageSize()) { IMAGE_CACHE .removeLast () .close (); } return nativeImage; } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/core/utils/Vertex.java ================================================ package com.github.argon4w.acceleratedrendering.core.utils; import lombok.EqualsAndHashCode; import lombok.Getter; import net.minecraft.util.FastColor; import net.minecraft.util.Mth; import org.joml.Vector2f; import org.joml.Vector2i; import org.joml.Vector3f; import org.joml.Vector4i; @Getter @EqualsAndHashCode public class Vertex { public static final int NORMAL_X_OFFSET = 0; public static final int NORMAL_Y_OFFSET = 8; public static final int NORMAL_Z_OFFSET = 16; private final Vector3f position; private final Vector2f uv; private final Vector4i color; private final Vector2i light; private final Vector3f normal; public Vertex() { this.position = new Vector3f(); this.uv = new Vector2f(); this.color = new Vector4i(); this.light = new Vector2i(); this.normal = new Vector3f(); } public Vertex(Vertex vertex) { this.position = new Vector3f(vertex.getPosition ()); this.uv = new Vector2f(vertex.getUv ()); this.color = new Vector4i(vertex.getColor ()); this.light = new Vector2i(vertex.getLight ()); this.normal = new Vector3f(vertex.getNormal ()); } public int getPackedLight() { return light.x | light.y << 16; } public int getPackedColor() { return FastColor.ARGB32.color( color.w, color.x, color.y, color.z ); } public int getPackedNormal() { return ((byte) ((int) (Mth.clamp(normal.x, -1.0f, 1.0f) * 127.0f) & 0xFF) << NORMAL_X_OFFSET) | ((byte) ((int) (Mth.clamp(normal.y, -1.0f, 1.0f) * 127.0f) & 0xFF) << NORMAL_Y_OFFSET) | ((byte) ((int) (Mth.clamp(normal.z, -1.0f, 1.0f) * 127.0f) & 0xFF) << NORMAL_Z_OFFSET); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/culling/OrientationCullingFeature.java ================================================ package com.github.argon4w.acceleratedrendering.features.culling; import com.github.argon4w.acceleratedrendering.configs.FeatureConfig; import com.github.argon4w.acceleratedrendering.configs.FeatureStatus; import java.util.ArrayDeque; import java.util.Deque; public class OrientationCullingFeature { private static final Deque CULLING_CONTROLLER_STACK = new ArrayDeque<>(); public static boolean isEnabled() { return FeatureConfig.CONFIG.orientationCullingFeatureStatus.get() == FeatureStatus.ENABLED; } public static boolean shouldIgnoreCullState() { return FeatureConfig.CONFIG.orientationCullingIgnoreCullState.get() == FeatureStatus.ENABLED; } public static boolean shouldCull() { return getCullingSetting() == FeatureStatus.ENABLED; } public static void disableCulling() { CULLING_CONTROLLER_STACK.push(FeatureStatus.DISABLED); } public static void forceEnableCulling() { CULLING_CONTROLLER_STACK.push(FeatureStatus.ENABLED); } public static void forceSetCulling(FeatureStatus status) { CULLING_CONTROLLER_STACK.push(status); } public static void resetCullingSetting() { CULLING_CONTROLLER_STACK.pop(); } public static FeatureStatus getCullingSetting() { return CULLING_CONTROLLER_STACK.isEmpty() ? getDefaultCullingSetting() : CULLING_CONTROLLER_STACK.peek(); } public static FeatureStatus getDefaultCullingSetting() { return FeatureConfig.CONFIG.orientationCullingDefaultCulling.get(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/culling/OrientationCullingProgramDispatcher.java ================================================ package com.github.argon4w.acceleratedrendering.features.culling; import com.github.argon4w.acceleratedrendering.core.backends.programs.ComputeProgram; import com.github.argon4w.acceleratedrendering.core.backends.programs.Uniform; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.AcceleratedBufferBuilder; import com.github.argon4w.acceleratedrendering.core.programs.ComputeShaderProgramLoader; import com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramDispatcher; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.resources.ResourceLocation; public class OrientationCullingProgramDispatcher implements ICullingProgramDispatcher { private static final int GROUP_SIZE = 128; private static final int DISPATCH_COUNT_Y_Z = 1; private final VertexFormat.Mode mode; private final ComputeProgram program; private final Uniform viewMatrixUniform; private final Uniform projectMatrixUniform; private final Uniform polygonCountUniform; private final Uniform vertexOffsetUniform; private final Uniform varyingOffsetUniform; public OrientationCullingProgramDispatcher(VertexFormat.Mode mode, ResourceLocation key) { this.mode = mode; this.program = ComputeShaderProgramLoader.getProgram(key); this.viewMatrixUniform = this.program .getUniform("viewMatrix"); this.projectMatrixUniform = this.program .getUniform("projectMatrix"); this.polygonCountUniform = this.program .getUniform("polygonCount"); this.vertexOffsetUniform = this.program .getUniform("vertexOffset"); this.varyingOffsetUniform = this.program .getUniform("varyingOffset"); } @Override public int dispatch(AcceleratedBufferBuilder builder) { var vertexCount = builder .getTotalVertexCount(); var polygonCount = vertexCount / mode.primitiveLength; viewMatrixUniform .uploadMatrix4f (RenderSystem .getModelViewMatrix ()); projectMatrixUniform.uploadMatrix4f (RenderSystem .getProjectionMatrix()); polygonCountUniform .uploadUnsignedInt (polygonCount); vertexOffsetUniform .uploadUnsignedInt ((int) (builder .getVertexBuffer ().getOffset() / builder.getVertexSize ())); varyingOffsetUniform.uploadUnsignedInt ((int) (builder .getVaryingBuffer ().getOffset() / builder.getVaryingSize ())); program.useProgram (); program.dispatch ( (polygonCount + GROUP_SIZE - 1) / GROUP_SIZE, DISPATCH_COUNT_Y_Z, DISPATCH_COUNT_Y_Z ); return program.getBarrierFlags(); } @Override public boolean shouldCull() { return OrientationCullingFeature.shouldCull(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/culling/OrientationCullingProgramSelector.java ================================================ package com.github.argon4w.acceleratedrendering.features.culling; import com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramDispatcher; import com.github.argon4w.acceleratedrendering.core.programs.culling.ICullingProgramSelector; import com.github.argon4w.acceleratedrendering.core.utils.RenderTypeUtils; import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.client.renderer.RenderType; import net.minecraft.resources.ResourceLocation; public class OrientationCullingProgramSelector implements ICullingProgramSelector { private final ICullingProgramSelector parent; private final ICullingProgramDispatcher quadDispatcher; private final ICullingProgramDispatcher triangleDispatcher; public OrientationCullingProgramSelector( ICullingProgramSelector parent, ResourceLocation quadProgramKey, ResourceLocation triangleProgramKey ) { this.parent = parent; this.quadDispatcher = new OrientationCullingProgramDispatcher(VertexFormat.Mode.QUADS, quadProgramKey); this.triangleDispatcher = new OrientationCullingProgramDispatcher(VertexFormat.Mode.TRIANGLES, triangleProgramKey); } @Override public ICullingProgramDispatcher select(RenderType renderType) { if ( OrientationCullingFeature .isEnabled () && ( OrientationCullingFeature .shouldIgnoreCullState () || RenderTypeUtils.isCulled(renderType)) ) { return switch (renderType.mode) { case QUADS -> quadDispatcher; case TRIANGLES -> triangleDispatcher; default -> parent.select(renderType); }; } return parent.select(renderType); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/culling/OrientationCullingPrograms.java ================================================ package com.github.argon4w.acceleratedrendering.features.culling; import com.github.argon4w.acceleratedrendering.AcceleratedRenderingModEntry; import com.github.argon4w.acceleratedrendering.core.backends.programs.BarrierFlags; import com.github.argon4w.acceleratedrendering.core.programs.LoadComputeShaderEvent; import com.github.argon4w.acceleratedrendering.core.programs.culling.LoadCullingProgramSelectorEvent; import com.github.argon4w.acceleratedrendering.core.utils.ResourceLocationUtils; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import net.minecraft.resources.ResourceLocation; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.EventPriority; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.EventBusSubscriber; @EventBusSubscriber( modid = AcceleratedRenderingModEntry .MOD_ID, bus = EventBusSubscriber.Bus .MOD, value = Dist .CLIENT ) public class OrientationCullingPrograms { public static final ResourceLocation CORE_ENTITY_QUAD_CULLING_KEY = ResourceLocationUtils.create("core_entity_quad_culling"); public static final ResourceLocation CORE_ENTITY_TRIANGLE_CULLING_KEY = ResourceLocationUtils.create("core_entity_triangle_culling"); public static final ResourceLocation CORE_BLOCK_QUAD_CULLING_KEY = ResourceLocationUtils.create("core_block_quad_culling"); public static final ResourceLocation CORE_BLOCK_TRIANGLE_CULLING_KEY = ResourceLocationUtils.create("core_block_triangle_culling"); public static final ResourceLocation CORE_POS_TEX_COLOR_QUAD_CULLING_KEY = ResourceLocationUtils.create("core_pos_tex_color_quad_culling"); public static final ResourceLocation CORE_POS_TEX_COLOR_TRIANGLE_CULLING_KEY = ResourceLocationUtils.create("core_pos_tex_color_triangle_culling"); public static final ResourceLocation CORE_POS_TEX_QUAD_CULLING_KEY = ResourceLocationUtils.create("core_pos_tex_quad_culling"); public static final ResourceLocation CORE_POS_TEX_TRIANGLE_CULLING_KEY = ResourceLocationUtils.create("core_pos_tex_triangle_culling"); @SubscribeEvent public static void onLoadComputeShaders(LoadComputeShaderEvent event) { event.loadComputeShader( CORE_ENTITY_QUAD_CULLING_KEY, ResourceLocationUtils .create("shaders/core/culling/entity_quad_culling_shader.compute"), BarrierFlags .SHADER_STORAGE, BarrierFlags .ATOMIC_COUNTER ); event.loadComputeShader( CORE_ENTITY_TRIANGLE_CULLING_KEY, ResourceLocationUtils .create("shaders/core/culling/entity_triangle_culling_shader.compute"), BarrierFlags .SHADER_STORAGE, BarrierFlags .ATOMIC_COUNTER ); event.loadComputeShader( CORE_BLOCK_QUAD_CULLING_KEY, ResourceLocationUtils .create("shaders/core/culling/block_quad_culling_shader.compute"), BarrierFlags .SHADER_STORAGE, BarrierFlags .ATOMIC_COUNTER ); event.loadComputeShader( CORE_BLOCK_TRIANGLE_CULLING_KEY, ResourceLocationUtils .create("shaders/core/culling/block_triangle_culling_shader.compute"), BarrierFlags .SHADER_STORAGE, BarrierFlags .ATOMIC_COUNTER ); event.loadComputeShader( CORE_POS_TEX_COLOR_QUAD_CULLING_KEY, ResourceLocationUtils .create("shaders/core/culling/pos_tex_color_quad_culling_shader.compute"), BarrierFlags .SHADER_STORAGE, BarrierFlags .ATOMIC_COUNTER ); event.loadComputeShader( CORE_POS_TEX_COLOR_TRIANGLE_CULLING_KEY, ResourceLocationUtils .create("shaders/core/culling/pos_tex_color_triangle_culling_shader.compute"), BarrierFlags .SHADER_STORAGE, BarrierFlags .ATOMIC_COUNTER ); event.loadComputeShader( CORE_POS_TEX_QUAD_CULLING_KEY, ResourceLocationUtils .create("shaders/core/culling/pos_tex_quad_culling_shader.compute"), BarrierFlags .SHADER_STORAGE, BarrierFlags .ATOMIC_COUNTER ); event.loadComputeShader( CORE_POS_TEX_TRIANGLE_CULLING_KEY, ResourceLocationUtils .create("shaders/core/culling/pos_tex_triangle_culling_shader.compute"), BarrierFlags .SHADER_STORAGE, BarrierFlags .ATOMIC_COUNTER ); } @SubscribeEvent(priority = EventPriority.HIGH) public static void onLoadCullingPrograms(LoadCullingProgramSelectorEvent event) { event.loadFor(DefaultVertexFormat.NEW_ENTITY, parent -> new OrientationCullingProgramSelector( parent, CORE_ENTITY_QUAD_CULLING_KEY, CORE_ENTITY_TRIANGLE_CULLING_KEY )); event.loadFor(DefaultVertexFormat.BLOCK, parent -> new OrientationCullingProgramSelector( parent, CORE_BLOCK_QUAD_CULLING_KEY, CORE_BLOCK_TRIANGLE_CULLING_KEY )); event.loadFor(DefaultVertexFormat.POSITION_TEX_COLOR, parent -> new OrientationCullingProgramSelector( parent, CORE_POS_TEX_COLOR_QUAD_CULLING_KEY, CORE_POS_TEX_COLOR_TRIANGLE_CULLING_KEY )); event.loadFor(DefaultVertexFormat.POSITION_TEX, parent -> new OrientationCullingProgramSelector( parent, CORE_POS_TEX_QUAD_CULLING_KEY, CORE_POS_TEX_TRIANGLE_CULLING_KEY )); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/emf/IEMFModelVariant.java ================================================ package com.github.argon4w.acceleratedrendering.features.emf; public interface IEMFModelVariant { void setCurrentVariant(int variant); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/emf/mixins/EMFModelPartMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.emf.mixins; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IBufferGraph; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.github.argon4w.acceleratedrendering.core.meshes.IMesh; import com.github.argon4w.acceleratedrendering.core.meshes.collectors.CulledMeshCollector; import com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData; import com.github.argon4w.acceleratedrendering.features.emf.IEMFModelVariant; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.github.argon4w.acceleratedrendering.features.modelparts.mixins.ModelPartMixin; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.experimental.ExtensionMethod; import net.minecraft.client.model.geom.ModelPart; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import traben.entity_model_features.models.parts.EMFModelPart; import java.util.Map; @ExtensionMethod(VertexConsumerExtension.class) @Mixin (EMFModelPart .class) public class EMFModelPartMixin extends ModelPartMixin implements IEMFModelVariant { @Unique private final Int2ReferenceMap> emfMeshes = new Int2ReferenceOpenHashMap<>(); @Unique private final Int2ReferenceMap> emfMerges = new Int2ReferenceOpenHashMap<>(); @Unique private int emfVariant = Integer.MIN_VALUE; @Inject( method = "renderLikeVanilla", at = @At("HEAD"), cancellable = true ) public void renderLikeVanillaFast( PoseStack poseStack, VertexConsumer buffer, int packedLight, int packedOverlay, int color, CallbackInfo ci ) { var extension = buffer.getAccelerated(); if ( AcceleratedEntityRenderingFeature .isEnabled () && AcceleratedEntityRenderingFeature .shouldUseAcceleratedPipeline () && ( CoreFeature .isRenderingLevel () || ( CoreFeature .isRenderingGui () && AcceleratedEntityRenderingFeature .shouldAccelerateInGui ())) && extension .isAccelerated () ) { ci.cancel(); renderFast( (ModelPart) (Object) this, poseStack, extension, packedLight, packedOverlay, color ); } } @Inject( method = "compile", at = @At("HEAD"), cancellable = true ) public void compileFast( PoseStack.Pose pPose, VertexConsumer pBuffer, int pPackedLight, int pPackedOverlay, int pColor, CallbackInfo ci ) { var extension = pBuffer.getAccelerated(); if ( AcceleratedEntityRenderingFeature .isEnabled () && AcceleratedEntityRenderingFeature .shouldUseAcceleratedPipeline () && ( CoreFeature .isRenderingLevel () || ( CoreFeature .isRenderingGui () && AcceleratedEntityRenderingFeature .shouldAccelerateInGui ())) && extension .isAccelerated () ) { ci .cancel (); extension .doRender ( this, null, pPose.pose (), pPose.normal(), pPackedLight, pPackedOverlay, pColor ); } } @Unique @Override public void render( VertexConsumer vertexConsumer, Void context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { var meshes = emfMeshes.get(emfVariant); var merges = emfMerges.get(emfVariant); if ( meshes == null || merges == null ) { meshes = new Object2ObjectOpenHashMap<>(); merges = new Object2ObjectOpenHashMap<>(); emfMeshes.put(emfVariant, meshes); emfMerges.put(emfVariant, merges); } var extension = vertexConsumer.getAccelerated (); var mesh = meshes .get (extension); extension.beginTransform(transform, normal); if (mesh != null) { mesh.write( extension, color, light, overlay ); extension.endTransform(); return; } var culledMeshCollector = new CulledMeshCollector (extension); var meshBuilder = extension.decorate (culledMeshCollector); for (var cube : cubes) { for (var polygon : cube.polygons) { var polygonNormal = polygon.normal; for (var vertex : polygon.vertices) { var vertexPosition = vertex.pos; meshBuilder.addVertex( vertexPosition.x / 16.0f, vertexPosition.y / 16.0f, vertexPosition.z / 16.0f, -1, vertex.u, vertex.v, overlay, 0, polygonNormal.x, polygonNormal.y, polygonNormal.z ); } } } culledMeshCollector.flush(); var data = culledMeshCollector .getData (); var buffer = culledMeshCollector .getBuffer (); mesh = merges .get (data); if (mesh != null) { buffer.discard (); buffer.close (); } else { mesh = AcceleratedEntityRenderingFeature .getMeshType() .getBuilder () .build (culledMeshCollector); } meshes .put (extension, mesh); merges .put (data, mesh); mesh .write ( extension, color, light, overlay ); extension.endTransform(); } @Unique @Override public void setCurrentVariant(int variant) { emfVariant = variant; } @Unique @SuppressWarnings("unchecked") private static void renderFast( ModelPart modelPart, PoseStack poseStack, IAcceleratedVertexConsumer extension, int packedLight, int packedOverlay, int packedColor ) { if (!modelPart.visible) { return; } if ( modelPart.cubes .isEmpty() && modelPart.children .isEmpty() ) { return; } poseStack.pushPose(); modelPart.translateAndRotate(poseStack); if (!modelPart.skipDraw) { extension.doRender( (IAcceleratedRenderer) (Object) modelPart, null, poseStack.last().pose(), poseStack.last().normal(), packedLight, packedOverlay, packedColor ); } for(var child : modelPart.children.values()) { renderFast( child, poseStack, extension, packedLight, packedOverlay, packedColor ); } poseStack.popPose(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/emf/mixins/EMFModelPartWithStateMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.emf.mixins; import com.github.argon4w.acceleratedrendering.features.emf.IEMFModelVariant; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import traben.entity_model_features.models.parts.EMFModelPartWithState; @Mixin(EMFModelPartWithState.class) public class EMFModelPartWithStateMixin { @Shadow public int currentModelVariant; @Inject( method = "resetState", at = @At("RETURN") ) public void resetEmfVariant(CallbackInfo ci) { ((IEMFModelVariant) this).setCurrentVariant(currentModelVariant); } @Inject( method = "setVariantStateTo", at = @At("RETURN") ) public void setEmfVariant(int newVariant, CallbackInfo ci) { ((IEMFModelVariant) this).setCurrentVariant(newVariant); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/entities/AcceleratedEntityRenderingFeature.java ================================================ package com.github.argon4w.acceleratedrendering.features.entities; import com.github.argon4w.acceleratedrendering.configs.FeatureConfig; import com.github.argon4w.acceleratedrendering.configs.FeatureStatus; import com.github.argon4w.acceleratedrendering.configs.PipelineSetting; import com.github.argon4w.acceleratedrendering.core.meshes.MeshType; import java.util.ArrayDeque; import java.util.Deque; public class AcceleratedEntityRenderingFeature { private static final Deque PIPELINE_CONTROLLER_STACK = new ArrayDeque<>(); private static final Deque GUI_ACCELERATION_CONTROLLER_STACK = new ArrayDeque<>(); public static boolean isEnabled() { return FeatureConfig.CONFIG.acceleratedEntityRenderingFeatureStatus.get() == FeatureStatus.ENABLED; } public static boolean shouldUseAcceleratedPipeline() { return getPipelineSetting() == PipelineSetting.ACCELERATED; } public static boolean shouldAccelerateInGui() { return getGuiAccelerationSetting() == FeatureStatus.ENABLED; } public static MeshType getMeshType() { return FeatureConfig.CONFIG.acceleratedEntityRenderingMeshType.get(); } public static void useVanillaPipeline() { PIPELINE_CONTROLLER_STACK.push(PipelineSetting.VANILLA); } public static void dontAccelerateInGui() { GUI_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.DISABLED); } public static void forceUseAcceleratedPipeline() { PIPELINE_CONTROLLER_STACK.push(PipelineSetting.ACCELERATED); } public static void forceAccelerateInGui() { GUI_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.ENABLED); } public static void forceSetPipeline(PipelineSetting pipeline) { PIPELINE_CONTROLLER_STACK.push(pipeline); } public static void forceSetGuiAcceleration(FeatureStatus status) { GUI_ACCELERATION_CONTROLLER_STACK.push(status); } public static void resetPipeline() { PIPELINE_CONTROLLER_STACK.pop(); } public static void resetGuiAcceleration() { GUI_ACCELERATION_CONTROLLER_STACK.pop(); } public static PipelineSetting getPipelineSetting() { return PIPELINE_CONTROLLER_STACK.isEmpty() ? getDefaultPipelineSetting() : PIPELINE_CONTROLLER_STACK.peek(); } public static FeatureStatus getGuiAccelerationSetting() { return GUI_ACCELERATION_CONTROLLER_STACK.isEmpty() ? getDefaultGuiAccelerationSetting() : GUI_ACCELERATION_CONTROLLER_STACK.peek(); } public static PipelineSetting getDefaultPipelineSetting() { return FeatureConfig.CONFIG.acceleratedEntityRenderingDefaultPipeline.get(); } public static FeatureStatus getDefaultGuiAccelerationSetting() { return FeatureConfig.CONFIG.acceleratedEntityRenderingGuiAcceleration.get(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/entities/AcceleratedEntityShadowRenderer.java ================================================ package com.github.argon4w.acceleratedrendering.features.entities; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.LightTexture; import net.minecraft.core.BlockPos; import net.minecraft.util.FastColor; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.RenderShape; import net.minecraft.world.level.chunk.ChunkAccess; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.joml.Vector2f; import org.joml.Vector3f; @ExtensionMethod(VertexConsumerExtension.class) public class AcceleratedEntityShadowRenderer implements IAcceleratedRenderer { @Override public void render( VertexConsumer vertexConsumer, Context context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { var extension = vertexConsumer .getAccelerated (); var levelReader = context .levelReader (); var chunkAccess = context .chunkAccess (); var blockPos = context .blockPos (); var center = context .center (); var size = context .size (); var weight = context .weight (); var belowPos = context.blockPos().below (); var blockState = chunkAccess .getBlockState (belowPos); if (blockState.getRenderShape() == RenderShape.INVISIBLE) { return; } var levelBrightness = levelReader.getMaxLocalRawBrightness(blockPos); if (levelBrightness <= 3) { return; } if (!blockState.isCollisionShapeFullBlock(chunkAccess, belowPos)) { return; } var voxelShape = blockState.getShape(chunkAccess, belowPos); if (voxelShape.isEmpty()) { return; } var dimensionBrightness = LightTexture.getBrightness(levelReader.dimensionType(), levelBrightness); var shadowTransparency = weight * 0.5f * dimensionBrightness * 255.0f; if (shadowTransparency < 0.0f) { return; } if (shadowTransparency > 255.0f) { shadowTransparency = 255.0f; } var shadowColor = FastColor.ARGB32 .color ((int) shadowTransparency, color); var bounds = voxelShape .bounds (); var minX = blockPos.getX() + (float) bounds.minX; var maxX = blockPos.getX() + (float) bounds.maxX; var minY = blockPos.getY() + (float) bounds.minY; var minZ = blockPos.getZ() + (float) bounds.minZ; var maxZ = blockPos.getZ() + (float) bounds.maxZ; var minPosX = minX - center.x; var maxPosX = maxX - center.x; var minPosY = minY - center.y; var minPosZ = minZ - center.z; var maxPosZ = maxZ - center.z; var u0 = -minPosX / 2.0f / size + 0.5f; var u1 = -maxPosX / 2.0f / size + 0.5f; var v0 = -minPosZ / 2.0f / size + 0.5f; var v1 = -maxPosZ / 2.0f / size + 0.5f; extension.beginTransform(transform, normal); var positions = new Vector3f[] { new Vector3f(minPosX, minPosY, minPosZ), new Vector3f(minPosX, minPosY, maxPosZ), new Vector3f(maxPosX, minPosY, maxPosZ), new Vector3f(maxPosX, minPosY, minPosZ), }; var texCoords = new Vector2f[] { new Vector2f(u0, v0), new Vector2f(u0, v1), new Vector2f(u1, v1), new Vector2f(u1, v0), }; for (var i = 0; i < 4; i ++) { var position = positions[i]; var texCoord = texCoords[i]; vertexConsumer.addVertex( position.x, position.y, position.z, shadowColor, texCoord.x, texCoord.y, overlay, light, 0.0f, 1.0f, 0.0f ); } extension.endTransform(); } public record Context( LevelReader levelReader, ChunkAccess chunkAccess, BlockPos blockPos, Vector3f center, float size, float weight ) { } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/entities/mixins/EntityRenderDispatcherMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.entities.mixins; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityShadowRenderer; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.core.BlockPos; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.chunk.ChunkAccess; import org.joml.Matrix3f; import org.joml.Vector3f; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @ExtensionMethod(VertexConsumerExtension.class) @Mixin ( value = EntityRenderDispatcher.class, priority = 999 ) public class EntityRenderDispatcherMixin { @Unique private static final Matrix3f SHADOW_NORMAL_MATRIX = new Matrix3f().identity (); @Unique private static final AcceleratedEntityShadowRenderer SHADOW_RENDERER = new AcceleratedEntityShadowRenderer (); @Inject( method = "renderBlockShadow", at = @At("HEAD"), cancellable = true ) private static void fastBlockShadow( PoseStack.Pose pPose, VertexConsumer pVertexConsumer, ChunkAccess pChunk, LevelReader pLevel, BlockPos pPos, double pX, double pY, double pZ, float pSize, float pWeight, CallbackInfo ci ) { var extension = pVertexConsumer.getAccelerated(); if ( CoreFeature .isRenderingLevel () && AcceleratedEntityRenderingFeature .isEnabled () && AcceleratedEntityRenderingFeature .shouldUseAcceleratedPipeline () && extension .isAccelerated () ) { ci .cancel (); extension .doRender ( SHADOW_RENDERER, new AcceleratedEntityShadowRenderer.Context( pLevel, pChunk, pPos, new Vector3f( (float) pX, (float) pY, (float) pZ ), pSize, pWeight ), pPose.pose(), SHADOW_NORMAL_MATRIX, LightTexture .FULL_BRIGHT, OverlayTexture .NO_OVERLAY, -1 ); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/entities/mixins/InventoryScreenMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.entities.mixins; import com.github.argon4w.acceleratedrendering.core.CoreBuffers; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.CoreStates; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.BufferSourceExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.mojang.blaze3d.platform.Lighting; import lombok.experimental.ExtensionMethod; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.inventory.InventoryScreen; import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.world.entity.LivingEntity; import org.spongepowered.asm.mixin.Mixin; @ExtensionMethod(BufferSourceExtension .class) @Mixin (InventoryScreen .class) public class InventoryScreenMixin { @WrapMethod(method = "lambda$renderEntityInInventory$1") private static void renderEntityInInventoryFast( EntityRenderDispatcher entityRenderDispatcher, LivingEntity entity, GuiGraphics guiGraphics, Operation operation ) { if ( !guiGraphics.bufferSource().getAcceleratable() .isBufferSourceAcceleratable () || !AcceleratedEntityRenderingFeature .isEnabled () || !AcceleratedEntityRenderingFeature .shouldUseAcceleratedPipeline () || !AcceleratedEntityRenderingFeature .shouldAccelerateInGui () || !CoreFeature .isLoaded () ) { operation.call( entityRenderDispatcher, entity, guiGraphics ); return; } if (CoreFeature.isGuiBatching()) { CoreFeature.forceSetDefaultLayer (2); CoreFeature.forceSetDefaultLayerBeforeFunction (Lighting::setupForEntityInInventory); CoreFeature.forceSetDefaultLayerAfterFunction (Lighting::setupFor3DItems); } CoreFeature.setRenderingGui(); operation.call( entityRenderDispatcher, entity, guiGraphics ); CoreFeature.resetRenderingGui(); if (CoreFeature.isGuiBatching()) { CoreFeature.resetDefaultLayer (); CoreFeature.resetDefaultLayerBeforeFunction (); CoreFeature.resetDefaultLayerAfterFunction (); } else { CoreStates .recordBuffers (); CoreBuffers.ENTITY .prepareBuffers (); CoreBuffers.BLOCK .prepareBuffers (); CoreBuffers.POS .prepareBuffers (); CoreBuffers.POS_COLOR .prepareBuffers (); CoreBuffers.POS_TEX .prepareBuffers (); CoreBuffers.POS_TEX_COLOR .prepareBuffers (); CoreBuffers.POS_COLOR_TEX_LIGHT .prepareBuffers (); CoreStates .restoreBuffers (); CoreBuffers.ENTITY .drawBuffers (LayerDrawType.ALL); CoreBuffers.BLOCK .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_COLOR .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_TEX .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_TEX_COLOR .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_COLOR_TEX_LIGHT .drawBuffers (LayerDrawType.ALL); CoreBuffers.ENTITY .clearBuffers (); CoreBuffers.BLOCK .clearBuffers (); CoreBuffers.POS .clearBuffers (); CoreBuffers.POS_COLOR .clearBuffers (); CoreBuffers.POS_TEX .clearBuffers (); CoreBuffers.POS_TEX_COLOR .clearBuffers (); CoreBuffers.POS_COLOR_TEX_LIGHT .clearBuffers (); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/filter/FilterFeature.java ================================================ package com.github.argon4w.acceleratedrendering.features.filter; import com.github.argon4w.acceleratedrendering.configs.FeatureConfig; import com.github.argon4w.acceleratedrendering.configs.FeatureStatus; import com.github.argon4w.acceleratedrendering.core.utils.RegistryFilter; import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.neoforged.neoforge.client.event.RenderLevelStageEvent; import java.util.ArrayDeque; import java.util.Deque; import java.util.Set; public class FilterFeature { private static final Deque MENU_FILTER_CONTROLLER_STACK = new ArrayDeque<>(); private static final Deque ENTITIES_FILTER_CONTROLLER_STACK = new ArrayDeque<>(); private static final Deque BLOCK_ENTITIES_FILTER_CONTROLLER_STACK = new ArrayDeque<>(); private static final Deque ITEM_FILTER_CONTROLLER_STACK = new ArrayDeque<>(); private static final Deque STAGE_FILTER_CONTROLLER_STACK = new ArrayDeque<>(); private static final Set > MENU_FILTER_VALUES; private static final Set > ENTITY_FILTER_VALUES; private static final Set > BLOCK_ENTITY_FILTER_VALUES; private static final Set ITEM_FILTER_VALUES; private static final Set STAGE_FILTER_VALUES; static { MENU_FILTER_VALUES = RegistryFilter.filterValues (BuiltInRegistries.MENU, FeatureConfig.CONFIG.filterMenuFilterValues .get()); ENTITY_FILTER_VALUES = RegistryFilter.filterValues (BuiltInRegistries.ENTITY_TYPE, FeatureConfig.CONFIG.filterEntityFilterValues .get()); BLOCK_ENTITY_FILTER_VALUES = RegistryFilter.filterValues (BuiltInRegistries.BLOCK_ENTITY_TYPE, FeatureConfig.CONFIG.filterBlockEntityFilterValues .get()); ITEM_FILTER_VALUES = RegistryFilter.filterValues (BuiltInRegistries.ITEM, FeatureConfig.CONFIG.filterItemFilterValues .get()); STAGE_FILTER_VALUES = new ReferenceOpenHashSet<> ( FeatureConfig.CONFIG.filterStageFilterValues .get()); } public static boolean isEnabled() { return FeatureConfig.CONFIG.filterFeatureStatus.get() == FeatureStatus.ENABLED; } public static boolean testMenu(AbstractContainerMenu menu) { return menu.menuType == null || getMenuFilterType().test(MENU_FILTER_VALUES, menu.menuType); } public static boolean testEntity(Entity entity) { return getEntityFilterType().test(ENTITY_FILTER_VALUES, entity.getType()); } public static boolean testBlockEntity(BlockEntity entity) { return getBlockEntityFilterType().test(BLOCK_ENTITY_FILTER_VALUES, entity.getType()); } public static boolean testItem(ItemStack itemStack) { return getItemFilterType().test(ITEM_FILTER_VALUES, itemStack.getItem()); } public static boolean testStage(RenderLevelStageEvent.Stage stage) { return getStageFilterType().test(STAGE_FILTER_VALUES, stage.toString()); } public static boolean shouldFilterMenus() { return getMenuFilterSetting() == FeatureStatus.ENABLED; } public static boolean shouldFilterEntities() { return getEntityFilterSetting() == FeatureStatus.ENABLED; } public static boolean shouldFilterBlockEntities() { return getBlockEntityFilterSetting() == FeatureStatus.ENABLED; } public static boolean shouldFilterItems() { return getItemFilterSetting() == FeatureStatus.ENABLED; } public static boolean shouldFilterStage() { return getStageFilterSetting() == FeatureStatus.ENABLED; } public static FilterType getMenuFilterType() { return FeatureConfig.CONFIG.filterMenuFilterType.get(); } public static FilterType getEntityFilterType() { return FeatureConfig.CONFIG.filterEntityFilterType.get(); } public static FilterType getBlockEntityFilterType() { return FeatureConfig.CONFIG.filterBlockEntityFilterType.get(); } public static FilterType getItemFilterType() { return FeatureConfig.CONFIG.filterItemFilterType.get(); } public static FilterType getStageFilterType() { return FeatureConfig.CONFIG.filterStageFilterType.get(); } public static void disableMenuFilter() { MENU_FILTER_CONTROLLER_STACK.push(FeatureStatus.DISABLED); } public static void disableEntityFilter() { ENTITIES_FILTER_CONTROLLER_STACK.push(FeatureStatus.DISABLED); } public static void disableBlockEntityFilter() { BLOCK_ENTITIES_FILTER_CONTROLLER_STACK.push(FeatureStatus.DISABLED); } public static void disableItemFilter() { ITEM_FILTER_CONTROLLER_STACK.push(FeatureStatus.DISABLED); } public static void disableStageFilter() { STAGE_FILTER_CONTROLLER_STACK.push(FeatureStatus.DISABLED); } public static void forceEnableMenuFilter() { MENU_FILTER_CONTROLLER_STACK.push(FeatureStatus.ENABLED); } public static void forceEnableEntityFilter() { ENTITIES_FILTER_CONTROLLER_STACK.push(FeatureStatus.ENABLED); } public static void forceEnableBlockEntityFilter() { BLOCK_ENTITIES_FILTER_CONTROLLER_STACK.push(FeatureStatus.ENABLED); } public static void forceEnableItemFilter() { ITEM_FILTER_CONTROLLER_STACK.push(FeatureStatus.ENABLED); } public static void forceEnableStageFilter() { STAGE_FILTER_CONTROLLER_STACK.push(FeatureStatus.ENABLED); } public static void forceSetMenuFilter(FeatureStatus status) { MENU_FILTER_CONTROLLER_STACK.push(status); } public static void forceSetEntityFilter(FeatureStatus status) { ENTITIES_FILTER_CONTROLLER_STACK.push(status); } public static void forceSetBlockEntityFilter(FeatureStatus status) { BLOCK_ENTITIES_FILTER_CONTROLLER_STACK.push(status); } public static void forceSetItemFilter(FeatureStatus status) { ITEM_FILTER_CONTROLLER_STACK.push(status); } public static void forceSetStageFilter(FeatureStatus status) { STAGE_FILTER_CONTROLLER_STACK.push(status); } public static void resetMenuFilter() { MENU_FILTER_CONTROLLER_STACK.pop(); } public static void resetEntityFilter() { ENTITIES_FILTER_CONTROLLER_STACK.pop(); } public static void resetBlockEntityFilter() { BLOCK_ENTITIES_FILTER_CONTROLLER_STACK.pop(); } public static void resetItemFilter() { ITEM_FILTER_CONTROLLER_STACK.pop(); } public static void resetStageFilter() { STAGE_FILTER_CONTROLLER_STACK.pop(); } public static FeatureStatus getMenuFilterSetting() { return MENU_FILTER_CONTROLLER_STACK.isEmpty() ? getDefaultMenuFilterSetting() : MENU_FILTER_CONTROLLER_STACK.peek(); } public static FeatureStatus getEntityFilterSetting() { return ENTITIES_FILTER_CONTROLLER_STACK.isEmpty() ? getDefaultEntityFilterSetting() : ENTITIES_FILTER_CONTROLLER_STACK.peek(); } public static FeatureStatus getBlockEntityFilterSetting() { return BLOCK_ENTITIES_FILTER_CONTROLLER_STACK.isEmpty() ? getDefaultBlockEntityFilterSetting() : BLOCK_ENTITIES_FILTER_CONTROLLER_STACK.peek(); } public static FeatureStatus getItemFilterSetting() { return ITEM_FILTER_CONTROLLER_STACK.isEmpty() ? getDefaultItemFilterSetting() : ITEM_FILTER_CONTROLLER_STACK.peek(); } public static FeatureStatus getStageFilterSetting() { return STAGE_FILTER_CONTROLLER_STACK.isEmpty() ? getDefaultStageFilterSetting() : STAGE_FILTER_CONTROLLER_STACK.peek(); } public static FeatureStatus getDefaultMenuFilterSetting() { return FeatureConfig.CONFIG.filterMenuFilter.get(); } public static FeatureStatus getDefaultEntityFilterSetting() { return FeatureConfig.CONFIG.filterEntityFilter.get(); } public static FeatureStatus getDefaultBlockEntityFilterSetting() { return FeatureConfig.CONFIG.filterBlockEntityFilter.get(); } public static FeatureStatus getDefaultItemFilterSetting() { return FeatureConfig.CONFIG.filterItemFilter.get(); } public static FeatureStatus getDefaultStageFilterSetting() { return FeatureConfig.CONFIG.filterStageFilter.get(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/filter/FilterType.java ================================================ package com.github.argon4w.acceleratedrendering.features.filter; import java.util.Set; public enum FilterType { BLACKLIST, WHITELIST; public boolean test(Set values, T value) { return switch (this) { case WHITELIST -> values.contains(value); case BLACKLIST -> ! values.contains(value); }; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/filter/mixins/AbstractContainerScreenMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.filter.mixins; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.github.argon4w.acceleratedrendering.features.filter.FilterFeature; import com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature; import com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature; import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.world.inventory.AbstractContainerMenu; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @Mixin(value = AbstractContainerScreen.class) public class AbstractContainerScreenMixin { @Shadow @Final protected AbstractContainerMenu menu; @WrapMethod(method = "render") public void startBatching( GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick, Operation original ) { var pass = ! FilterFeature.isEnabled () || ! FilterFeature.shouldFilterMenus () || FilterFeature.testMenu (menu); if (!pass) { AcceleratedEntityRenderingFeature .useVanillaPipeline(); AcceleratedItemRenderingFeature .useVanillaPipeline(); AcceleratedTextRenderingFeature .useVanillaPipeline(); } original.call( guiGraphics, mouseX, mouseY, partialTick ); if (!pass) { AcceleratedEntityRenderingFeature .resetPipeline(); AcceleratedItemRenderingFeature .resetPipeline(); AcceleratedTextRenderingFeature .resetPipeline(); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/filter/mixins/BlockEntityRenderDispatcherMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.filter.mixins; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.github.argon4w.acceleratedrendering.features.filter.FilterFeature; import com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature; import com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; import net.minecraft.world.level.block.entity.BlockEntity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @Mixin(BlockEntityRenderDispatcher.class) public class BlockEntityRenderDispatcherMixin { @WrapOperation( method = "tryRender", at = @At( value = "INVOKE", target = "Ljava/lang/Runnable;run()V" ) ) private static void filterBlockEntity( Runnable instance, Operation original, BlockEntity blockEntity ) { var pass = ! FilterFeature.isEnabled () || ! FilterFeature.shouldFilterBlockEntities () || FilterFeature.testBlockEntity (blockEntity); if (!pass) { AcceleratedEntityRenderingFeature .useVanillaPipeline(); AcceleratedItemRenderingFeature .useVanillaPipeline(); AcceleratedTextRenderingFeature .useVanillaPipeline(); } original.call(instance); if (!pass) { AcceleratedEntityRenderingFeature .resetPipeline(); AcceleratedItemRenderingFeature .resetPipeline(); AcceleratedTextRenderingFeature .resetPipeline(); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/filter/mixins/ClientHooksMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.filter.mixins; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.github.argon4w.acceleratedrendering.features.filter.FilterFeature; import com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature; import com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.neoforged.bus.api.Event; import net.neoforged.bus.api.IEventBus; import net.neoforged.neoforge.client.ClientHooks; import net.neoforged.neoforge.client.event.RenderLevelStageEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @Mixin(ClientHooks.class) public class ClientHooksMixin { @WrapOperation( method = "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", at = @At( value = "INVOKE", target = "Lnet/neoforged/bus/api/IEventBus;post(Lnet/neoforged/bus/api/Event;)Lnet/neoforged/bus/api/Event;" ) ) private static Event startRenderLevelStage( IEventBus instance, Event event, Operation original, RenderLevelStageEvent.Stage stage ) { var pass = ! FilterFeature.isEnabled () || ! FilterFeature.shouldFilterStage () || FilterFeature.testStage (stage); if (!pass) { AcceleratedEntityRenderingFeature .useVanillaPipeline(); AcceleratedItemRenderingFeature .useVanillaPipeline(); AcceleratedTextRenderingFeature .useVanillaPipeline(); } var result = original.call(instance, event); if (!pass) { AcceleratedEntityRenderingFeature .resetPipeline(); AcceleratedItemRenderingFeature .resetPipeline(); AcceleratedTextRenderingFeature .resetPipeline(); } return result; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/filter/mixins/ItemRendererMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.filter.mixins; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.github.argon4w.acceleratedrendering.features.filter.FilterFeature; import com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature; import com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.world.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @Mixin( value = ItemRenderer.class, priority = 1001 ) public class ItemRendererMixin { @WrapOperation( method = "render", at = @At( value = "INVOKE", target = "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" ) ) public void filterItem( ItemRenderer instance, BakedModel bakedModel, ItemStack model, int stack, int combinedLight, PoseStack combinedOverlay, VertexConsumer poseStack, Operation original ) { var pass = ! FilterFeature.isEnabled () || ! FilterFeature.shouldFilterItems () || FilterFeature.testItem (model); if (!pass) { AcceleratedEntityRenderingFeature .useVanillaPipeline(); AcceleratedItemRenderingFeature .useVanillaPipeline(); AcceleratedTextRenderingFeature .useVanillaPipeline(); } original.call( instance, bakedModel, model, stack, combinedLight, combinedOverlay, poseStack ); if (!pass) { AcceleratedEntityRenderingFeature .resetPipeline(); AcceleratedItemRenderingFeature .resetPipeline(); AcceleratedTextRenderingFeature .resetPipeline(); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/filter/mixins/LevelRendererMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.filter.mixins; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.github.argon4w.acceleratedrendering.features.filter.FilterFeature; import com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature; import com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.world.entity.Entity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @Mixin(LevelRenderer.class) public class LevelRendererMixin { @WrapOperation( method = "renderLevel", at = @At( value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;renderEntity(Lnet/minecraft/world/entity/Entity;DDDFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;)V" ) ) public void filterEntity( LevelRenderer instance, Entity entity, double camX, double camY, double camZ, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, Operation original ) { var pass = ! FilterFeature.isEnabled () || ! FilterFeature.shouldFilterEntities () || FilterFeature.testEntity (entity); if (!pass) { AcceleratedEntityRenderingFeature .useVanillaPipeline(); AcceleratedItemRenderingFeature .useVanillaPipeline(); AcceleratedTextRenderingFeature .useVanillaPipeline(); } original.call( instance, entity, camX, camY, camZ, partialTick, poseStack, bufferSource ); if (!pass) { AcceleratedEntityRenderingFeature .resetPipeline(); AcceleratedItemRenderingFeature .resetPipeline(); AcceleratedTextRenderingFeature .resetPipeline(); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/ftb/mixins/BaseScreenMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.ftb.mixins; import com.github.argon4w.acceleratedrendering.features.items.gui.GuiBatchingController; import dev.ftb.mods.ftblibrary.ui.BaseScreen; import dev.ftb.mods.ftblibrary.ui.Theme; import net.minecraft.client.gui.GuiGraphics; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Pseudo @Mixin(BaseScreen.class) public class BaseScreenMixin { @Inject( method = "draw", at = { @At( value = "INVOKE", target = "Ldev/ftb/mods/ftblibrary/ui/Panel;draw(Lnet/minecraft/client/gui/GuiGraphics;Ldev/ftb/mods/ftblibrary/ui/Theme;IIII)V", shift = At.Shift.BEFORE ), @At( value = "INVOKE", target = "Ldev/ftb/mods/ftblibrary/ui/ModalPanel;draw(Lnet/minecraft/client/gui/GuiGraphics;Ldev/ftb/mods/ftblibrary/ui/Theme;IIII)V", shift = At.Shift.BEFORE ) } ) public void startBatching( GuiGraphics graphics, Theme theme, int x, int y, int w, int h, CallbackInfo ci ) { GuiBatchingController.INSTANCE.startBatching(graphics); } @Inject( method = "draw", at = { @At( value = "INVOKE", target = "Ldev/ftb/mods/ftblibrary/ui/Panel;draw(Lnet/minecraft/client/gui/GuiGraphics;Ldev/ftb/mods/ftblibrary/ui/Theme;IIII)V", shift = At.Shift.AFTER ), @At( value = "INVOKE", target = "Ldev/ftb/mods/ftblibrary/ui/ModalPanel;draw(Lnet/minecraft/client/gui/GuiGraphics;Ldev/ftb/mods/ftblibrary/ui/Theme;IIII)V", shift = At.Shift.AFTER ) } ) public void stopBatching( GuiGraphics graphics, Theme theme, int x, int y, int w, int h, CallbackInfo ci ) { GuiBatchingController.INSTANCE.flushBatching(graphics); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/geckolib/mixins/GeoBoneMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.geckolib.mixins; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IBufferGraph; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.github.argon4w.acceleratedrendering.core.meshes.IMesh; import com.github.argon4w.acceleratedrendering.core.meshes.collectors.CulledMeshCollector; import com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.experimental.ExtensionMethod; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.joml.Vector3f; import org.joml.Vector4f; import org.spongepowered.asm.mixin.*; import software.bernie.geckolib.cache.object.GeoBone; import software.bernie.geckolib.cache.object.GeoCube; import software.bernie.geckolib.util.RenderUtil; import java.util.List; import java.util.Map; @Pseudo @ExtensionMethod(VertexConsumerExtension.class) @Mixin (GeoBone .class) public class GeoBoneMixin implements IAcceleratedRenderer { @Shadow @Final private List cubes; @Unique private final Map meshes = new Object2ObjectOpenHashMap<>(); @Unique private final Map merges = new Object2ObjectOpenHashMap<>(); @Override public void render( VertexConsumer vertexConsumer, Void context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { var extension = vertexConsumer.getAccelerated (); var mesh = meshes .get (extension); extension.beginTransform(transform, normal); if (mesh != null) { mesh.write( extension, color, light, overlay ); extension.endTransform(); return; } var culledMeshCollector = new CulledMeshCollector (extension); var meshBuilder = extension.decorate (culledMeshCollector); for (GeoCube cube : cubes) { var poseStack = new PoseStack(); RenderUtil.translateToPivotPoint (poseStack, cube); RenderUtil.rotateMatrixAroundCube (poseStack, cube); RenderUtil.translateAwayFromPivotPoint (poseStack, cube); var pose = poseStack .last (); var cubeTransform = pose .pose (); var cubeNormal = pose .normal (); for (var quad : cube.quads()) { if (quad != null) { var polygonNormal = cubeNormal.transform(new Vector3f(quad.normal())); for (var vertex : quad.vertices()) { var vertexPosition = cubeTransform.transform(new Vector4f(vertex.position(), 1.0f)); meshBuilder.addVertex( vertexPosition.x, vertexPosition.y, vertexPosition.z, -1, vertex.texU(), vertex.texV(), overlay, 0, polygonNormal.x, polygonNormal.y, polygonNormal.z ); } } } } culledMeshCollector.flush(); var data = culledMeshCollector .getData (); var buffer = culledMeshCollector .getBuffer (); mesh = merges .get (data); if (mesh != null) { buffer.discard (); buffer.close (); } else { mesh = AcceleratedEntityRenderingFeature .getMeshType() .getBuilder () .build (culledMeshCollector); } meshes .put (extension, mesh); merges .put (data, mesh); mesh .write ( extension, color, light, overlay ); extension.endTransform(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/geckolib/mixins/GeoRendererMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.geckolib.mixins; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.experimental.ExtensionMethod; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import software.bernie.geckolib.cache.object.GeoBone; import software.bernie.geckolib.renderer.GeoRenderer; @Pseudo @ExtensionMethod(VertexConsumerExtension.class) @Mixin (GeoRenderer .class) public interface GeoRendererMixin { @SuppressWarnings ("unchecked") @Inject ( method = "renderCubesOfBone", cancellable = true, at = @At( value = "INVOKE", target = "Lsoftware/bernie/geckolib/cache/object/GeoBone;getCubes()Ljava/util/List;", shift = At.Shift.BEFORE ) ) default void renderCubesOfBoneFast( PoseStack poseStack, GeoBone bone, VertexConsumer buffer, int packedLight, int packedOverlay, int colour, CallbackInfo ci ) { var extension = buffer.getAccelerated(); if ( AcceleratedEntityRenderingFeature .isEnabled () && AcceleratedEntityRenderingFeature .shouldUseAcceleratedPipeline () && ( CoreFeature .isRenderingLevel () || ( CoreFeature .isRenderingGui () && AcceleratedEntityRenderingFeature .shouldAccelerateInGui ())) && extension .isAccelerated () ) { var pose = poseStack.last(); ci .cancel (); extension .doRender ( (IAcceleratedRenderer) bone, null, pose.pose (), pose.normal (), packedLight, packedOverlay, colour ); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/AcceleratedItemRenderingFeature.java ================================================ package com.github.argon4w.acceleratedrendering.features.items; import com.github.argon4w.acceleratedrendering.configs.FeatureConfig; import com.github.argon4w.acceleratedrendering.configs.FeatureStatus; import com.github.argon4w.acceleratedrendering.configs.PipelineSetting; import com.github.argon4w.acceleratedrendering.core.meshes.MeshType; import java.util.ArrayDeque; import java.util.Deque; public class AcceleratedItemRenderingFeature { private static final Deque PIPELINE_CONTROLLER_STACK = new ArrayDeque<>(); private static final Deque BAKE_QUAD_MESH_CONTROLLER_STACK = new ArrayDeque<>(); private static final Deque HAND_ACCELERATION_CONTROLLER_STACK = new ArrayDeque<>(); private static final Deque GUI_ACCELERATION_CONTROLLER_STACK = new ArrayDeque<>(); public static boolean isEnabled() { return FeatureConfig.CONFIG.acceleratedItemRenderingFeatureStatus.get() == FeatureStatus.ENABLED; } public static boolean shouldUseAcceleratedPipeline() { return getPipelineSetting() == PipelineSetting.ACCELERATED; } public static boolean shouldBakeMeshForQuad() { return getBakeQuadMeshSetting() == FeatureStatus.ENABLED; } public static boolean shouldAccelerateInHand() { return getHandAccelerationSetting() == FeatureStatus.ENABLED; } public static boolean shouldAccelerateInGui() { return getGUIAccelerationSetting() == FeatureStatus.ENABLED; } public static boolean shouldUseGuiItemBatching() { return FeatureConfig.CONFIG.acceleratedItemRenderingGuiItemBatching.get() == FeatureStatus.ENABLED; } public static boolean shouldMergeGuiItemBatches() { return FeatureConfig.CONFIG.acceleratedItemRenderingMergeGuiItemBatches.get() == FeatureStatus.ENABLED; } public static MeshType getMeshType() { return FeatureConfig.CONFIG.acceleratedItemRenderingMeshType.get(); } public static void useVanillaPipeline() { PIPELINE_CONTROLLER_STACK.push(PipelineSetting.VANILLA); } public static void dontBakeMeshForQuad() { BAKE_QUAD_MESH_CONTROLLER_STACK.push(FeatureStatus.DISABLED); } public static void dontAccelerateInHand() { HAND_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.DISABLED); } public static void dontAccelerateInGui() { GUI_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.DISABLED); } public static void forceUseAcceleratedPipeline() { PIPELINE_CONTROLLER_STACK.push(PipelineSetting.ACCELERATED); } public static void forceBakeMeshForQuad() { BAKE_QUAD_MESH_CONTROLLER_STACK.push(FeatureStatus.ENABLED); } public static void forceAccelerateInHand() { HAND_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.ENABLED); } public static void forceAccelerateInGui() { GUI_ACCELERATION_CONTROLLER_STACK.push(FeatureStatus.ENABLED); } public static void forceSetPipeline(PipelineSetting pipeline) { PIPELINE_CONTROLLER_STACK.push(pipeline); } public static void forceSetBakeQuadForMesh(FeatureStatus status) { BAKE_QUAD_MESH_CONTROLLER_STACK.push(status); } public static void forceSetHandAcceleration(FeatureStatus status) { HAND_ACCELERATION_CONTROLLER_STACK.push(status); } public static void forceSetGUIAcceleration(FeatureStatus status) { GUI_ACCELERATION_CONTROLLER_STACK.push(status); } public static void resetPipeline() { PIPELINE_CONTROLLER_STACK.pop(); } public static void resetBakeQuadForMesh() { BAKE_QUAD_MESH_CONTROLLER_STACK.pop(); } public static void resetHandAcceleration() { HAND_ACCELERATION_CONTROLLER_STACK.pop(); } public static void resetGuiAcceleration() { GUI_ACCELERATION_CONTROLLER_STACK.pop(); } public static PipelineSetting getPipelineSetting() { return PIPELINE_CONTROLLER_STACK.isEmpty() ? getDefaultPipelineSetting() : PIPELINE_CONTROLLER_STACK.peek(); } public static FeatureStatus getBakeQuadMeshSetting() { return BAKE_QUAD_MESH_CONTROLLER_STACK.isEmpty() ? getDefaultBakeQuadMeshSetting() : BAKE_QUAD_MESH_CONTROLLER_STACK.peek(); } public static FeatureStatus getHandAccelerationSetting() { return HAND_ACCELERATION_CONTROLLER_STACK.isEmpty() ? getDefaultHandAccelerationSetting() : HAND_ACCELERATION_CONTROLLER_STACK.peek(); } public static FeatureStatus getGUIAccelerationSetting() { return GUI_ACCELERATION_CONTROLLER_STACK.isEmpty() ? getDefaultGUIAccelerationSetting() : GUI_ACCELERATION_CONTROLLER_STACK.peek(); } public static PipelineSetting getDefaultPipelineSetting() { return FeatureConfig.CONFIG.acceleratedItemRenderingDefaultPipeline.get(); } public static FeatureStatus getDefaultBakeQuadMeshSetting() { return FeatureConfig.CONFIG.acceleratedItemRenderingBakeMeshForQuads.get(); } public static FeatureStatus getDefaultHandAccelerationSetting() { return FeatureConfig.CONFIG.acceleratedItemRenderingHandAcceleration.get(); } public static FeatureStatus getDefaultGUIAccelerationSetting() { return FeatureConfig.CONFIG.acceleratedItemRenderingGuiAcceleration.get(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/AcceleratedQuadsRenderer.java ================================================ package com.github.argon4w.acceleratedrendering.features.items; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.github.argon4w.acceleratedrendering.features.items.contexts.AcceleratedQuadsRenderContext; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.experimental.ExtensionMethod; import org.joml.Matrix3f; import org.joml.Matrix4f; @ExtensionMethod({ VertexConsumerExtension .class, BakedModelExtension .class }) public class AcceleratedQuadsRenderer implements IAcceleratedRenderer { public static final AcceleratedQuadsRenderer INSTANCE = new AcceleratedQuadsRenderer(); @Override public void render( VertexConsumer vertexConsumer, AcceleratedQuadsRenderContext context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { var extension = vertexConsumer.getAccelerated (); var quads = context .quads (); var colors = context .colors (); extension.beginTransform(transform, normal); for (var quad : quads) { quad .getAccelerated () .renderFast ( transform, normal, extension, light, overlay, colors.getColor(quad.getTintIndex()) ); } extension.endTransform(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/BakedModelExtension.java ================================================ package com.github.argon4w.acceleratedrendering.features.items; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.resources.model.BakedModel; public class BakedModelExtension { public static IAcceleratedBakedModel getAccelerated(BakedModel in) { return (IAcceleratedBakedModel) in; } public static IAcceleratedBakedQuad getAccelerated(BakedQuad in) { return (IAcceleratedBakedQuad) in; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/IAcceleratedBakedModel.java ================================================ package com.github.argon4w.acceleratedrendering.features.items; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.renderer.RenderType; import net.minecraft.util.RandomSource; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.data.ModelData; public interface IAcceleratedBakedModel { void renderItemFast (ItemStack itemStack, RandomSource random, PoseStack.Pose pose, IAcceleratedVertexConsumer extension, int light, int overlay); void renderBlockFast (BlockState blockState, RandomSource random, PoseStack.Pose pose, IAcceleratedVertexConsumer extension, int light, int overlay, int color, ModelData data, RenderType renderType); int getCustomColor (int layer, int color); boolean isAccelerated (); boolean isAcceleratedInHand (); boolean isAcceleratedInGui (); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/IAcceleratedBakedQuad.java ================================================ package com.github.argon4w.acceleratedrendering.features.items; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import org.joml.Matrix3f; import org.joml.Matrix4f; public interface IAcceleratedBakedQuad { void renderFast (Matrix4f transform, Matrix3f normal, IAcceleratedVertexConsumer extension, int combinedLight, int combinedOverlay, int color); int getCustomColor (int color); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/colors/BlockLayerColors.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.colors; import com.github.argon4w.acceleratedrendering.features.items.mixins.accessors.BlockColorsAccessor; import net.minecraft.client.Minecraft; import net.minecraft.client.color.block.BlockColor; import net.minecraft.world.level.block.state.BlockState; public class BlockLayerColors implements ILayerColors { private final BlockState blockState; private final BlockColor blockColor; public BlockLayerColors(BlockState blockState) { this.blockState = blockState; this.blockColor = ((BlockColorsAccessor) Minecraft.getInstance().getBlockColors()).getBlockColors().getOrDefault(this.blockState.getBlock(), EmptyBlockColor.INSTANCE); } @Override public int getColor(int layer) { return layer == -1 ? -1 : blockColor.getColor( blockState, null, null, layer ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/colors/EmptyBlockColor.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.colors; import net.minecraft.client.color.block.BlockColor; import net.minecraft.core.BlockPos; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.block.state.BlockState; public class EmptyBlockColor implements BlockColor { public static final BlockColor INSTANCE = new EmptyBlockColor(); @Override public int getColor( BlockState state, BlockAndTintGetter level, BlockPos pos, int tintIndex ) { return -1; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/colors/EmptyItemColor.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.colors; import net.minecraft.client.color.item.ItemColor; import net.minecraft.world.item.ItemStack; public class EmptyItemColor implements ItemColor { public static final ItemColor INSTANCE = new EmptyItemColor(); @Override public int getColor(ItemStack pStack, int pTintIndex) { return -1; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/colors/FixedColors.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.colors; public record FixedColors(int color) implements ILayerColors { @Override public int getColor(int layer) { return color; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/colors/ILayerColors.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.colors; public interface ILayerColors { int getColor(int layer); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/colors/ItemLayerColors.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.colors; import com.github.argon4w.acceleratedrendering.features.items.mixins.accessors.ItemColorsAccessor; import net.minecraft.client.Minecraft; import net.minecraft.client.color.item.ItemColor; import net.minecraft.world.item.ItemStack; public class ItemLayerColors implements ILayerColors { private final ItemStack itemStack; private final ItemColor itemColor; public ItemLayerColors(ItemStack itemStack) { this.itemStack = itemStack; this.itemColor = ((ItemColorsAccessor) Minecraft.getInstance().getItemColors()).getItemColors().getOrDefault(this.itemStack.getItem(), EmptyItemColor.INSTANCE); } @Override public int getColor(int layer) { return layer == -1 ? -1 : itemColor.getColor(itemStack, layer); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/contexts/AcceleratedModelRenderContext.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.contexts; import com.github.argon4w.acceleratedrendering.features.items.colors.ILayerColors; import net.minecraft.util.RandomSource; public record AcceleratedModelRenderContext(RandomSource randomSource, ILayerColors layerColors) { } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/contexts/AcceleratedQuadsRenderContext.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.contexts; import com.github.argon4w.acceleratedrendering.features.items.colors.ILayerColors; import net.minecraft.client.renderer.block.model.BakedQuad; import java.util.List; public record AcceleratedQuadsRenderContext(List quads, ILayerColors colors) { } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/contexts/DecorationRenderContext.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.contexts; import net.minecraft.world.item.ItemStack; public record DecorationRenderContext( ItemStack itemStack, String countString, int slotX, int slotY ) { } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/GuiBatchingController.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.gui; import com.github.argon4w.acceleratedrendering.core.CoreBuffers; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.CoreStates; import com.github.argon4w.acceleratedrendering.core.backends.states.IBindingState; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.BufferSourceExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.layers.LayerDrawType; import com.github.argon4w.acceleratedrendering.core.utils.PoseStackExtension; import com.github.argon4w.acceleratedrendering.core.utils.RenderTypeUtils; import com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature; import com.github.argon4w.acceleratedrendering.features.items.gui.contexts.*; import com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string.IStringDrawContext; import com.github.argon4w.acceleratedrendering.features.items.gui.renderer.AcceleratedBlitRenderer; import com.github.argon4w.acceleratedrendering.features.items.gui.renderer.AcceleratedFillRenderer; import com.github.argon4w.acceleratedrendering.features.items.gui.renderer.AcceleratedGradientRenderer; import com.mojang.blaze3d.platform.Lighting; import it.unimi.dsi.fastutil.floats.Float2ReferenceAVLTreeMap; import it.unimi.dsi.fastutil.floats.Float2ReferenceSortedMap; import it.unimi.dsi.fastutil.objects.ReferenceArrayList; import lombok.experimental.ExtensionMethod; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.client.ItemDecoratorHandler; import org.joml.Matrix3f; import org.joml.Matrix4f; import java.util.List; @ExtensionMethod({ VertexConsumerExtension .class, BufferSourceExtension .class, PoseStackExtension .class, }) public class GuiBatchingController { public static final GuiBatchingController INSTANCE = new GuiBatchingController(); private final IBindingState scissorDraw; private final IBindingState scissorFlush; private final List blitDrawContexts; private final List stringDrawContexts; private final List decoratorDrawContexts; private final List fillDrawContexts; private final List highlightDrawContexts; private final List gradientDrawContexts; private final List flatItemDrawContexts; private final List blockItemDrawContexts; private final Float2ReferenceSortedMap> depthLayers; private GuiBatchingController() { this.scissorDraw = CoreFeature.createScissorState (); this.scissorFlush = CoreFeature.createScissorState (); this.blitDrawContexts = new ReferenceArrayList <> (); this.stringDrawContexts = new ReferenceArrayList <> (); this.decoratorDrawContexts = new ReferenceArrayList <> (); this.fillDrawContexts = new ReferenceArrayList <> (); this.highlightDrawContexts = new ReferenceArrayList <> (); this.gradientDrawContexts = new ReferenceArrayList <> (); this.flatItemDrawContexts = new ReferenceArrayList <> (); this.blockItemDrawContexts = new ReferenceArrayList <> (); this.depthLayers = new Float2ReferenceAVLTreeMap <> (); } public void startBatching(GuiGraphics graphics) { if ( graphics.bufferSource().getAcceleratable() .isBufferSourceAcceleratable () && AcceleratedItemRenderingFeature .isEnabled () && AcceleratedItemRenderingFeature .shouldUseAcceleratedPipeline () && AcceleratedItemRenderingFeature .shouldAccelerateInGui () && AcceleratedItemRenderingFeature .shouldUseGuiItemBatching () && CoreFeature .isLoaded () ) { CoreFeature.setGuiBatching (); scissorDraw.record (graphics); } } @SuppressWarnings("UnstableApiUsage") public void flushBatching(GuiGraphics graphics) { if (CoreFeature.isGuiBatching()) { var itemRenderer = Minecraft.getInstance() .getItemRenderer(); var bufferSource = graphics .bufferSource (); var poseStack = graphics .pose (); CoreFeature.resetGuiBatching(); CoreFeature.setRenderingGui (); for (float layer : depthLayers.keySet()) { var nextLayer = depthLayers.tailMap (layer); var elements = depthLayers.get (layer); var depth = 0.0f; var step = 0.1f; if (!nextLayer.isEmpty()) { step = 1.0f / nextLayer.firstEntry().getValue().size(); } for (var element : elements) { element.transform().translateLocal( 0.0f, 0.0f, depth ); depth += step; } } for (float layer : depthLayers.keySet()) { var elements = depthLayers.get(layer); if (elements.isEmpty()) { depthLayers.remove(layer); } else { elements.clear(); } } for (var context : blitDrawContexts) { var extension = graphics.bufferSource().getBuffer(GuiRenderTypes.blit(context.atlasLocation())).getAccelerated(); if (extension.isAccelerated()) { extension.doRender( AcceleratedBlitRenderer.INSTANCE, context, context.transform (), context.normal (), context.blitLight (), context.blitOverlay (), context.blitColor () ); } } for (var context : fillDrawContexts) { var extension = graphics.bufferSource().getBuffer(context.renderType()).getAccelerated(); if (extension.isAccelerated()) { extension.doRender( AcceleratedFillRenderer.INSTANCE, context, context.transform (), context.normal (), context.light (), context.overlay (), context.color () ); } } for (var context : gradientDrawContexts) { var extension = graphics.bufferSource().getBuffer(context.renderType()).getAccelerated(); if (extension.isAccelerated()) { extension.doRender( AcceleratedGradientRenderer.INSTANCE, context, context.transform (), context.normal (), context.light (), context.overlay (), -1 ); } } for (var context : stringDrawContexts) { context.drawString(graphics.bufferSource()); } scissorFlush.record (graphics); scissorDraw .restore(); CoreFeature.forceSetDefaultLayer (1); CoreFeature.forceSetDefaultLayerBeforeFunction (Lighting::setupForFlatItems); CoreFeature.forceSetDefaultLayerAfterFunction (Lighting::setupFor3DItems); for (var context : flatItemDrawContexts) { poseStack.pushPose (); poseStack.setPose (context.transform(), context.normal()); itemRenderer.render( context.itemStack (), context.displayContext (), context.leftHand (), poseStack, bufferSource, context.combinedLight (), context.combinedOverlay (), context.bakedModel () ); poseStack.popPose(); } CoreFeature.resetDefaultLayer (); CoreFeature.resetDefaultLayerBeforeFunction (); CoreFeature.resetDefaultLayerAfterFunction (); for (var context : blockItemDrawContexts) { poseStack.pushPose (); poseStack.setPose (context.transform(), context.normal()); itemRenderer.render( context.itemStack (), context.displayContext (), context.leftHand (), poseStack, bufferSource, context.combinedLight (), context.combinedOverlay (), context.bakedModel () ); poseStack.popPose(); } CoreFeature.resetRenderingGui (); flushBatching (); for (var context : decoratorDrawContexts) { poseStack.pushPose (); poseStack.setPose (context.transform(), context.normal()); context.handler().render( graphics, context.font (), context.stack (), context.xOffset (), context.yOffset () ); graphics.pose().popPose(); } for (var context : highlightDrawContexts) { poseStack.pushPose (); poseStack.last ().pose ().set(context.transform()); poseStack.last ().normal ().set(context.normal ()); AbstractContainerScreen.renderSlotHighlight( graphics, context.highlightX (), context.highlightY (), context.blitOffset (), context.color () ); graphics.pose().popPose(); } blitDrawContexts .clear (); stringDrawContexts .clear (); decoratorDrawContexts .clear (); fillDrawContexts .clear (); highlightDrawContexts .clear (); gradientDrawContexts .clear (); flatItemDrawContexts .clear (); blockItemDrawContexts .clear (); scissorFlush .restore(); } } public void flushBatching() { CoreStates .recordBuffers (); CoreBuffers.ENTITY .prepareBuffers (); CoreBuffers.BLOCK .prepareBuffers (); CoreBuffers.POS .prepareBuffers (); CoreBuffers.POS_COLOR .prepareBuffers (); CoreBuffers.POS_TEX .prepareBuffers (); CoreBuffers.POS_TEX_COLOR .prepareBuffers (); CoreBuffers.POS_COLOR_TEX_LIGHT .prepareBuffers (); CoreStates .restoreBuffers (); CoreBuffers.ENTITY .drawBuffers (LayerDrawType.ALL); CoreBuffers.BLOCK .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_COLOR .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_TEX .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_TEX_COLOR .drawBuffers (LayerDrawType.ALL); CoreBuffers.POS_COLOR_TEX_LIGHT .drawBuffers (LayerDrawType.ALL); CoreBuffers.ENTITY .clearBuffers (); CoreBuffers.BLOCK .clearBuffers (); CoreBuffers.POS .clearBuffers (); CoreBuffers.POS_COLOR .clearBuffers (); CoreBuffers.POS_TEX .clearBuffers (); CoreBuffers.POS_TEX_COLOR .clearBuffers (); CoreBuffers.POS_COLOR_TEX_LIGHT .clearBuffers (); } public void submitBlit( Matrix4f transform, Matrix3f normal, ResourceLocation atlasLocation, int minX, int maxX, int minY, int maxY, int blitOffset, int blitColor, float minU, float maxU, float minV, float maxV ) { var layer = getLayer(getGlobalDepth( transform.m22(), transform.m32(), blitOffset )); var context = new BlitDrawContext( new Matrix4f(transform), new Matrix3f(normal), atlasLocation, minX, maxX, minY, maxY, blitOffset, blitColor, 0, 0, minU, maxU, minV, maxV ); blitDrawContexts.add(context); layer .add(context); } public void submitItem( Matrix4f transform, Matrix3f normal, ItemStack itemStack, ItemDisplayContext displayContext, boolean leftHand, int combinedLight, int combinedOverlay, BakedModel bakedModel, boolean blockLight ) { var layer = getLayer(getGlobalDepth( transform.m22(), transform.m32(), 0.0f )); var context = new ItemRenderContext( new Matrix4f(transform), new Matrix3f(normal), itemStack, displayContext, leftHand, combinedLight, combinedOverlay, bakedModel ); var contexts = blockLight ? blockItemDrawContexts : flatItemDrawContexts; contexts.add(context); layer .add(context); } public void submitFill( Matrix4f transform, Matrix3f normal, RenderType renderType, int minX, int minY, int maxX, int maxY, int blitOffset, int color ) { if (RenderTypeUtils.hasDepth(renderType)) { var layer = getLayer(getGlobalDepth( transform.m22(), transform.m32(), blitOffset )); var context = new FillDrawContext( new Matrix4f(transform), new Matrix3f(normal), renderType, minX, minY, maxX, maxY, blitOffset, color, 0, 0 ); fillDrawContexts.add(context); layer .add(context); } else { var depth = depthLayers.lastFloatKey(); var layer = depthLayers.get (depth); var context = new FillDrawContext( new Matrix4f (transform).translate(0.0f, 0.0f, depth), new Matrix3f (normal), RenderTypeUtils.withDepth (renderType), minX, minY, maxX, maxY, 0, color, 0, 0 ); fillDrawContexts.add(context); layer .add(context); } } public void submitGradient( Matrix4f transform, Matrix3f normal, RenderType renderType, int minX, int minY, int maxX, int maxY, int blitOffset, int colorFrom, int colorTo ) { if (RenderTypeUtils.hasDepth(renderType)) { var layer = getLayer(getGlobalDepth( transform.m22(), transform.m32(), blitOffset )); var context = new GradientDrawContext( new Matrix4f(transform), new Matrix3f(normal), renderType, minX, minY, maxX, maxY, blitOffset, colorFrom, colorTo, 0, 0 ); gradientDrawContexts.add(context); layer .add(context); } else { var depth = depthLayers.lastFloatKey(); var layer = depthLayers.get (depth); var context = new GradientDrawContext( new Matrix4f (transform).translate(0.0f, 0.0f, depth), new Matrix3f (normal), RenderTypeUtils.withDepth (renderType), minX, minY, maxX, maxY, 0, colorFrom, colorTo, 0, 0 ); gradientDrawContexts.add(context); layer .add(context); } } @SuppressWarnings("UnstableApiUsage") public void submitCustomDecorator( Matrix4f transform, Matrix3f normal, ItemDecoratorHandler handler, Font font, ItemStack itemStack, int xOffset, int yOffset ) { var layer = getLayer(getGlobalDepth( transform.m22(), transform.m32(), 100.0f )); var context = new DecoratorDrawContext( new Matrix4f(transform), new Matrix3f(normal), handler, font, itemStack, xOffset, yOffset ); decoratorDrawContexts .add(context); layer .add(context); } public void submitHighlight( Matrix4f transform, Matrix3f normal, int highlightX, int highlightY, int blitOffset, int color ) { var layer = getLayer(getGlobalDepth( transform.m22(), transform.m32(), blitOffset )); var context = new HighlightDrawContext( new Matrix4f(transform), new Matrix3f(normal), highlightX, highlightY, blitOffset, color ); highlightDrawContexts .add(context); layer .add(context); } public void submitString(IStringDrawContext context) { var layer = getLayer(getGlobalDepth( context.transform().m22(), context.transform().m32(), 0.0f )); stringDrawContexts .add(context); layer .add(context); } private List getLayer(float depth) { var layer = depthLayers.get(depth); if (layer == null) { layer = new ReferenceArrayList<>(); depthLayers.put(depth, layer); } return layer; } public static float getGlobalDepth( float m22, float m32, float localDepth ) { return m22 * localDepth + m32; } public void delete() { scissorDraw .delete(); scissorFlush.delete(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/GuiRenderTypes.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.gui; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.Util; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.RenderType; import net.minecraft.resources.ResourceLocation; import java.util.function.Function; public class GuiRenderTypes extends RenderType { public static final ShaderStateShard POSITION_TEX_COLOR_SHADER = new ShaderStateShard(GameRenderer::getPositionTexColorShader); public static final Function BLIT = Util.memoize(atlasLocation -> create( "acceleratedrendering:blit", DefaultVertexFormat .POSITION_TEX_COLOR, VertexFormat.Mode .QUADS, 256, false, false, CompositeState .builder() .setTextureState (new TextureStateShard(atlasLocation, false, false)) .setShaderState (POSITION_TEX_COLOR_SHADER) .setDepthTestState (LEQUAL_DEPTH_TEST) .setTransparencyState (TRANSLUCENT_TRANSPARENCY) .createCompositeState (false) )); private GuiRenderTypes( String name, VertexFormat format, VertexFormat.Mode formatMode, int bufferSize, boolean affectsCrumbling, boolean sortOnUpload, Runnable setupState, Runnable clearState ) { super( name, format, formatMode, bufferSize, affectsCrumbling, sortOnUpload, setupState, clearState ); } public static RenderType blit(ResourceLocation atlasLocation) { return BLIT.apply(atlasLocation); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/BlitDrawContext.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.gui.contexts; import net.minecraft.resources.ResourceLocation; import org.joml.Matrix3f; import org.joml.Matrix4f; public record BlitDrawContext( Matrix4f transform, Matrix3f normal, ResourceLocation atlasLocation, int minX, int maxX, int minY, int maxY, int blitOffset, int blitColor, int blitLight, int blitOverlay, float minU, float maxU, float minV, float maxV ) implements IGuiElementContext { @Override public float depth() { return blitOffset; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/DecoratorDrawContext.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.gui.contexts; import net.minecraft.client.gui.Font; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.client.ItemDecoratorHandler; import org.joml.Matrix3f; import org.joml.Matrix4f; @SuppressWarnings("UnstableApiUsage") public record DecoratorDrawContext( Matrix4f transform, Matrix3f normal, ItemDecoratorHandler handler, Font font, ItemStack stack, int xOffset, int yOffset ) implements IGuiElementContext { @Override public float depth() { return 100.0f; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/FillDrawContext.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.gui.contexts; import net.minecraft.client.renderer.RenderType; import org.joml.Matrix3f; import org.joml.Matrix4f; public record FillDrawContext( Matrix4f transform, Matrix3f normal, RenderType renderType, int minX, int minY, int maxX, int maxY, int blitOffset, int color, int light, int overlay ) implements IGuiElementContext { @Override public float depth() { return blitOffset; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/GradientDrawContext.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.gui.contexts; import net.minecraft.client.renderer.RenderType; import org.joml.Matrix3f; import org.joml.Matrix4f; public record GradientDrawContext( Matrix4f transform, Matrix3f normal, RenderType renderType, int minX, int minY, int maxX, int maxY, int blitOffset, int colorFrom, int colorTo, int light, int overlay ) implements IGuiElementContext { @Override public float depth() { return blitOffset; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/HighlightDrawContext.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.gui.contexts; import org.joml.Matrix3f; import org.joml.Matrix4f; public record HighlightDrawContext( Matrix4f transform, Matrix3f normal, int highlightX, int highlightY, int blitOffset, int color ) implements IGuiElementContext { @Override public float depth() { return blitOffset; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/IGuiElementContext.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.gui.contexts; import org.joml.Matrix3f; import org.joml.Matrix4f; public interface IGuiElementContext { Matrix4f transform (); Matrix3f normal (); float depth (); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/ItemRenderContext.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.gui.contexts; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; import org.joml.Matrix3f; import org.joml.Matrix4f; public record ItemRenderContext( Matrix4f transform, Matrix3f normal, ItemStack itemStack, ItemDisplayContext displayContext, boolean leftHand, int combinedLight, int combinedOverlay, BakedModel bakedModel ) implements IGuiElementContext { @Override public float depth() { return 0.0f; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/string/ComponentStringDrawContext.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string; import net.minecraft.client.gui.Font; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.network.chat.Component; import org.joml.Matrix3f; import org.joml.Matrix4f; public record ComponentStringDrawContext( Matrix4f transform, Font font, Component text, float textX, float textY, int textColor, boolean dropShadow, Font.DisplayMode displayMode, int backgroundColor, int packedLight ) implements IStringDrawContext { public static final Matrix3f NORMAL = new Matrix3f().identity(); @Override public Matrix3f normal() { return NORMAL; } @Override public float depth() { return 0.0f; } @Override public void drawString(MultiBufferSource bufferSource) { font.drawInBatch( text, textX, textY, textColor, dropShadow, transform, bufferSource, displayMode, backgroundColor, packedLight ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/string/FormattedStringDrawContext.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string; import net.minecraft.client.gui.Font; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.network.chat.Component; import net.minecraft.util.FormattedCharSequence; import org.joml.Matrix3f; import org.joml.Matrix4f; public record FormattedStringDrawContext( Matrix4f transform, Font font, FormattedCharSequence text, float textX, float textY, int textColor, boolean dropShadow, Font.DisplayMode displayMode, int backgroundColor, int packedLight ) implements IStringDrawContext { public static final Matrix3f NORMAL = new Matrix3f().identity(); @Override public Matrix3f normal() { return NORMAL; } @Override public float depth() { return 0.0f; } @Override public void drawString(MultiBufferSource bufferSource) { font.drawInBatch( text, textX, textY, textColor, dropShadow, transform, bufferSource, displayMode, backgroundColor, packedLight ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/string/IStringDrawContext.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string; import com.github.argon4w.acceleratedrendering.features.items.gui.contexts.IGuiElementContext; import net.minecraft.client.renderer.MultiBufferSource; public interface IStringDrawContext extends IGuiElementContext { void drawString(MultiBufferSource buffer); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/string/Outline8StringDrawContext.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string; import net.minecraft.client.gui.Font; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.util.FormattedCharSequence; import org.joml.Matrix3f; import org.joml.Matrix4f; public record Outline8StringDrawContext( Matrix4f transform, Font font, FormattedCharSequence text, float textX, float textY, int textColor, int backgroundColor, int packedLight ) implements IStringDrawContext { public static final Matrix3f NORMAL = new Matrix3f().identity(); @Override public Matrix3f normal() { return NORMAL; } @Override public float depth() { return 0.0f; } @Override public void drawString(MultiBufferSource bufferSource) { font.drawInBatch8xOutline( text, textX, textY, textColor, backgroundColor, transform, bufferSource, packedLight ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/contexts/string/RawStringDrawContext.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string; import net.minecraft.client.gui.Font; import net.minecraft.client.renderer.MultiBufferSource; import org.joml.Matrix3f; import org.joml.Matrix4f; public record RawStringDrawContext( Matrix4f transform, Font font, String text, float textX, float textY, int textColor, boolean dropShadow, Font.DisplayMode displayMode, int backgroundColor, int packedLight, boolean bidirectional ) implements IStringDrawContext { public static final Matrix3f NORMAL = new Matrix3f().identity(); @Override public Matrix3f normal() { return NORMAL; } @Override public float depth() { return 0.0f; } @Override public void drawString(MultiBufferSource bufferSource) { font.drawInBatch( text, textX, textY, textColor, dropShadow, transform, bufferSource, displayMode, backgroundColor, packedLight, bidirectional ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/renderer/AcceleratedBlitRenderer.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.gui.renderer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.github.argon4w.acceleratedrendering.features.items.gui.contexts.BlitDrawContext; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.experimental.ExtensionMethod; import org.joml.Matrix3f; import org.joml.Matrix4f; @ExtensionMethod(VertexConsumerExtension.class) public class AcceleratedBlitRenderer implements IAcceleratedRenderer { public static final AcceleratedBlitRenderer INSTANCE = new AcceleratedBlitRenderer(); @Override public void render( VertexConsumer vertexConsumer, BlitDrawContext context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { var extension = vertexConsumer.getAccelerated(); extension.beginTransform(transform, normal); var minU = context.minU (); var minV = context.minV (); var maxU = context.maxU (); var maxV = context.maxV (); var minX = context.minX (); var minY = context.minY (); var maxX = context.maxX (); var maxY = context.maxY (); var blitOffset = context.blitOffset(); vertexConsumer.addVertex(minX, minY, blitOffset).setColor(color).setUv(minU, minV); vertexConsumer.addVertex(minX, maxY, blitOffset).setColor(color).setUv(minU, maxV); vertexConsumer.addVertex(maxX, maxY, blitOffset).setColor(color).setUv(maxU, maxV); vertexConsumer.addVertex(maxX, minY, blitOffset).setColor(color).setUv(maxU, minV); extension.endTransform(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/renderer/AcceleratedFillRenderer.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.gui.renderer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.github.argon4w.acceleratedrendering.features.items.gui.contexts.FillDrawContext; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.experimental.ExtensionMethod; import org.joml.Matrix3f; import org.joml.Matrix4f; @ExtensionMethod(VertexConsumerExtension.class) public class AcceleratedFillRenderer implements IAcceleratedRenderer { public static final AcceleratedFillRenderer INSTANCE = new AcceleratedFillRenderer(); @Override public void render( VertexConsumer vertexConsumer, FillDrawContext context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { var extension = vertexConsumer.getAccelerated(); extension.beginTransform(transform, normal); var blitOffset = context.blitOffset(); var minX = context.minX (); var minY = context.minY (); var maxX = context.maxX (); var maxY = context.maxY (); var swap = 0; if (minX < maxX) { swap = minX; minX = maxX; maxX = swap; } if (minY < maxY) { swap = minY; minY = maxY; maxY = swap; } vertexConsumer.addVertex(minX, minY, blitOffset).setColor(color); vertexConsumer.addVertex(minX, maxY, blitOffset).setColor(color); vertexConsumer.addVertex(maxX, maxY, blitOffset).setColor(color); vertexConsumer.addVertex(maxX, minY, blitOffset).setColor(color); extension.endTransform(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/gui/renderer/AcceleratedGradientRenderer.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.gui.renderer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.github.argon4w.acceleratedrendering.features.items.gui.contexts.FillDrawContext; import com.github.argon4w.acceleratedrendering.features.items.gui.contexts.GradientDrawContext; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.experimental.ExtensionMethod; import org.joml.Matrix3f; import org.joml.Matrix4f; @ExtensionMethod(VertexConsumerExtension.class) public class AcceleratedGradientRenderer implements IAcceleratedRenderer { public static final AcceleratedGradientRenderer INSTANCE = new AcceleratedGradientRenderer(); @Override public void render( VertexConsumer vertexConsumer, GradientDrawContext context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { var extension = vertexConsumer.getAccelerated(); extension.beginTransform(transform, normal); var blitOffset = context.blitOffset(); var minX = context.minX (); var minY = context.minY (); var maxX = context.maxX (); var maxY = context.maxY (); var colorFrom = context.colorFrom (); var colorTo = context.colorTo (); vertexConsumer.addVertex(minX, minY, blitOffset).setColor(colorFrom); vertexConsumer.addVertex(minX, maxY, blitOffset).setColor(colorTo); vertexConsumer.addVertex(maxX, maxY, blitOffset).setColor(colorTo); vertexConsumer.addVertex(maxX, minY, blitOffset).setColor(colorFrom); extension.endTransform(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/ItemRendererMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.mixins; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.utils.DirectionUtils; import com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature; import com.github.argon4w.acceleratedrendering.features.items.AcceleratedQuadsRenderer; import com.github.argon4w.acceleratedrendering.features.items.BakedModelExtension; import com.github.argon4w.acceleratedrendering.features.items.colors.ItemLayerColors; import com.github.argon4w.acceleratedrendering.features.items.contexts.AcceleratedQuadsRenderContext; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.util.RandomSource; import net.minecraft.world.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @ExtensionMethod(value = {VertexConsumerExtension .class, BakedModelExtension.class }) @Mixin (value = {ItemRenderer .class }) public class ItemRendererMixin { @SuppressWarnings ("deprecation") @WrapOperation ( method = "render", at = @At( value = "INVOKE", target = "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" ) ) public void renderFast( ItemRenderer instance, BakedModel pModel, ItemStack pStack, int pCombinedLight, int pCombinedOverlay, PoseStack pPoseStack, VertexConsumer pBuffer, Operation original ) { var extension1 = pBuffer.getAccelerated(); var extension2 = pModel .getAccelerated(); if ( ! AcceleratedItemRenderingFeature .isEnabled () || ! AcceleratedItemRenderingFeature .shouldUseAcceleratedPipeline () || ( ! CoreFeature .isRenderingLevel () && ! ( CoreFeature .isRenderingHand () && ( extension2 .isAcceleratedInHand () || AcceleratedItemRenderingFeature .shouldAccelerateInHand ())) && ! ( CoreFeature .isRenderingGui () && ( extension2 .isAcceleratedInGui () || AcceleratedItemRenderingFeature .shouldAccelerateInGui ()))) || ! extension1 .isAccelerated () ) { original.call( instance, pModel, pStack, pCombinedLight, pCombinedOverlay, pPoseStack, pBuffer ); return; } if (extension2.isAccelerated()) { extension2.renderItemFast( pStack, RandomSource.create (42L), pPoseStack .last (), extension1, pCombinedLight, pCombinedOverlay ); return; } if (!AcceleratedItemRenderingFeature.shouldBakeMeshForQuad()) { original.call( instance, pModel, pStack, pCombinedLight, pCombinedOverlay, pPoseStack, pBuffer ); return; } var pose = pPoseStack .last (); var randomSource = RandomSource .create (); for (var direction : DirectionUtils.FULL) { randomSource.setSeed (42L); extension1 .doRender ( AcceleratedQuadsRenderer.INSTANCE, new AcceleratedQuadsRenderContext( pModel.getQuads( null, direction, randomSource ), new ItemLayerColors(pStack) ), pose.pose (), pose.normal (), pCombinedLight, pCombinedOverlay, -1 ); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/ModelBlockRendererMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.mixins; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.utils.DirectionUtils; import com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature; import com.github.argon4w.acceleratedrendering.features.items.AcceleratedQuadsRenderer; import com.github.argon4w.acceleratedrendering.features.items.BakedModelExtension; import com.github.argon4w.acceleratedrendering.features.items.colors.FixedColors; import com.github.argon4w.acceleratedrendering.features.items.contexts.AcceleratedQuadsRenderContext; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.ModelBlockRenderer; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.util.FastColor; import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.data.ModelData; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @ExtensionMethod(value = {VertexConsumerExtension .class, BakedModelExtension.class }) @Mixin (value = {ModelBlockRenderer .class }, priority = 999) public class ModelBlockRendererMixin { @Inject( cancellable = true, method = "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", at = @At("HEAD") ) public void renderModelFast( PoseStack.Pose pose, VertexConsumer consumer, BlockState state, BakedModel model, float red, float green, float blue, int packedLight, int packedOverlay, ModelData modelData, RenderType renderType, CallbackInfo ci ) { var extension1 = consumer .getAccelerated(); var extension2 = model .getAccelerated(); if ( ! AcceleratedItemRenderingFeature .isEnabled () || ! AcceleratedItemRenderingFeature .shouldUseAcceleratedPipeline () || ( ! CoreFeature .isRenderingLevel () && ! ( CoreFeature .isRenderingHand () && ( extension2 .isAcceleratedInHand () || AcceleratedItemRenderingFeature .shouldAccelerateInHand ())) && ! ( CoreFeature .isRenderingGui () && ( extension2 .isAcceleratedInGui () || AcceleratedItemRenderingFeature .shouldAccelerateInGui ()))) || ! extension1 .isAccelerated () ) { return; } if (extension2.isAccelerated()) { ci .cancel (); extension2 .renderBlockFast( state, RandomSource.create(42), pose, extension1, packedLight, packedOverlay, FastColor.ARGB32.colorFromFloat( 1.0f, Mth.clamp(red, 0.0f, 1.0f), Mth.clamp(green, 0.0f, 1.0f), Mth.clamp(blue, 0.0f, 1.0f) ), modelData, renderType ); return; } if (!AcceleratedItemRenderingFeature.shouldBakeMeshForQuad()) { return; } ci.cancel(); var randomSource = RandomSource.create(); for (var direction : DirectionUtils.FULL) { randomSource.setSeed (42L); extension1 .doRender ( AcceleratedQuadsRenderer.INSTANCE, new AcceleratedQuadsRenderContext( model.getQuads( state, direction, randomSource, modelData, renderType ), new FixedColors(FastColor.ARGB32.colorFromFloat( 1.0f, Mth.clamp(red, 0.0f, 1.0f), Mth.clamp(green, 0.0f, 1.0f), Mth.clamp(blue, 0.0f, 1.0f) )) ), pose.pose (), pose.normal (), packedLight, packedOverlay, -1 ); } } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/accessors/BlockColorsAccessor.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.mixins.accessors; import net.minecraft.client.color.block.BlockColor; import net.minecraft.client.color.block.BlockColors; import net.minecraft.world.level.block.Block; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import java.util.Map; @Mixin(BlockColors.class) public interface BlockColorsAccessor { @Accessor("blockColors") Map getBlockColors(); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/accessors/ItemColorsAccessor.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.mixins.accessors; import net.minecraft.client.color.item.ItemColor; import net.minecraft.client.color.item.ItemColors; import net.minecraft.world.item.Item; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import java.util.Map; @Mixin(ItemColors.class) public interface ItemColorsAccessor { @Accessor("itemColors") Map getItemColors(); } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/compatibility/ClientHooksMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.mixins.compatibility; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature; import com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.neoforged.bus.api.Event; import net.neoforged.bus.api.IEventBus; import net.neoforged.neoforge.client.ClientHooks; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @Mixin(ClientHooks.class) public class ClientHooksMixin { @WrapOperation( method = "drawScreenInternal", at = @At( value = "INVOKE", target = "Lnet/neoforged/bus/api/IEventBus;post(Lnet/neoforged/bus/api/Event;)Lnet/neoforged/bus/api/Event;" ) ) private static Event disableAdditionalScreenAcceleration( IEventBus instance, Event event, Operation original ) { AcceleratedEntityRenderingFeature .useVanillaPipeline (); AcceleratedItemRenderingFeature .useVanillaPipeline (); AcceleratedTextRenderingFeature .useVanillaPipeline (); var result = original.call(instance, event); AcceleratedEntityRenderingFeature .resetPipeline (); AcceleratedItemRenderingFeature .resetPipeline (); AcceleratedTextRenderingFeature .resetPipeline (); return result; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/compatibility/GuiLayerManagerMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.mixins.compatibility; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature; import com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.neoforged.bus.api.Event; import net.neoforged.bus.api.IEventBus; import net.neoforged.neoforge.client.gui.GuiLayerManager; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @SuppressWarnings ("UnstableApiUsage") @Mixin (GuiLayerManager.class) public class GuiLayerManagerMixin { @WrapOperation( method = "render", at = @At( value = "INVOKE", target = "Lnet/neoforged/bus/api/IEventBus;post(Lnet/neoforged/bus/api/Event;)Lnet/neoforged/bus/api/Event;" ) ) private static Event disableAdditionalGuiAcceleration( IEventBus instance, Event event, Operation original ) { AcceleratedEntityRenderingFeature .useVanillaPipeline (); AcceleratedItemRenderingFeature .useVanillaPipeline (); AcceleratedTextRenderingFeature .useVanillaPipeline (); var result = original.call(instance, event); AcceleratedEntityRenderingFeature .resetPipeline (); AcceleratedItemRenderingFeature .resetPipeline (); AcceleratedTextRenderingFeature .resetPipeline (); return result; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/gui/AbstractContainerScreenMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.mixins.gui; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature; import com.github.argon4w.acceleratedrendering.features.items.gui.GuiBatchingController; import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(AbstractContainerScreen.class) public abstract class AbstractContainerScreenMixin { @Inject( method = "render", at = @At("HEAD") ) public void startBackgroundBatching( GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick, CallbackInfo ci ) { GuiBatchingController.INSTANCE.startBatching(guiGraphics); } @Inject( method = "render", at = @At( value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;translate(FFF)V", shift = At.Shift.BEFORE ) ) public void flushBackgroundBatching( GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick, CallbackInfo ci ) { if (!AcceleratedItemRenderingFeature.shouldMergeGuiItemBatches()) { GuiBatchingController.INSTANCE.flushBatching(guiGraphics); } } @Inject( method = "render", at = @At( value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;translate(FFF)V", shift = At.Shift.AFTER ) ) public void startItemBatching( GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick, CallbackInfo ci ) { if (!AcceleratedItemRenderingFeature.shouldMergeGuiItemBatches()) { GuiBatchingController.INSTANCE.startBatching(guiGraphics); } } @Inject( method = "render", at = @At( value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/AbstractContainerScreen;renderLabels(Lnet/minecraft/client/gui/GuiGraphics;II)V", shift = At.Shift.AFTER ) ) public void flushItemBatching( GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick, CallbackInfo ci ) { GuiBatchingController.INSTANCE.flushBatching(guiGraphics); } @WrapMethod(method = "renderSlotHighlight(Lnet/minecraft/client/gui/GuiGraphics;IIII)V") private static void startRenderHighlight( GuiGraphics guiGraphics, int highlightX, int highLightY, int blitOffset, int color, Operation original ) { if (!CoreFeature.isGuiBatching()) { original.call( guiGraphics, highlightX, highLightY, blitOffset, color ); return; } var last = guiGraphics.pose().last(); GuiBatchingController.INSTANCE.submitHighlight( last.pose (), last.normal (), highlightX, highLightY, blitOffset, color ); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/gui/FontMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.mixins.gui; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.features.items.gui.GuiBatchingController; import com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string.ComponentStringDrawContext; import com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string.FormattedStringDrawContext; import com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string.Outline8StringDrawContext; import com.github.argon4w.acceleratedrendering.features.items.gui.contexts.string.RawStringDrawContext; import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import net.minecraft.client.gui.Font; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.network.chat.Component; import net.minecraft.util.FormattedCharSequence; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @Mixin(Font.class) public abstract class FontMixin { @Shadow public abstract boolean isBidirectional(); @WrapMethod(method = "drawInBatch(Ljava/lang/String;FFIZLorg/joml/Matrix4f;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/client/gui/Font$DisplayMode;II)I") public int renderGuiStringFast1( String text, float textX, float textY, int textColor, boolean dropShadow, Matrix4f transform, MultiBufferSource bufferSource, Font.DisplayMode displayMode, int backgroundColor, int packedLight, Operation original ) { if (!CoreFeature.isGuiBatching()) { return original.call( text, textX, textY, textColor, dropShadow, transform, bufferSource, displayMode, backgroundColor, packedLight ); } GuiBatchingController.INSTANCE.submitString(new RawStringDrawContext( new Matrix4f(transform), (Font) (Object) this, text, textX, textY, textColor, dropShadow, displayMode, backgroundColor, packedLight, isBidirectional() )); return 0; } @WrapMethod(method = "drawInBatch(Ljava/lang/String;FFIZLorg/joml/Matrix4f;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/client/gui/Font$DisplayMode;IIZ)I") public int renderGuiStringFast2( String text, float textX, float textY, int textColor, boolean dropShadow, Matrix4f transform, MultiBufferSource bufferSource, Font.DisplayMode displayMode, int backgroundColor, int packedLight, boolean bidirectional, Operation original ) { if (!CoreFeature.isGuiBatching()) { return original.call( text, textX, textY, textColor, dropShadow, transform, bufferSource, displayMode, backgroundColor, packedLight, bidirectional ); } GuiBatchingController.INSTANCE.submitString(new RawStringDrawContext( new Matrix4f(transform), (Font) (Object) this, text, textX, textY, textColor, dropShadow, displayMode, backgroundColor, packedLight, bidirectional )); return 0; } @WrapMethod(method = "drawInBatch(Lnet/minecraft/network/chat/Component;FFIZLorg/joml/Matrix4f;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/client/gui/Font$DisplayMode;II)I") public int renderGuiStringFast3( Component text, float textX, float textY, int textColor, boolean dropShadow, Matrix4f transform, MultiBufferSource bufferSource, Font.DisplayMode displayMode, int backgroundColor, int packedLight, Operation original ) { if (!CoreFeature.isGuiBatching()) { return original.call( text, textX, textY, textColor, dropShadow, transform, bufferSource, displayMode, backgroundColor, packedLight ); } GuiBatchingController.INSTANCE.submitString(new ComponentStringDrawContext( new Matrix4f(transform), (Font) (Object) this, text, textX, textY, textColor, dropShadow, displayMode, backgroundColor, packedLight )); return 0; } @WrapMethod(method = "drawInBatch(Lnet/minecraft/util/FormattedCharSequence;FFIZLorg/joml/Matrix4f;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/client/gui/Font$DisplayMode;II)I") public int renderGuiStringFast4( FormattedCharSequence text, float textX, float textY, int textColor, boolean dropShadow, Matrix4f transform, MultiBufferSource bufferSource, Font.DisplayMode displayMode, int backgroundColor, int packedLight, Operation original ) { if (!CoreFeature.isGuiBatching()) { return original.call( text, textX, textY, textColor, dropShadow, transform, bufferSource, displayMode, backgroundColor, packedLight ); } GuiBatchingController.INSTANCE.submitString(new FormattedStringDrawContext( new Matrix4f(transform), (Font) (Object) this, text, textX, textY, textColor, dropShadow, displayMode, backgroundColor, packedLight )); return 0; } @WrapMethod(method = "drawInBatch8xOutline") public void renderGuiStringFast5( FormattedCharSequence text, float textX, float textY, int textColor, int backgroundColor, Matrix4f transform, MultiBufferSource bufferSource, int packedLight, Operation original ) { if (!CoreFeature.isGuiBatching()) { original.call( text, textX, textY, textColor, backgroundColor, transform, bufferSource, packedLight ); return; } GuiBatchingController.INSTANCE.submitString(new Outline8StringDrawContext( new Matrix4f(transform), (Font) (Object) this, text, textX, textY, textColor, backgroundColor, packedLight )); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/gui/GuiGraphicsMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.mixins.gui; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.features.items.AcceleratedItemRenderingFeature; import com.github.argon4w.acceleratedrendering.features.items.gui.GuiBatchingController; import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.FastColor; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.client.ItemDecoratorHandler; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @Mixin(GuiGraphics.class) public class GuiGraphicsMixin { @Shadow @Final private PoseStack pose; @WrapMethod(method = "fill(IIIII)V") public void renderFillFast( int minX, int minY, int maxX, int maxY, int color, Operation original ) { if (!CoreFeature.isGuiBatching()) { original.call( minX, minY, maxX, maxY, color ); return; } var last = pose.last(); GuiBatchingController.INSTANCE.submitFill( last .pose (), last .normal (), RenderType .gui (), minX, minY, maxX, maxY, -1, color ); } @WrapMethod(method = "fill(Lnet/minecraft/client/renderer/RenderType;IIIIII)V") public void renderFillFast( RenderType renderType, int minX, int minY, int maxX, int maxY, int blitOffset, int color, Operation original ) { if (!CoreFeature.isGuiBatching()) { original.call( renderType, minX, minY, maxX, maxY, blitOffset, color ); return; } var last = pose.last(); GuiBatchingController.INSTANCE.submitFill( last.pose (), last.normal (), renderType, minX, minY, maxX, maxY, blitOffset, color ); } @WrapMethod(method = "fillGradient(Lnet/minecraft/client/renderer/RenderType;IIIIIII)V") public void renderGradientFast( RenderType renderType, int minX, int minY, int maxX, int maxY, int colorFrom, int colorTo, int blitOffset, Operation original ) { if (!CoreFeature.isGuiBatching()) { original.call( renderType, minX, minY, maxX, maxY, colorFrom, colorTo, blitOffset ); return; } var last = pose.last(); GuiBatchingController.INSTANCE.submitGradient( last.pose (), last.normal (), renderType, minX, minY, maxX, maxY, blitOffset, colorFrom, colorTo ); } @WrapMethod(method = "fillRenderType") public void renderRenderTypeFast( RenderType renderType, int minX, int minY, int maxX, int maxY, int blitOffset, Operation original ) { if (!CoreFeature.isGuiBatching()) { original.call( renderType, minX, minY, maxX, maxY, blitOffset ); return; } var last = pose.last(); GuiBatchingController.INSTANCE.submitGradient( last.pose (), last.normal (), renderType, minX, minY, maxX, maxY, blitOffset, -1, -1 ); } @WrapMethod(method = "innerBlit(Lnet/minecraft/resources/ResourceLocation;IIIIIFFFF)V") public void renderBlitFast( ResourceLocation atlasLocation, int minX, int maxX, int minY, int maxY, int blitOffset, float minU, float maxU, float minV, float maxV, Operation original ) { if (!CoreFeature.isGuiBatching()) { original.call( atlasLocation, minX, maxX, minY, maxY, blitOffset, minU, maxU, minV, maxV ); return; } var last = pose.last(); GuiBatchingController.INSTANCE.submitBlit( last.pose (), last.normal (), atlasLocation, minX, maxX, minY, maxY, blitOffset, -1, minU, maxU, minV, maxV ); } @WrapMethod(method = "innerBlit(Lnet/minecraft/resources/ResourceLocation;IIIIIFFFFFFFF)V") public void renderBlitFast( ResourceLocation atlasLocation, int minX, int maxX, int minY, int maxY, int blitOffset, float minU, float maxU, float minV, float maxV, float red, float green, float blue, float alpha, Operation original ) { if (!CoreFeature.isGuiBatching()) { original.call( atlasLocation, minX, maxX, minY, maxY, blitOffset, minU, maxU, minV, maxV, red, green, blue, alpha ); return; } var last = pose.last(); GuiBatchingController.INSTANCE.submitBlit( last.pose (), last.normal (), atlasLocation, minX, maxX, minY, maxY, blitOffset, FastColor.ARGB32.color( (int) (alpha * 255.0f), (int) (red * 255.0f), (int) (green * 255.0f), (int) (blue * 255.0f) ), minU, maxU, minV, maxV ); } @SuppressWarnings ("UnstableApiUsage") @WrapOperation ( method = "renderItemDecorations(Lnet/minecraft/client/gui/Font;Lnet/minecraft/world/item/ItemStack;IILjava/lang/String;)V", at = @At( value = "INVOKE", target = "Lnet/neoforged/neoforge/client/ItemDecoratorHandler;render(Lnet/minecraft/client/gui/GuiGraphics;Lnet/minecraft/client/gui/Font;Lnet/minecraft/world/item/ItemStack;II)V" ) ) public void renderDecorationCustomFast( ItemDecoratorHandler instance, GuiGraphics guiGraphics, Font font, ItemStack stack, int xOffset, int yOffset, Operation original ) { if (!CoreFeature.isGuiBatching()) { original.call( instance, guiGraphics, font, stack, xOffset, yOffset ); return; } var last = pose.last(); GuiBatchingController.INSTANCE.submitCustomDecorator( last.pose (), last.normal (), instance, font, stack, xOffset, yOffset ); } @WrapOperation( method = "renderItem(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;IIII)V", at = @At( value = "INVOKE", target = "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" ) ) public void renderItemFast( ItemRenderer instance, ItemStack itemStack, ItemDisplayContext displayContext, boolean leftHand, PoseStack poseStack, MultiBufferSource bufferSource, int combinedLight, int combinedOverlay, BakedModel bakedModel, Operation original ) { if ( !AcceleratedItemRenderingFeature.isEnabled () || !AcceleratedItemRenderingFeature.shouldUseAcceleratedPipeline () || !AcceleratedItemRenderingFeature.shouldAccelerateInGui () || !CoreFeature .isLoaded () ) { original.call( instance, itemStack, displayContext, leftHand, poseStack, bufferSource, combinedLight, combinedOverlay, bakedModel ); return; } if (CoreFeature.isGuiBatching()) { var last = pose.last(); GuiBatchingController.INSTANCE.submitItem( last.pose (), last.normal (), itemStack, displayContext, leftHand, combinedLight, combinedOverlay, bakedModel, bakedModel.usesBlockLight() ); return; } CoreFeature.setRenderingGui(); original.call( instance, itemStack, displayContext, leftHand, poseStack, bufferSource, combinedLight, combinedOverlay, bakedModel ); CoreFeature .resetRenderingGui (); GuiBatchingController.INSTANCE .flushBatching (); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/gui/GuiMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.mixins.gui; import com.github.argon4w.acceleratedrendering.features.items.gui.GuiBatchingController; import net.minecraft.client.DeltaTracker; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiGraphics; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(Gui.class) public class GuiMixin { @Inject( method = "renderItemHotbar", at = @At("HEAD") ) public void startBatching( GuiGraphics guiGraphics, DeltaTracker deltaTracker, CallbackInfo ci ) { GuiBatchingController.INSTANCE.startBatching(guiGraphics); } @Inject( method = "renderItemHotbar", at = @At("TAIL") ) public void flushBatching( GuiGraphics guiGraphics, DeltaTracker deltaTracker, CallbackInfo ci ) { GuiBatchingController.INSTANCE.flushBatching(guiGraphics); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/models/BakedCompositeModelMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.mixins.models; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.features.items.BakedModelExtension; import com.github.argon4w.acceleratedrendering.features.items.IAcceleratedBakedModel; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.mojang.blaze3d.vertex.PoseStack; import lombok.Getter; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.ItemOverrides; import net.minecraft.client.renderer.block.model.ItemTransforms; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.util.RandomSource; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.CompositeModel; import net.neoforged.neoforge.client.model.data.ModelData; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Getter @ExtensionMethod(BakedModelExtension .class) @Mixin (CompositeModel.Baked .class) public class BakedCompositeModelMixin implements IAcceleratedBakedModel { @Shadow @Final private ImmutableMap children; @Unique private boolean accelerated; @Unique private boolean acceleratedInHand; @Unique private boolean acceleratedInGui; @Inject( method = "", at = @At("TAIL") ) public void checkAccelerationSupport( boolean isGui3d, boolean isSideLit, boolean isAmbientOcclusion, TextureAtlasSprite particle, ItemTransforms transforms, ItemOverrides overrides, ImmutableMap children, ImmutableList itemPasses, CallbackInfo ci ) { accelerated = true; acceleratedInHand = true; acceleratedInGui = true; for (BakedModel childModel : children.values()) { var extension = childModel.getAccelerated(); accelerated &= extension.isAccelerated (); acceleratedInHand &= extension.isAcceleratedInHand(); acceleratedInGui &= extension.isAcceleratedInGui (); } } @Override public void renderItemFast( ItemStack itemStack, RandomSource random, PoseStack.Pose pose, IAcceleratedVertexConsumer extension, int light, int overlay ) { for (BakedModel child : children.values()) { child .getAccelerated () .renderItemFast( itemStack, random, pose, extension, light, overlay ); } } @Override public void renderBlockFast( BlockState blockState, RandomSource random, PoseStack.Pose pose, IAcceleratedVertexConsumer extension, int light, int overlay, int color, ModelData data, RenderType renderType ) { for (BakedModel child : children.values()) { var renderTypeSet = blockState == null ? null : child.getRenderTypes( blockState, random, data ); if ( renderType == null || ( renderTypeSet != null && renderTypeSet.contains(renderType)) ) { child .getAccelerated () .renderBlockFast( blockState, random, pose, extension, light, overlay, getCustomColor(-1, color), data, renderType ); } } } @Override public int getCustomColor(int layer, int color) { return color; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/models/BakedModelMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.mixins.models; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.features.items.IAcceleratedBakedModel; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.util.RandomSource; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.data.ModelData; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @Mixin(BakedModel.class) public interface BakedModelMixin extends IAcceleratedBakedModel { @Unique @Override default void renderItemFast( ItemStack itemStack, RandomSource random, PoseStack.Pose pose, IAcceleratedVertexConsumer vertexConsumer, int light, int overlay ) { throw new UnsupportedOperationException("Unsupported Operation."); } @Unique @Override default void renderBlockFast( BlockState state, RandomSource random, PoseStack.Pose pose, IAcceleratedVertexConsumer extension, int light, int overlay, int color, ModelData data, RenderType renderType ) { throw new UnsupportedOperationException("Unsupported Operation."); } @Unique @Override default boolean isAccelerated() { return false; } @Unique @Override default boolean isAcceleratedInHand() { return false; } @Unique @Override default boolean isAcceleratedInGui() { return false; } @Unique @Override default int getCustomColor(int layer, int color) { return color; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/models/BakedQuadMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.mixins.models; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IBufferGraph; import com.github.argon4w.acceleratedrendering.core.meshes.IMesh; import com.github.argon4w.acceleratedrendering.core.meshes.collectors.CulledMeshCollector; import com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData; import com.github.argon4w.acceleratedrendering.core.utils.FastColorUtils; import com.github.argon4w.acceleratedrendering.core.utils.IntArrayHashStrategy; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.github.argon4w.acceleratedrendering.features.items.IAcceleratedBakedQuad; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.client.renderer.block.model.BakedQuad; import net.neoforged.neoforge.client.model.IQuadTransformer; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import java.util.Map; @Mixin(BakedQuad.class) public abstract class BakedQuadMixin implements IAcceleratedBakedQuad { @Unique private static final Map> MESHES = new Object2ObjectOpenCustomHashMap<>(IntArrayHashStrategy.INSTANCE); @Unique private static final Map> MERGES = new Object2ObjectOpenCustomHashMap<>(IntArrayHashStrategy.INSTANCE); @Shadow @Final protected int[] vertices; @Shadow public abstract boolean isTinted(); @Unique @Override public void renderFast( Matrix4f transform, Matrix3f normal, IAcceleratedVertexConsumer extension, int combinedLight, int combinedOverlay, int color ) { var meshes = MESHES.get(vertices); var merges = MERGES.get(vertices); if (meshes == null) { meshes = new Object2ObjectOpenHashMap<> (); merges = new Object2ObjectOpenHashMap<> (); MESHES.put (vertices, meshes); MERGES.put (vertices, merges); } var mesh = meshes.get(extension); if (mesh != null) { mesh.write( extension, getCustomColor(color), combinedLight, combinedOverlay ); return; } var culledMeshCollector = new CulledMeshCollector (extension); var meshBuilder = extension.decorate (culledMeshCollector); for (var i = 0; i < vertices.length / 8; i++) { var vertexOffset = i * IQuadTransformer.STRIDE; var posOffset = vertexOffset + IQuadTransformer.POSITION; var colorOffset = vertexOffset + IQuadTransformer.COLOR; var uv0Offset = vertexOffset + IQuadTransformer.UV0; var uv2Offset = vertexOffset + IQuadTransformer.UV2; var normalOffset = vertexOffset + IQuadTransformer.NORMAL; var packedNormal = vertices[normalOffset]; meshBuilder.addVertex( Float .intBitsToFloat (vertices[posOffset + 0]), Float .intBitsToFloat (vertices[posOffset + 1]), Float .intBitsToFloat (vertices[posOffset + 2]), FastColorUtils .convert (vertices[colorOffset]), Float .intBitsToFloat (vertices[uv0Offset + 0]), Float .intBitsToFloat (vertices[uv0Offset + 1]), combinedOverlay, vertices[uv2Offset], ((byte) ( packedNormal & 0xFF)) / 127.0f, ((byte) (( packedNormal >> 8) & 0xFF)) / 127.0f, ((byte) (( packedNormal >> 16) & 0xFF)) / 127.0f ); } culledMeshCollector.flush(); var data = culledMeshCollector .getData (); var buffer = culledMeshCollector .getBuffer (); mesh = merges .get (data); if (mesh != null) { buffer.discard (); buffer.close (); } else { mesh = AcceleratedEntityRenderingFeature .getMeshType() .getBuilder () .build (culledMeshCollector); } meshes .put (extension, mesh); merges .put (data, mesh); mesh .write ( extension, getCustomColor(color), combinedLight, combinedOverlay ); } @Unique @Override public int getCustomColor(int color) { return isTinted() ? color : -1; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/models/BakedSeparateTransformsModelMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.mixins.models; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.features.items.BakedModelExtension; import com.github.argon4w.acceleratedrendering.features.items.IAcceleratedBakedModel; import com.mojang.blaze3d.vertex.PoseStack; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.util.RandomSource; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.SeparateTransformsModel; import net.neoforged.neoforge.client.model.data.ModelData; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @ExtensionMethod(BakedModelExtension .class) @Mixin (SeparateTransformsModel.Baked .class) public class BakedSeparateTransformsModelMixin implements IAcceleratedBakedModel { @Shadow @Final private BakedModel baseModel; @Override public void renderItemFast( ItemStack itemStack, RandomSource random, PoseStack.Pose pose, IAcceleratedVertexConsumer extension, int light, int overlay ) { baseModel .getAccelerated() .renderItemFast( itemStack, random, pose, extension, light, overlay ); } @Override public void renderBlockFast( BlockState blockState, RandomSource random, PoseStack.Pose pose, IAcceleratedVertexConsumer extension, int light, int overlay, int color, ModelData data, RenderType renderType ) { baseModel .getAccelerated () .renderBlockFast( blockState, random, pose, extension, light, overlay, color, data, renderType ); } @Override public int getCustomColor(int layer, int color) { return baseModel .getAccelerated() .getCustomColor(layer, color); } @Override public boolean isAccelerated() { return baseModel .getAccelerated () .isAccelerated (); } @Override public boolean isAcceleratedInHand() { return baseModel .getAccelerated () .isAcceleratedInHand(); } @Override public boolean isAcceleratedInGui() { return baseModel .getAccelerated () .isAcceleratedInGui (); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/models/MultipartBakedModelMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.mixins.models; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.features.items.BakedModelExtension; import com.github.argon4w.acceleratedrendering.features.items.IAcceleratedBakedModel; import com.mojang.blaze3d.vertex.PoseStack; import lombok.Getter; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.MultiPartBakedModel; import net.minecraft.util.RandomSource; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.data.ModelData; import org.apache.commons.lang3.tuple.Pair; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.BitSet; import java.util.List; import java.util.function.Predicate; @Getter @ExtensionMethod(BakedModelExtension.class) @Mixin (MultiPartBakedModel.class) public abstract class MultipartBakedModelMixin implements IAcceleratedBakedModel { @Unique private boolean accelerated; @Unique private boolean acceleratedInHand; @Unique private boolean acceleratedInGui; @Shadow @Final private List, BakedModel>> selectors; @Shadow public abstract BitSet getSelectors(BlockState p_235050_); @Inject( method = "", at = @At("TAIL") ) public void checkAccelerationSupport(List, BakedModel>> selectors, CallbackInfo ci) { accelerated = true; acceleratedInHand = true; acceleratedInGui = true; for (Pair, BakedModel> selector : selectors) { var extension = selector.getRight().getAccelerated(); accelerated &= extension.isAccelerated (); acceleratedInHand &= extension.isAcceleratedInHand(); acceleratedInGui &= extension.isAcceleratedInGui (); } } @Override public void renderItemFast( ItemStack itemStack, RandomSource random, PoseStack.Pose pose, IAcceleratedVertexConsumer extension, int light, int overlay ) { } @Override public void renderBlockFast( BlockState blockState, RandomSource random, PoseStack.Pose pose, IAcceleratedVertexConsumer extension, int light, int overlay, int color, ModelData data, RenderType renderType ) { if (blockState == null) { return; } var bitset = getSelectors (blockState); var seed = random.nextLong (); for (var j = 0; j < bitset.length(); j ++) { if (bitset.get(j)) { var selector = selectors .get (j); var selected = selector .getRight (); var renderTypeSet = selected .getRenderTypes ( blockState, random, data ); if ( renderType == null || renderTypeSet.contains(renderType) ) { selected .getAccelerated () .renderBlockFast( blockState, RandomSource.create(seed), pose, extension, light, overlay, getCustomColor(-1, color), data, renderType ); } } } } @Override public int getCustomColor(int layer, int color) { return color; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/models/SimpleBakedModelMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.mixins.models; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IBufferGraph; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.github.argon4w.acceleratedrendering.core.meshes.IMesh; import com.github.argon4w.acceleratedrendering.core.meshes.collectors.CulledMeshCollector; import com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData; import com.github.argon4w.acceleratedrendering.core.utils.DirectionUtils; import com.github.argon4w.acceleratedrendering.core.utils.FastColorUtils; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.github.argon4w.acceleratedrendering.features.items.IAcceleratedBakedModel; import com.github.argon4w.acceleratedrendering.features.items.colors.FixedColors; import com.github.argon4w.acceleratedrendering.features.items.colors.ItemLayerColors; import com.github.argon4w.acceleratedrendering.features.items.contexts.AcceleratedModelRenderContext; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.resources.model.SimpleBakedModel; import net.minecraft.core.Direction; import net.minecraft.util.RandomSource; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.IQuadTransformer; import net.neoforged.neoforge.client.model.data.ModelData; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import java.util.List; import java.util.Map; @ExtensionMethod(VertexConsumerExtension.class) @Mixin (SimpleBakedModel .class) public abstract class SimpleBakedModelMixin implements IAcceleratedBakedModel, IAcceleratedRenderer { @Shadow public abstract List getQuads(BlockState pState, Direction pDirection, RandomSource pRandom); @Unique private final Map> meshes = new Object2ObjectOpenHashMap<>(); @Unique private final Map merges = new Object2ObjectOpenHashMap<>(); @Unique @Override public void renderItemFast( ItemStack itemStack, RandomSource random, PoseStack.Pose pose, IAcceleratedVertexConsumer extension, int combinedLight, int combinedOverlay ) { extension.doRender( this, new AcceleratedModelRenderContext(random, new ItemLayerColors(itemStack)), pose.pose (), pose.normal (), combinedLight, combinedOverlay, -1 ); } @Override public void renderBlockFast( BlockState state, RandomSource random, PoseStack.Pose pose, IAcceleratedVertexConsumer extension, int combinedLight, int combinedOverlay, int color, ModelData data, RenderType renderType ) { extension.doRender( this, new AcceleratedModelRenderContext(random, new FixedColors(color)), pose.pose (), pose.normal (), combinedLight, combinedOverlay, -1 ); } @Unique @Override public void render( VertexConsumer vertexConsumer, AcceleratedModelRenderContext context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { var extension = vertexConsumer.getAccelerated (); var randomSource = context .randomSource (); var layerColors = context .layerColors (); var layers = meshes .get (extension); extension.beginTransform(transform, normal); if (layers != null) { for (int layer : layers.keySet()) { var mesh = layers.get(layer); mesh.write( extension, getCustomColor(layer, layerColors.getColor(layer)), light, overlay ); } extension.endTransform(); return; } var culledMeshCollectors = new Int2ObjectOpenHashMap (); layers = new Int2ObjectAVLTreeMap <> (); meshes.put(extension, layers); for (var direction : DirectionUtils.FULL) { for (var quad : getQuads( null, direction, randomSource )) { var culledMeshCollector = culledMeshCollectors.get(quad.getTintIndex()); if (culledMeshCollector == null) { culledMeshCollector = new CulledMeshCollector (extension); culledMeshCollectors.put (quad.getTintIndex(), culledMeshCollector); } var meshBuilder = extension .decorate (culledMeshCollector); var data = quad .getVertices(); for (int i = 0; i < data.length / 8; i++) { var vertexOffset = i * IQuadTransformer.STRIDE; var posOffset = vertexOffset + IQuadTransformer.POSITION; var colorOffset = vertexOffset + IQuadTransformer.COLOR; var uv0Offset = vertexOffset + IQuadTransformer.UV0; var uv2Offset = vertexOffset + IQuadTransformer.UV2; var normalOffset = vertexOffset + IQuadTransformer.NORMAL; var packedNormal = data[normalOffset]; meshBuilder.addVertex( Float .intBitsToFloat (data[posOffset + 0]), Float .intBitsToFloat (data[posOffset + 1]), Float .intBitsToFloat (data[posOffset + 2]), FastColorUtils .convert (data[colorOffset]), Float .intBitsToFloat (data[uv0Offset + 0]), Float .intBitsToFloat (data[uv0Offset + 1]), -1, data[uv2Offset], ((byte) ( packedNormal & 0xFF)) / 127.0f, ((byte) (( packedNormal >> 8) & 0xFF)) / 127.0f, ((byte) (( packedNormal >> 16) & 0xFF)) / 127.0f ); } } } for (int layer : culledMeshCollectors.keySet()) { var culledMeshCollector = culledMeshCollectors.get(layer); culledMeshCollector.flush(); var data = culledMeshCollector .getData (); var buffer = culledMeshCollector .getBuffer (); var mesh = merges .get (data); if (mesh != null) { buffer.discard (); buffer.close (); } else { mesh = AcceleratedEntityRenderingFeature .getMeshType() .getBuilder () .build (culledMeshCollector); } layers .put (layer, mesh); merges .put (data, mesh); mesh .write ( extension, getCustomColor(layer, layerColors.getColor(layer)), light, overlay ); } extension.endTransform(); } @Unique @Override public boolean isAccelerated() { return true; } @Unique @Override public boolean isAcceleratedInHand() { return false; } @Unique @Override public boolean isAcceleratedInGui() { return false; } @Unique @Override public int getCustomColor(int layer, int color) { return layer == -1 ? -1 : color; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/items/mixins/models/WeightedBakedModelMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.items.mixins.models; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.features.items.BakedModelExtension; import com.github.argon4w.acceleratedrendering.features.items.IAcceleratedBakedModel; import com.mojang.blaze3d.vertex.PoseStack; import lombok.Getter; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.WeightedBakedModel; import net.minecraft.util.RandomSource; import net.minecraft.util.random.WeightedEntry; import net.minecraft.util.random.WeightedRandom; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.data.ModelData; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.List; @Getter @ExtensionMethod(BakedModelExtension.class) @Mixin (WeightedBakedModel .class) public class WeightedBakedModelMixin implements IAcceleratedBakedModel { @Unique private boolean accelerated; @Unique private boolean acceleratedInHand; @Unique private boolean acceleratedInGui; @Shadow @Final private List> list; @Shadow @Final private int totalWeight; @Inject( method = "", at = @At("TAIL") ) public void checkAccelerationSupport(List> list, CallbackInfo ci) { accelerated = true; acceleratedInHand = true; acceleratedInGui = true; for (WeightedEntry.Wrapper wrapper : list) { var extension = wrapper.data().getAccelerated(); accelerated &= extension.isAccelerated (); acceleratedInHand &= extension.isAcceleratedInHand(); acceleratedInGui &= extension.isAcceleratedInGui (); } } @Override public void renderItemFast( ItemStack itemStack, RandomSource random, PoseStack.Pose pose, IAcceleratedVertexConsumer extension, int light, int overlay ) { var model = WeightedRandom.getWeightedItem(list, Math.abs((int) random.nextLong()) % totalWeight); if (model.isPresent()) { model .get () .data () .getAccelerated () .renderItemFast ( itemStack, random, pose, extension, light, overlay ); } } @Override public void renderBlockFast( BlockState state, RandomSource random, PoseStack.Pose pose, IAcceleratedVertexConsumer extension, int light, int overlay, int color, ModelData data, RenderType renderType ) { var model = WeightedRandom.getWeightedItem(list, Math.abs((int) random.nextLong()) % totalWeight); if (model.isPresent()) { model .get () .data () .getAccelerated () .renderBlockFast( state, random, pose, extension, light, overlay, getCustomColor(-1, color), data, renderType ); } } @Override public int getCustomColor(int layer, int color) { return color; } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/modelparts/mixins/ModelPartMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.modelparts.mixins; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IBufferGraph; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.github.argon4w.acceleratedrendering.core.meshes.IMesh; import com.github.argon4w.acceleratedrendering.core.meshes.collectors.CulledMeshCollector; import com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.experimental.ExtensionMethod; import net.minecraft.client.model.geom.ModelPart; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.List; import java.util.Map; @ExtensionMethod (VertexConsumerExtension.class) @Mixin (ModelPart .class) public class ModelPartMixin implements IAcceleratedRenderer { @Shadow @Final public List cubes; @Unique private final Map meshes = new Object2ObjectOpenHashMap<>(); @Unique private final Map merges = new Object2ObjectOpenHashMap<>(); @Inject( method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;III)V", at = @At("HEAD"), cancellable = true ) public void renderFast( PoseStack poseStack, VertexConsumer buffer, int packedLight, int packedOverlay, int color, CallbackInfo ci ) { var extension = buffer.getAccelerated(); if ( AcceleratedEntityRenderingFeature .isEnabled () && AcceleratedEntityRenderingFeature .shouldUseAcceleratedPipeline () && ( CoreFeature .isRenderingLevel () || ( CoreFeature .isRenderingGui () && AcceleratedEntityRenderingFeature .shouldAccelerateInGui ())) && extension .isAccelerated () ) { ci.cancel(); renderFast( (ModelPart) (Object) this, poseStack, extension, packedLight, packedOverlay, color ); } } @Inject( method = "compile", at = @At("HEAD"), cancellable = true ) public void compileFast( PoseStack.Pose pPose, VertexConsumer pBuffer, int pPackedLight, int pPackedOverlay, int pColor, CallbackInfo ci ) { var extension = pBuffer.getAccelerated(); if ( AcceleratedEntityRenderingFeature .isEnabled () && AcceleratedEntityRenderingFeature .shouldUseAcceleratedPipeline () && ( CoreFeature .isRenderingLevel () || ( CoreFeature .isRenderingGui () && AcceleratedEntityRenderingFeature .shouldAccelerateInGui ())) && extension .isAccelerated () ) { ci .cancel (); extension .doRender ( this, null, pPose.pose (), pPose.normal(), pPackedLight, pPackedOverlay, pColor ); } } @Unique @Override public void render( VertexConsumer vertexConsumer, Void context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { var extension = vertexConsumer.getAccelerated (); var mesh = meshes .get (extension); extension.beginTransform(transform, normal); if (mesh != null) { mesh.write( extension, color, light, overlay ); extension.endTransform(); return; } var culledMeshCollector = new CulledMeshCollector (extension); var meshBuilder = extension.decorate (culledMeshCollector); for (var cube : cubes) { for (var polygon : cube.polygons) { var polygonNormal = polygon.normal; for (var vertex : polygon.vertices) { var vertexPosition = vertex.pos; meshBuilder.addVertex( vertexPosition.x / 16.0f, vertexPosition.y / 16.0f, vertexPosition.z / 16.0f, -1, vertex.u, vertex.v, overlay, 0, polygonNormal.x, polygonNormal.y, polygonNormal.z ); } } } culledMeshCollector.flush(); var data = culledMeshCollector .getData (); var buffer = culledMeshCollector .getBuffer (); mesh = merges .get (data); if (mesh != null) { buffer.discard (); buffer.close (); } else { mesh = AcceleratedEntityRenderingFeature .getMeshType() .getBuilder () .build (culledMeshCollector); } meshes .put (extension, mesh); merges .put (data, mesh); mesh .write ( extension, color, light, overlay ); extension.endTransform(); } @Unique @SuppressWarnings("unchecked") private static void renderFast( ModelPart modelPart, PoseStack poseStack, IAcceleratedVertexConsumer extension, int packedLight, int packedOverlay, int packedColor ) { if (!modelPart.visible) { return; } if ( modelPart.cubes .isEmpty() && modelPart.children .isEmpty() ) { return; } poseStack.pushPose(); modelPart.translateAndRotate(poseStack); if (!modelPart.skipDraw) { var last = poseStack.last(); extension.doRender( (IAcceleratedRenderer) (Object) modelPart, null, last.pose (), last.normal (), packedLight, packedOverlay, packedColor ); } for(var child : modelPart.children.values()) { renderFast( child, poseStack, extension, packedLight, packedOverlay, packedColor ); } poseStack.popPose(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/simplebedrockmodel/mixins/BedrockPartMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.simplebedrockmodel.mixins; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IBufferGraph; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.github.argon4w.acceleratedrendering.core.meshes.IMesh; import com.github.argon4w.acceleratedrendering.core.meshes.collectors.CulledMeshCollector; import com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.github.tartaricacid.simplebedrockmodel.client.bedrock.model.BedrockCube; import com.github.tartaricacid.simplebedrockmodel.client.bedrock.model.BedrockPart; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectList; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.LightTexture; import net.minecraft.util.FastColor; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.joml.Vector3f; import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.Map; @Pseudo @ExtensionMethod(VertexConsumerExtension.class) @Mixin (BedrockPart .class) public class BedrockPartMixin implements IAcceleratedRenderer { @Unique private static final PoseStack.Pose POSE = new PoseStack().last(); @Unique private static final Vector3f[] FIXED_NORMALS = { new Vector3f(-0.0f, -1.0f, -0.0f), new Vector3f(+0.0f, +1.0f, +0.0f), new Vector3f(-0.0f, -0.0f, -1.0f), new Vector3f(+0.0f, +0.0f, +1.0f), new Vector3f(-1.0f, -0.0f, -0.0f), new Vector3f(+1.0f, +0.0f, +0.0f) }; @Shadow @Final public ObjectList cubes; @Unique private final Map meshes = new Object2ObjectOpenHashMap<>(); @Unique private final Map merges = new Object2ObjectOpenHashMap<>(); @Inject(method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;IIFFFF)V", at = @At("HEAD"), cancellable = true) public void renderFast( PoseStack poseStack, VertexConsumer consumer, int lightmap, int overlay, float red, float green, float blue, float alpha, CallbackInfo ci ) { var extension = consumer.getAccelerated(); if ( AcceleratedEntityRenderingFeature .isEnabled () && AcceleratedEntityRenderingFeature .shouldUseAcceleratedPipeline () && ( CoreFeature .isRenderingLevel () || ( CoreFeature .isRenderingGui () && AcceleratedEntityRenderingFeature .shouldAccelerateInGui ())) && extension .isAccelerated () ) { ci.cancel(); renderFast( (BedrockPart) (Object) this, poseStack, extension, lightmap, overlay, FastColor.ARGB32.color( (int) (alpha * 255.0f), (int) (red * 255.0f), (int) (green * 255.0f), (int) (blue * 255.0f) ) ); } } @Inject( method = "compile", at = @At("HEAD"), cancellable = true ) public void compileFast( PoseStack.Pose pose, VertexConsumer consumer, int texU, int texV, float red, float green, float blue, float alpha, CallbackInfo ci ) { var extension = consumer.getAccelerated(); if ( AcceleratedEntityRenderingFeature .isEnabled () && AcceleratedEntityRenderingFeature .shouldUseAcceleratedPipeline () && ( CoreFeature .isRenderingLevel () || ( CoreFeature .isRenderingGui () && AcceleratedEntityRenderingFeature .shouldAccelerateInGui ())) && extension .isAccelerated () ) { ci.cancel(); extension.doRender( this, null, pose.pose (), pose.normal (), texU, texV, FastColor.ARGB32.color ( (int) (alpha * 255.0f), (int) (red * 255.0f), (int) (green * 255.0f), (int) (blue * 255.0f) ) ); } } @Unique @Override public void render( VertexConsumer vertexConsumer, Void context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { var extension = vertexConsumer.getAccelerated (); var mesh = meshes .get (extension); extension.beginTransform(transform, normal); if (mesh != null) { mesh.write( extension, color, light, overlay ); extension.endTransform(); return; } var culledMeshCollector = new CulledMeshCollector (extension); var meshBuilder = extension.decorate (culledMeshCollector); for (var cube : cubes) { cube.compile( POSE, FIXED_NORMALS, meshBuilder, 0, overlay, 1.0f, 1.0f, 1.0f, 1.0f ); } culledMeshCollector.flush(); var data = culledMeshCollector .getData (); var buffer = culledMeshCollector .getBuffer (); mesh = merges .get (data); if (mesh != null) { buffer.discard (); buffer.close (); } else { mesh = AcceleratedEntityRenderingFeature .getMeshType() .getBuilder () .build (culledMeshCollector); } meshes .put (extension, mesh); merges .put (data, mesh); mesh .write ( extension, color, light, overlay ); extension.endTransform(); } @Unique @SuppressWarnings("unchecked") private static void renderFast( BedrockPart bedrockPart, PoseStack poseStack, IAcceleratedVertexConsumer extension, int packedLight, int packedOverlay, int packedColor ) { if (!bedrockPart.visible) { return; } var xNearZero = -1E-5F < bedrockPart.xScale && bedrockPart.xScale < 1E-5F; var yNearZero = -1E-5F < bedrockPart.yScale && bedrockPart.yScale < 1E-5F; var zNearZero = -1E-5F < bedrockPart.zScale && bedrockPart.zScale < 1E-5F; if ((xNearZero && yNearZero) || (xNearZero && zNearZero) || (yNearZero && zNearZero)) { return; } if ( bedrockPart.cubes .isEmpty() && bedrockPart.children.isEmpty() ) { return; } poseStack.pushPose(); bedrockPart.translateAndRotateAndScale(poseStack); var last = poseStack.last(); extension.doRender( (IAcceleratedRenderer) bedrockPart, null, last.pose (), last.normal (), bedrockPart.illuminated ? LightTexture.FULL_BRIGHT : packedLight, packedOverlay, packedColor ); for(var child : bedrockPart.children) { renderFast( child, poseStack, extension, packedLight, packedOverlay, packedColor ); } poseStack.popPose(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/text/AcceleratedBakedGlyphRenderer.java ================================================ package com.github.argon4w.acceleratedrendering.features.text; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IBufferGraph; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.github.argon4w.acceleratedrendering.core.meshes.IMesh; import com.github.argon4w.acceleratedrendering.core.meshes.collectors.SimpleMeshCollector; import com.mojang.blaze3d.vertex.VertexConsumer; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.experimental.ExtensionMethod; import net.minecraft.client.gui.font.glyphs.BakedGlyph; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.joml.Vector2f; import org.joml.Vector3f; import java.util.Map; @ExtensionMethod(VertexConsumerExtension.class) public class AcceleratedBakedGlyphRenderer implements IAcceleratedRenderer { private static final Matrix4f TRANSFORM = new Matrix4f(); private static final Matrix3f NORMAL = new Matrix3f(); private final Map meshes; private final BakedGlyph bakedGlyph; private final boolean italic; public AcceleratedBakedGlyphRenderer(BakedGlyph bakedGlyph, boolean italic) { this.meshes = new Object2ObjectOpenHashMap<>(); this.bakedGlyph = bakedGlyph; this.italic = italic; } @Override public void render( VertexConsumer vertexConsumer, Vector2f context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { var extension = vertexConsumer.getAccelerated (); var mesh = meshes .get (extension); TRANSFORM.set (transform); TRANSFORM.translate ( context.x, context.y, 0.0f ); extension.beginTransform(TRANSFORM, NORMAL); if (mesh != null) { mesh.write( extension, color, light, overlay ); extension.endTransform(); return; } var meshCollector = new SimpleMeshCollector (extension.getLayout()); var meshBuilder = extension.decorate (meshCollector); var italicOffsetUp = italic ? 1.0f - 0.25f * bakedGlyph.up : 0.0f; var italicOffsetDown = italic ? 1.0f - 0.25f * bakedGlyph.down : 0.0f; var positions = new Vector2f[] { new Vector2f(bakedGlyph.left + italicOffsetUp, bakedGlyph.up), new Vector2f(bakedGlyph.left + italicOffsetDown, bakedGlyph.down), new Vector2f(bakedGlyph.right + italicOffsetDown, bakedGlyph.down), new Vector2f(bakedGlyph.right + italicOffsetUp, bakedGlyph.up) }; var texCoords = new Vector2f[] { new Vector2f(bakedGlyph.u0, bakedGlyph.v0), new Vector2f(bakedGlyph.u0, bakedGlyph.v1), new Vector2f(bakedGlyph.u1, bakedGlyph.v1), new Vector2f(bakedGlyph.u1, bakedGlyph.v0), }; for (var i = 0; i < 4; i ++) { var position = new Vector3f(positions[i], 0.0f); var texCoord = texCoords[i]; meshBuilder .addVertex (position) .setColor (-1) .setUv (texCoord.x, texCoord.y) .setLight (0); } mesh = AcceleratedTextRenderingFeature .getMeshType() .getBuilder () .build (meshCollector); meshes .put (extension, mesh); mesh .write ( extension, color, light, overlay ); extension.endTransform(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/text/AcceleratedTextRenderingFeature.java ================================================ package com.github.argon4w.acceleratedrendering.features.text; import com.github.argon4w.acceleratedrendering.configs.FeatureConfig; import com.github.argon4w.acceleratedrendering.configs.FeatureStatus; import com.github.argon4w.acceleratedrendering.configs.PipelineSetting; import com.github.argon4w.acceleratedrendering.core.meshes.MeshType; import java.util.ArrayDeque; import java.util.Deque; public class AcceleratedTextRenderingFeature { private static final Deque PIPELINE_CONTROLLER_STACK = new ArrayDeque<>(); public static boolean isEnabled() { return FeatureConfig.CONFIG.acceleratedTextRenderingFeatureStatus.get() == FeatureStatus.ENABLED; } public static boolean shouldUseAcceleratedPipeline() { return getPipelineSetting() == PipelineSetting.ACCELERATED; } public static MeshType getMeshType() { return FeatureConfig.CONFIG.acceleratedTextRenderingMeshType.get(); } public static void useVanillaPipeline() { PIPELINE_CONTROLLER_STACK.push(PipelineSetting.VANILLA); } public static void forceUseAcceleratedPipeline() { PIPELINE_CONTROLLER_STACK.push(PipelineSetting.ACCELERATED); } public static void forceSetPipeline(PipelineSetting pipeline) { PIPELINE_CONTROLLER_STACK.push(pipeline); } public static void resetPipeline() { PIPELINE_CONTROLLER_STACK.pop(); } public static PipelineSetting getPipelineSetting() { return PIPELINE_CONTROLLER_STACK.isEmpty() ? getDefaultPipelineSetting() : PIPELINE_CONTROLLER_STACK.peek(); } public static PipelineSetting getDefaultPipelineSetting() { return FeatureConfig.CONFIG.acceleratedTextRenderingDefaultPipeline.get(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/text/mixins/BakedGlyphEffectMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.text.mixins; import lombok.EqualsAndHashCode; import net.minecraft.client.gui.font.glyphs.BakedGlyph; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @EqualsAndHashCode @Mixin(BakedGlyph.Effect.class) public class BakedGlyphEffectMixin { @Shadow @Final public float x0; @Shadow @Final public float x1; @Shadow @Final public float y0; @Shadow @Final public float y1; @Shadow @Final public float depth; } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/text/mixins/BakedGlyphMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.text.mixins; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IBufferGraph; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.github.argon4w.acceleratedrendering.core.meshes.IMesh; import com.github.argon4w.acceleratedrendering.core.meshes.collectors.SimpleMeshCollector; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.github.argon4w.acceleratedrendering.features.text.AcceleratedBakedGlyphRenderer; import com.github.argon4w.acceleratedrendering.features.text.AcceleratedTextRenderingFeature; import com.mojang.blaze3d.vertex.VertexConsumer; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.experimental.ExtensionMethod; import net.minecraft.client.gui.font.glyphs.BakedGlyph; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.util.FastColor; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.joml.Vector2f; import org.joml.Vector3f; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.Map; @ExtensionMethod(value = VertexConsumerExtension.class) @Mixin (value = BakedGlyph .class, priority = Integer.MIN_VALUE) public class BakedGlyphMixin implements IAcceleratedRenderer { @Shadow @Final public float u0; @Shadow @Final public float v0; @Shadow @Final public float u1; @Shadow @Final public float v1; @Unique private static final Matrix3f NORMAL = new Matrix3f(); @Unique private final AcceleratedBakedGlyphRenderer normalRenderer = new AcceleratedBakedGlyphRenderer ((BakedGlyph) (Object) this, false); @Unique private final AcceleratedBakedGlyphRenderer italicRenderer = new AcceleratedBakedGlyphRenderer ((BakedGlyph) (Object) this, true); @Unique private final Map> effectMeshes = new Object2ObjectOpenHashMap<> (); @Inject( method = "render", at = @At("HEAD"), cancellable = true ) public void renderFast( boolean pItalic, float pX, float pY, Matrix4f pMatrix, VertexConsumer pBuffer, float pRed, float pGreen, float pBlue, float pAlpha, int pPackedLight, CallbackInfo ci ) { var extension = pBuffer.getAccelerated(); if ( AcceleratedTextRenderingFeature .isEnabled () && AcceleratedTextRenderingFeature .shouldUseAcceleratedPipeline () && ( CoreFeature .isRenderingLevel () || CoreFeature .isRenderingGui ()) && extension .isAccelerated () ) { ci .cancel (); extension .doRender ( pItalic ? italicRenderer : normalRenderer, new Vector2f(pX, pY), pMatrix, null, pPackedLight, OverlayTexture .NO_OVERLAY, FastColor.ARGB32.color( (int) (pAlpha * 255.0f), (int) (pRed * 255.0f), (int) (pGreen * 255.0f), (int) (pBlue * 255.0f) ) ); } } @Inject( method = "renderEffect", at = @At("HEAD"), cancellable = true ) public void renderEffectFast( BakedGlyph.Effect effect, Matrix4f matrix, VertexConsumer buffer, int packedLight, CallbackInfo ci ) { var extension = buffer.getAccelerated(); if ( AcceleratedTextRenderingFeature .isEnabled () && AcceleratedTextRenderingFeature .shouldUseAcceleratedPipeline () && ( CoreFeature .isRenderingLevel () || CoreFeature .isRenderingGui ()) && extension .isAccelerated () ) { ci .cancel (); extension .doRender ( this, effect, matrix, NORMAL, packedLight, OverlayTexture .NO_OVERLAY, FastColor.ARGB32.color( (int) (effect.a * 255.0f), (int) (effect.r * 255.0f), (int) (effect.g * 255.0f), (int) (effect.b * 255.0f) ) ); } } @Unique @Override public void render( VertexConsumer vertexConsumer, BakedGlyph.Effect context, Matrix4f transform, Matrix3f normal, int light, int overlay, int color ) { var extension = vertexConsumer.getAccelerated (); var meshes = effectMeshes .get (context); extension.beginTransform(transform, normal); if (meshes == null) { meshes = new Object2ObjectOpenHashMap<> (); effectMeshes.put (context, meshes); } var mesh = meshes.get(extension); if (mesh != null) { mesh.write( extension, color, light, overlay ); extension.endTransform(); return; } var meshCollector = new SimpleMeshCollector (extension.getLayout()); var meshBuilder = extension.decorate (meshCollector); var positions = new Vector2f[] { new Vector2f(context.x0, context.y0), new Vector2f(context.x1, context.y0), new Vector2f(context.x1, context.y1), new Vector2f(context.x0, context.y1), }; var texCoords = new Vector2f[] { new Vector2f(u0, v0), new Vector2f(u0, v1), new Vector2f(u1, v1), new Vector2f(u1, v0), }; for (var i = 0; i < 4; i ++) { var position = new Vector3f(positions[i], context.depth); var texCoord = texCoords[i]; meshBuilder .addVertex (position) .setColor (-1) .setUv (texCoord.x, texCoord.y) .setLight (0); } mesh = AcceleratedTextRenderingFeature .getMeshType() .getBuilder () .build (meshCollector); meshes .put (extension, mesh); mesh .write ( extension, color, light, overlay ); extension.endTransform(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/touhoulittlemaid/mixins/GeoBoneMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.touhoulittlemaid.mixins; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IBufferGraph; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.github.argon4w.acceleratedrendering.core.meshes.IMesh; import com.github.argon4w.acceleratedrendering.core.meshes.collectors.CulledMeshCollector; import com.github.argon4w.acceleratedrendering.core.meshes.data.MeshData; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.github.tartaricacid.touhoulittlemaid.geckolib3.geo.render.built.GeoBone; import com.github.tartaricacid.touhoulittlemaid.geckolib3.geo.render.built.GeoMesh; import com.mojang.blaze3d.vertex.VertexConsumer; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.experimental.ExtensionMethod; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.joml.Vector2i; import org.joml.Vector3f; import org.spongepowered.asm.mixin.*; import java.util.Map; @Pseudo @ExtensionMethod(VertexConsumerExtension.class) @Mixin (GeoBone .class) public class GeoBoneMixin implements IAcceleratedRenderer { @Shadow @Final private GeoMesh cubes; @Unique private final Map meshes = new Object2ObjectOpenHashMap<>(); @Unique private final Map merges = new Object2ObjectOpenHashMap<>(); @Unique @Override public void render( VertexConsumer vertexConsumer, Void context, Matrix4f transformMatrix, Matrix3f normalMatrix, int light, int overlay, int color ) { var extension = vertexConsumer.getAccelerated (); var mesh = meshes .get (extension); extension.beginTransform(transformMatrix, normalMatrix); if (mesh != null) { mesh.write( extension, color, light, overlay ); extension.endTransform(); return; } var culledMeshCollector = new CulledMeshCollector (extension); var meshBuilder = extension.decorate (culledMeshCollector); for(int i = 0; i < cubes.getCubeCount(); ++i) { var deltaX = new Vector3f (cubes.dx(i)); var deltaY = new Vector3f (cubes.dy(i)); var deltaZ = new Vector3f (cubes.dz(i)); var p000 = new Vector3f (cubes.position(i)); var p100 = p000 .add (deltaX, new Vector3f()); var p110 = p100 .add (deltaY, new Vector3f()); var p010 = p000 .add (deltaY, new Vector3f()); var p001 = p000 .add (deltaZ, new Vector3f()); var p101 = p100 .add (deltaZ, new Vector3f()); var p111 = p110 .add (deltaZ, new Vector3f()); var p011 = p010 .add (deltaZ, new Vector3f()); var positiveNormalZ = deltaX.cross (deltaY, new Vector3f()).normalize(); var positiveNormalX = deltaY.cross (deltaZ, new Vector3f()).normalize(); var positiveNormalY = deltaZ.cross (deltaX, new Vector3f()).normalize(); var faces = cubes .faces (i); var mirrored = (faces & 64) != 0; if (mirrored) { positiveNormalX.mul(-1.0F); positiveNormalY.mul(-1.0F); positiveNormalZ.mul(-1.0F); } var negativeNormalX = positiveNormalX.negate(new Vector3f()); var negativeNormalY = positiveNormalY.negate(new Vector3f()); var negativeNormalZ = positiveNormalZ.negate(new Vector3f()); var positions = new Vector3f[][] { {p101, p001, p000, p100}, {p110, p010, p011, p111}, {p100, p000, p010, p110}, {p001, p101, p111, p011}, {p000, p001, p011, p010}, {p101, p100, p110, p111} }; var texCoords = new float[][] { {cubes.downU0 (i), cubes.downU1 (i), cubes.downV0 (i), cubes.downV1 (i)}, {cubes.upU0 (i), cubes.upU1 (i), cubes.upV0 (i), cubes.upV1 (i)}, {cubes.northU0 (i), cubes.northU1 (i), cubes.northV0 (i), cubes.northV1 (i)}, {cubes.southU0 (i), cubes.southU1 (i), cubes.southV0 (i), cubes.southV1 (i)}, {cubes.westU0 (i), cubes.westU1 (i), cubes.westV0 (i), cubes.westV1 (i)}, {cubes.eastU0 (i), cubes.eastU1 (i), cubes.eastV0 (i), cubes.eastV1 (i)}, }; var texOrders = new Vector2i[] { new Vector2i(0, 3), new Vector2i(1, 3), new Vector2i(1, 2), new Vector2i(0, 2) }; var normals = new Vector3f[] { negativeNormalY, positiveNormalY, negativeNormalZ, positiveNormalZ, negativeNormalX, positiveNormalX, }; for (var j = 0; j < 6; j ++) { if ((faces & (1 << j)) != 0) { for (var k = 0; k < 4; k ++) { var position = positions [j][k]; var texCoord = texCoords [j]; var texOrder = texOrders [k]; var normal = normals [j]; meshBuilder.addVertex( position.x, position.y, position.z, -1, texCoord[texOrder.x], texCoord[texOrder.y], overlay, 0, normal.x, normal.y, normal.z ); } } } } culledMeshCollector.flush(); var data = culledMeshCollector .getData (); var buffer = culledMeshCollector .getBuffer (); mesh = merges .get (data); if (mesh != null) { buffer.discard (); buffer.close (); } else { mesh = AcceleratedEntityRenderingFeature .getMeshType() .getBuilder () .build (culledMeshCollector); } meshes .put (extension, mesh); merges .put (data, mesh); mesh .write ( extension, color, light, overlay ); extension.endTransform(); } } ================================================ FILE: src/main/java/com/github/argon4w/acceleratedrendering/features/touhoulittlemaid/mixins/IGeoRendererMixin.java ================================================ package com.github.argon4w.acceleratedrendering.features.touhoulittlemaid.mixins; import com.github.argon4w.acceleratedrendering.core.CoreFeature; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.IAcceleratedVertexConsumer; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.builders.VertexConsumerExtension; import com.github.argon4w.acceleratedrendering.core.buffers.accelerated.renderers.IAcceleratedRenderer; import com.github.argon4w.acceleratedrendering.features.entities.AcceleratedEntityRenderingFeature; import com.github.tartaricacid.touhoulittlemaid.geckolib3.geo.IGeoRenderer; import com.github.tartaricacid.touhoulittlemaid.geckolib3.geo.animated.AnimatedGeoBone; import com.github.tartaricacid.touhoulittlemaid.geckolib3.util.RenderUtils; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.experimental.ExtensionMethod; import net.minecraft.client.renderer.LightTexture; import net.minecraft.util.FastColor; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Pseudo @ExtensionMethod(VertexConsumerExtension.class) @Mixin (IGeoRenderer .class) public interface IGeoRendererMixin { @Inject( method = "renderRecursively", at = @At("HEAD"), cancellable = true ) default void renderRecursivelyFast( AnimatedGeoBone bone, PoseStack poseStack, VertexConsumer buffer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha, CallbackInfo ci ) { var extension = buffer.getAccelerated(); if ( AcceleratedEntityRenderingFeature .isEnabled () && AcceleratedEntityRenderingFeature .shouldUseAcceleratedPipeline () && ( CoreFeature .isRenderingLevel () || ( CoreFeature .isRenderingGui () && AcceleratedEntityRenderingFeature .shouldAccelerateInGui ())) && extension .isAccelerated () ) { ci.cancel(); renderRecursivelyFast( bone, poseStack, extension, packedLight, packedOverlay, FastColor.ARGB32.color( (int) (alpha * 255.0f), (int) (red * 255.0f), (int) (green * 255.0f), (int) (blue * 255.0f) ) ); } } @SuppressWarnings ("unchecked") @WrapOperation ( method = "renderRecursively", at = @At( value = "INVOKE", target = "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" ) ) default boolean renderBoneFast( AnimatedGeoBone bone, PoseStack poseStack, VertexConsumer buffer, int cubePackedLight, int packedOverlay, float red, float green, float blue, float alpha, Operation original ) { var extension = buffer.getAccelerated(); if ( AcceleratedEntityRenderingFeature .isEnabled () && AcceleratedEntityRenderingFeature .shouldUseAcceleratedPipeline () && ( CoreFeature .isRenderingLevel () || ( CoreFeature .isRenderingGui () && AcceleratedEntityRenderingFeature .shouldAccelerateInGui ())) && extension .isAccelerated () ) { if ( !bone.isHidden () && !bone.cubesAreHidden() ) { var last = poseStack.last(); extension.doRender( (IAcceleratedRenderer) bone.geoBone(), null, last.pose (), last.normal (), cubePackedLight, packedOverlay, FastColor.ARGB32.color( (int) (alpha * 255.0f), (int) (red * 255.0f), (int) (green * 255.0f), (int) (blue * 255.0f) ) ); } return true; } return original.call( bone, poseStack, buffer, cubePackedLight, packedOverlay, red, green, blue, alpha ); } @Unique @SuppressWarnings("unchecked") private static void renderRecursivelyFast( AnimatedGeoBone animated, PoseStack poseStack, IAcceleratedVertexConsumer extension, int packedLight, int packedOverlay, int packedColor ) { if ( (animated.getScaleX() == 0.0F ? 0 : 1) + (animated.getScaleY() == 0.0F ? 0 : 1) + (animated.getScaleZ() == 0.0F ? 0 : 1) >= 2 ) { poseStack.pushPose(); RenderUtils.prepMatrixForBone(poseStack, animated); if ( !animated.isHidden () && !animated.cubesAreHidden() ) { var last = poseStack.last (); var bone = animated .geoBone(); extension.doRender( (IAcceleratedRenderer) bone, null, last.pose (), last.normal (), bone.glow () ? LightTexture.FULL_BRIGHT : packedLight, packedOverlay, packedColor ); } if (!animated.childBonesAreHiddenToo()) { for(var childBone : animated.children()) { renderRecursivelyFast( childBone, poseStack, extension, packedLight, packedOverlay, packedColor ); } } poseStack.popPose(); } } } ================================================ FILE: src/main/resources/META-INF/accesstransformer.cfg ================================================ # Core public net.minecraft.client.renderer.OutlineBufferSource$EntityOutlineGenerator public net.minecraft.client.renderer.RenderType$CompositeState texturingState # ModelPart public net.minecraft.client.model.geom.ModelPart cubes public net.minecraft.client.model.geom.ModelPart children # Mesh caching public net.minecraft.client.model.geom.ModelPart$Cube polygons public net.minecraft.client.model.geom.ModelPart$Polygon public net.minecraft.client.model.geom.ModelPart$Vertex # For Texture based pre-render culling and gpu-based culling public net.minecraft.client.renderer.RenderType$CompositeRenderType public net.minecraft.client.renderer.RenderType$CompositeRenderType state # Texture based pre-render culling public net.minecraft.client.renderer.RenderType$CompositeState textureState public net.minecraft.client.renderer.RenderStateShard$EmptyTextureStateShard cutoutTexture()Ljava/util/Optional; public net.minecraft.client.renderer.RenderStateShard$TextureStateShard cutoutTexture()Ljava/util/Optional; public net.minecraft.client.renderer.RenderStateShard$MultiTextureStateShard cutoutTexture()Ljava/util/Optional; # GPU based culling public net.minecraft.client.renderer.RenderType$CompositeState cullState public net.minecraft.client.renderer.RenderStateShard$BooleanStateShard enabled # Text Rendering public net.minecraft.client.gui.font.glyphs.BakedGlyph u0 public net.minecraft.client.gui.font.glyphs.BakedGlyph u1 public net.minecraft.client.gui.font.glyphs.BakedGlyph v0 public net.minecraft.client.gui.font.glyphs.BakedGlyph v1 public net.minecraft.client.gui.font.glyphs.BakedGlyph left public net.minecraft.client.gui.font.glyphs.BakedGlyph right public net.minecraft.client.gui.font.glyphs.BakedGlyph up public net.minecraft.client.gui.font.glyphs.BakedGlyph down public net.minecraft.client.gui.font.glyphs.BakedGlyph$Effect x0 public net.minecraft.client.gui.font.glyphs.BakedGlyph$Effect y0 public net.minecraft.client.gui.font.glyphs.BakedGlyph$Effect x1 public net.minecraft.client.gui.font.glyphs.BakedGlyph$Effect y1 public net.minecraft.client.gui.font.glyphs.BakedGlyph$Effect depth public net.minecraft.client.gui.font.glyphs.BakedGlyph$Effect r public net.minecraft.client.gui.font.glyphs.BakedGlyph$Effect g public net.minecraft.client.gui.font.glyphs.BakedGlyph$Effect b public net.minecraft.client.gui.font.glyphs.BakedGlyph$Effect a # Item Rendering public net.minecraft.client.gui.GuiGraphics renderItem(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;IIII)V public net.minecraft.world.inventory.AbstractContainerMenu menuType public net.minecraft.client.gui.GuiGraphics innerBlit(Lnet/minecraft/resources/ResourceLocation;IIIIIFFFFFFFF)V public net.minecraft.client.renderer.RenderStateShard$WriteMaskStateShard writeColor public net.minecraft.client.renderer.RenderStateShard$WriteMaskStateShard writeDepth public net.minecraft.client.renderer.RenderType$CompositeState shaderState public net.minecraft.client.renderer.RenderType$CompositeState transparencyState public net.minecraft.client.renderer.RenderType$CompositeState depthTestState public net.minecraft.client.renderer.RenderType$CompositeState cullState public net.minecraft.client.renderer.RenderType$CompositeState lightmapState public net.minecraft.client.renderer.RenderType$CompositeState overlayState public net.minecraft.client.renderer.RenderType$CompositeState layeringState public net.minecraft.client.renderer.RenderType$CompositeState outputState public net.minecraft.client.renderer.RenderType$CompositeState texturingState public net.minecraft.client.renderer.RenderType$CompositeState writeMaskState public net.minecraft.client.renderer.RenderType$CompositeState lineState public net.minecraft.client.renderer.RenderType$CompositeState colorLogicState public net.minecraft.client.renderer.RenderType$CompositeState outlineProperty # Scissor State public net.minecraft.client.gui.GuiGraphics scissorStack public net.minecraft.client.gui.GuiGraphics$ScissorStack public net.minecraft.client.gui.GuiGraphics$ScissorStack stack ================================================ FILE: src/main/resources/META-INF/neoforge.mods.toml ================================================ # This is an example neoforge.mods.toml file. It contains the data relating to the loading mods. # There are several mandatory fields (#mandatory), and many more that are optional (#optional). # The overall format is standard TOML format, v0.5.0. # Note that there are a couple of TOML lists in this file. # Find more information on toml format here: https://github.com/toml-lang/toml # The name of the mod loader type to load - for regular FML @Mod mods it should be javafml modLoader="javafml" #mandatory # A version range to match for said mod loader - for regular FML @Mod it will be the FML version. This is currently 2. loaderVersion="${loader_version_range}" #mandatory # The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. # Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. license="${mod_license}" # A URL to refer people to when problems occur with this mod issueTrackerURL="https://github.com/Argon4W/AcceleratedRendering/issues" #optional # A list of mods - how many allowed here is determined by the individual mod loader [[mods]] #mandatory # The modid of the mod modId="${mod_id}" #mandatory # The version number of the mod version="${mod_version}" #mandatory # A display name for the mod displayName="${mod_name}" #mandatory # A URL to query for updates for this mod. See the JSON update specification https://docs.neoforged.net/docs/misc/updatechecker/ #updateJSONURL="https://change.me.example.invalid/updates.json" #optional # A URL for the "homepage" for this mod, displayed in the mod UI displayURL="https://github.com/Argon4W/AcceleratedRendering" #optional # A file name (in the root of the mod JAR) containing a logo for display logoFile="logo.png" #optional # A text field displayed in the mod UI #credits="" #optional # A text field displayed in the mod UI authors="${mod_authors}" #optional # The description text for the mod (multi line!) (#mandatory) description='''${mod_description}''' # The [[mixins]] block allows you to declare your mixin config to FML so that it gets loaded. # Accelerated Rendering Core Mixins # Provides core functions to make Accelerated Rendering works. [[mixins]] config="${mod_id}.core.mixins.json" # Accelerated Rendering Compatibility Feature Mixins # Provides shaders and post processings that supports modified vertex formats by Iris Shaders [[mixins]] config="${mod_id}.compat.iris.mixins.json" # Immediately Fast Compatibility Feature Mixins # Provides comparibility of Accelerated Rendering to BatchableBufferSource in Immediately Fast. [[mixins]] config="${mod_id}.compat.immediatelyfast.mixins.json" # Accelerated Rendering Curios Compatibility Feature Mixins # Provides compatibility features that prevents some bad rendering code from breaking Accelerated Rendering. [[mixins]] config="${mod_id}.compat.curios.mixins.json" # Accelerated Entity Rendering Feature Mixins # Provides basic entity acceleration feature controllers and entity shadows acceleration. [[mixins]] config="${mod_id}.feature.entities.mixins.json" # Accelerated Entity ModelPart Rendering Feature Mixins # Accelerates the rendering of vanilla entities or modded vanilla-Like entities that uses ModelPart. [[mixins]] config="${mod_id}.feature.modelparts.mixins.json" # Accelerated Item Rendering Feature Mixins # Accelerates the rendering of simple item models that use BakedModel/BakedQuads and provides acceleration feature controller of them. [[mixins]] config="${mod_id}.feature.items.mixins.json" # Accelerated Text Rendering Feature Mixins # Accekerates the rendering of BakedGlyph which is the most common way of rendering text in Minecraft and provides acceleration feature controller of them. [[mixins]] config="${mod_id}.feature.text.mixins.json" # Filter Feature Mixins # Prevent specific entities/block entities from being accelerated when rendering to achieve better compatibility. [[mixins]] config="${mod_id}.feature.filter.mixins.json" # Simple Bedrock Model Acceleration Feature Mixins # Accelerates the rendering of entities that uses BedrockPart provided by the SimpleBedrockModel such as older version model in Touhou Little Maid. [[mixins]] config="${mod_id}.feature.simplebedrockmodel.mixins.json" # Touhou Little Maid Acceleration Feature Mixins # Accelerates the rendering of maids in Touhou Little Maid that uses modified version of the GeckoLib. [[mixins]] config="${mod_id}.feature.touhoulittlemaid.mixins.json" # FTB Library Acceleration Feature Mixins # Batch the rendering of items in GUI screens provided by mods like FTB Quests. [[mixins]] config="${mod_id}.feature.ftb.mixins.json" # Geckolib Acceleration Feature Mixins # Accelerated the rendering of entities and block entities that uses the GeoBone provided by GeckoLib. [[mixins]] config="${mod_id}.feature.geckolib.mixins.json" # Entity Model Feature Acceleration Feature Mixins # Entity Model Feature modifies and uses its own compile method same as vanilla ModelPart so it has to be injected manully to be accelerated. [[mixins]] config="${mod_id}.feature.entitymodelfeature.mixins.json" # The [[accessTransformers]] block allows you to declare where your AT file is. # If this block is omitted, a fallback attempt will be made to load an AT from META-INF/accesstransformer.cfg #[[accessTransformers]] #file="META-INF/accesstransformer.cfg" # The coremods config file path is not configurable and is always loaded from META-INF/coremods.json # A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. [[dependencies.${mod_id}]] #optional # the modid of the dependency modId="neoforge" #mandatory # The type of the dependency. Can be one of "required", "optional", "incompatible" or "discouraged" (case insensitive). # 'required' requires the mod to exist, 'optional' does not # 'incompatible' will prevent the game from loading when the mod exists, and 'discouraged' will show a warning type="required" #mandatory # Optional field describing why the dependency is required or why it is incompatible # reason="..." # The version range of the dependency versionRange="${neo_version_range}" #mandatory # An ordering relationship for the dependency. # BEFORE - This mod is loaded BEFORE the dependency # AFTER - This mod is loaded AFTER the dependency ordering="NONE" # Side this dependency is applied on - BOTH, CLIENT, or SERVER side="CLIENT" # Here's another dependency [[dependencies.${mod_id}]] # the modid of the dependency modId="minecraft" # The type of the dependency. Can be one of "required", "optional", "incompatible" or "discouraged" (case insensitive). # 'required' requires the mod to exist, 'optional' does not # 'incompatible' will prevent the game from loading when the mod exists, and 'discouraged' will show a warning type="required" # Optional field describing why the dependency is required or why it is incompatible # reason="..." # The version range of the dependency # This version range declares a minimum of the current minecraft version up to but not including the next major version versionRange="${minecraft_version_range}" # An ordering relationship for the dependency. # BEFORE - This mod is loaded BEFORE the dependency # AFTER - This mod is loaded AFTER the dependency ordering="NONE" # Side this dependency is applied on - BOTH, CLIENT, or SERVER side="CLIENT" # Features are specific properties of the game environment, that you may want to declare you require. This example declares # that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't # stop your mod loading on the server for example. [features.${mod_id}] openGLVersion="[4.6,)" ================================================ FILE: src/main/resources/acceleratedrendering.compat.curios.mixins.json ================================================ { "required": true, "minVersion": "0.8", "package": "com.github.argon4w.acceleratedrendering.compat.curios.mixins", "compatibilityLevel": "JAVA_21", "client": [ "CuriosLayerMixin" ], "injectors": { "defaultRequire": 1 } } ================================================ FILE: src/main/resources/acceleratedrendering.compat.immediatelyfast.mixins.json ================================================ { "required": true, "minVersion": "0.8", "package": "com.github.argon4w.acceleratedrendering.compat.immediatelyfast.mixins", "compatibilityLevel": "JAVA_21", "client": [ "BatchableBufferSourceMixin", "BatchingBuffersMixin", "WrappedRenderLayerMixin" ], "injectors": { "defaultRequire": 1 } } ================================================ FILE: src/main/resources/acceleratedrendering.compat.iris.mixins.json ================================================ { "required": true, "minVersion": "0.8", "package": "com.github.argon4w.acceleratedrendering.compat.iris.mixins", "compatibilityLevel": "JAVA_21", "plugin": "com.github.argon4w.acceleratedrendering.compat.iris.mixins.plugin.IrisCompatMixinPlugin", "client": [ "acceleratedrendering.AcceleratedBufferBuilderMixin", "acceleratedrendering.AcceleratedBufferSourceMixin", "acceleratedrendering.AcceleratedRenderingModEntryMixin", "acceleratedrendering.CoreBuffersProviderMixin", "acceleratedrendering.FlattenMeshInfoCacheMixin", "acceleratedrendering.IBufferEnvironmentPresetsMixin", "acceleratedrendering.SimpleMeshInfoMixin", "acceleratedrendering.MeshUploaderMixin", "acceleratedrendering.MeshUploadingProgramDispatcherMixin", "acceleratedrendering.RenderTypeUtilsMixin", "acceleratedrendering.SimpleMeshInfoCacheMixin", "acceleratedrendering.UnsafeMemoryMeshInfoCacheMixin", "iris.FullyBufferedMultiBufferSourceMixin", "iris.HandRendererMixin", "iris.IrisVertexFormatsMixin", "iris.ModelToEntityVertexSerializerMixin", "iris.ShadowRendererMixin", "vanilla.LevelRendererMixin" ], "injectors": { "defaultRequire": 1 } } ================================================ FILE: src/main/resources/acceleratedrendering.core.mixins.json ================================================ { "required": true, "minVersion": "0.8", "package": "com.github.argon4w.acceleratedrendering.core.mixins", "compatibilityLevel": "JAVA_21", "client": [ "buffers.BufferBuilderMixin", "buffers.BufferSourceMixin", "buffers.EntityOutlineGeneratorMixin", "buffers.MinecraftMixin", "buffers.OutlineBufferSourceMixin", "buffers.SheetedDecalTextureGeneratorMixin", "buffers.SpriteCoordinateExpanderMixin", "buffers.VertexConsumerMixin", "buffers.VertexDoubleConsumerMixin", "buffers.VertexMultipleConsumerMixin", "compatibility.MinecraftMixin", "compatibility.ParticleEngineMixin", "compatibility.RenderTypeMixin", "compatibility.WindowMixin", "GameRendererMixin", "LevelRendererMixin" ], "injectors": { "defaultRequire": 1 } } ================================================ FILE: src/main/resources/acceleratedrendering.feature.entities.mixins.json ================================================ { "required": true, "minVersion": "0.8", "package": "com.github.argon4w.acceleratedrendering.features.entities.mixins", "compatibilityLevel": "JAVA_21", "client": [ "EntityRenderDispatcherMixin", "InventoryScreenMixin" ], "injectors": { "defaultRequire": 1 } } ================================================ FILE: src/main/resources/acceleratedrendering.feature.entitymodelfeature.mixins.json ================================================ { "required": true, "minVersion": "0.8", "package": "com.github.argon4w.acceleratedrendering.features.emf.mixins", "compatibilityLevel": "JAVA_21", "client": [ "EMFModelPartMixin", "EMFModelPartWithStateMixin" ], "injectors": { "defaultRequire": 1 } } ================================================ FILE: src/main/resources/acceleratedrendering.feature.filter.mixins.json ================================================ { "required": true, "minVersion": "0.8", "package": "com.github.argon4w.acceleratedrendering.features.filter.mixins", "compatibilityLevel": "JAVA_21", "client": [ "AbstractContainerScreenMixin", "BlockEntityRenderDispatcherMixin", "ClientHooksMixin", "ItemRendererMixin", "LevelRendererMixin" ], "injectors": { "defaultRequire": 1 } } ================================================ FILE: src/main/resources/acceleratedrendering.feature.ftb.mixins.json ================================================ { "required": true, "minVersion": "0.8", "package": "com.github.argon4w.acceleratedrendering.features.ftb.mixins", "compatibilityLevel": "JAVA_21", "client": [ "BaseScreenMixin" ], "injectors": { "defaultRequire": 1 } } ================================================ FILE: src/main/resources/acceleratedrendering.feature.geckolib.mixins.json ================================================ { "required": true, "minVersion": "0.8", "package": "com.github.argon4w.acceleratedrendering.features.geckolib.mixins", "compatibilityLevel": "JAVA_21", "client": [ "GeoBoneMixin", "GeoRendererMixin" ], "injectors": { "defaultRequire": 1 } } ================================================ FILE: src/main/resources/acceleratedrendering.feature.items.mixins.json ================================================ { "required": true, "minVersion": "0.8", "package": "com.github.argon4w.acceleratedrendering.features.items.mixins", "compatibilityLevel": "JAVA_21", "client": [ "accessors.BlockColorsAccessor", "accessors.ItemColorsAccessor", "compatibility.ClientHooksMixin", "compatibility.GuiLayerManagerMixin", "gui.AbstractContainerScreenMixin", "gui.FontMixin", "gui.GuiGraphicsMixin", "gui.GuiMixin", "models.BakedCompositeModelMixin", "models.BakedModelMixin", "models.BakedQuadMixin", "models.BakedSeparateTransformsModelMixin", "models.MultipartBakedModelMixin", "models.SimpleBakedModelMixin", "models.WeightedBakedModelMixin", "ItemRendererMixin", "ModelBlockRendererMixin" ], "injectors": { "defaultRequire": 1 } } ================================================ FILE: src/main/resources/acceleratedrendering.feature.modelparts.mixins.json ================================================ { "required": true, "minVersion": "0.8", "package": "com.github.argon4w.acceleratedrendering.features.modelparts.mixins", "compatibilityLevel": "JAVA_21", "client": [ "ModelPartMixin" ], "injectors": { "defaultRequire": 1 } } ================================================ FILE: src/main/resources/acceleratedrendering.feature.simplebedrockmodel.mixins.json ================================================ { "required": true, "minVersion": "0.8", "package": "com.github.argon4w.acceleratedrendering.features.simplebedrockmodel.mixins", "compatibilityLevel": "JAVA_21", "client": [ "BedrockPartMixin" ], "injectors": { "defaultRequire": 1 } } ================================================ FILE: src/main/resources/acceleratedrendering.feature.text.mixins.json ================================================ { "required": true, "minVersion": "0.8", "package": "com.github.argon4w.acceleratedrendering.features.text.mixins", "compatibilityLevel": "JAVA_21", "client": [ "BakedGlyphEffectMixin", "BakedGlyphMixin" ], "injectors": { "defaultRequire": 1 } } ================================================ FILE: src/main/resources/acceleratedrendering.feature.touhoulittlemaid.mixins.json ================================================ { "required": true, "minVersion": "0.8", "package": "com.github.argon4w.acceleratedrendering.features.touhoulittlemaid.mixins", "compatibilityLevel": "JAVA_21", "client": [ "GeoBoneMixin", "IGeoRendererMixin" ], "injectors": { "defaultRequire": 1 } } ================================================ FILE: src/main/resources/assets/acceleratedrendering/lang/en_us.json ================================================ { "acceleratedrendering.configuration.title": "Accelerated Rendering Configurations", "acceleratedrendering.configuration.section.acceleratedrendering.client.toml.title": "Accelerated Rendering Client Configurations", "acceleratedrendering.configuration.section.acceleratedrendering.client.toml": "Configurations of features provided by Accelerated Rendering", "acceleratedrendering.configuration.core_settings": "Core Settings", "acceleratedrendering.configuration.core_settings.tooltip": "Core Settings allows you to change setting that are related to all rendering features.", "acceleratedrendering.configuration.core_settings.pooled_ring_buffer_size": "Maximum Pooled Ring Buffer Size", "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.", "acceleratedrendering.configuration.core_settings.pooled_batching_size": "Maximum Pooled Batching Size", "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.", "acceleratedrendering.configuration.core_settings.cached_image_size": "Maximum Cached Image Size", "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.", "acceleratedrendering.configuration.core_settings.dynamic_uv_resolution": "Dynamic Render Type Cache UV Resolution", "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.", "acceleratedrendering.configuration.core_settings.debug_context": "Enable Debug Context", "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.", "acceleratedrendering.configuration.core_settings.force_translucent_acceleration": "Enable Force Translucent Acceleration", "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.", "acceleratedrendering.configuration.core_settings.cache_identical_pose": "Enable Cache Identical Pose", "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.", "acceleratedrendering.configuration.core_settings.mesh_info_cache_type": "Mesh Instance Info Cache Type", "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.", "acceleratedrendering.configuration.core_settings.layer_storage_type": "Batching Layer Storage Type", "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.", "acceleratedrendering.configuration.core_settings.mesh_merge_type": "Mesh Merge Type", "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.", "acceleratedrendering.configuration.core_settings.upload_mesh_immediately": "Enable Uploading Mesh Immediately", "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.", "acceleratedrendering.configuration.core_settings.cache_dynamic_render_type": "Enable Cache Dynamic Render Type", "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.", "acceleratedrendering.configuration.core_settings.viewport_binding_state": "Viewport Restoring Type", "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.", "acceleratedrendering.configuration.core_settings.scissor_binding_state": "Scissor Restoring Type", "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.", "acceleratedrendering.configuration.core_settings.button": "Configure", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring": "Block Buffer Restoring Settings", "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.", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.feature_status": "Enable Block Buffer Restoring", "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.", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.binding_cache_type": "Block Buffer Binding Cache Type", "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.", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.shader_storage_type": "Shader Storage Buffer Restoring Type", "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.", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.atomic_counter_type": "Atomic Counter Buffer Restoring Type", "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.", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.shader_storage_range": "Shader Storage Buffer Restoring Range", "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.", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.atomic_counter_range": "Atomic Counter Buffer Restoring Range", "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.", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.button": "Configure", "acceleratedrendering.configuration.accelerated_entity_rendering": "Accelerated Entity Rendering Settings", "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.", "acceleratedrendering.configuration.accelerated_entity_rendering.feature_status": "Enable Accelerated Entity Rendering", "acceleratedrendering.configuration.accelerated_entity_rendering.feature_status.tooltip": "- DISABLED: Disable accelerated entity rendering.\n- ENABLED: Enable accelerated entity rendering.", "acceleratedrendering.configuration.accelerated_entity_rendering.default_pipeline": "Default Rendering Pipeline", "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.", "acceleratedrendering.configuration.accelerated_entity_rendering.mesh_type": "Cached Mesh Type", "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.", "acceleratedrendering.configuration.accelerated_entity_rendering.gui_acceleration": "Enable GUI Acceleration", "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.", "acceleratedrendering.configuration.accelerated_entity_rendering.button": "Configure", "acceleratedrendering.configuration.accelerated_item_rendering": "Accelerated Item Rendering Settings", "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.", "acceleratedrendering.configuration.accelerated_item_rendering.feature_status": "Enable Accelerated Item Rendering", "acceleratedrendering.configuration.accelerated_item_rendering.feature_status.tooltip": "- DISABLED: Disable accelerated item rendering.\n- ENABLED: Enable accelerated item rendering.", "acceleratedrendering.configuration.accelerated_item_rendering.bake_mesh_for_quads": "Bake Mesh For Quads", "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?)", "acceleratedrendering.configuration.accelerated_item_rendering.default_pipeline": "Default Rendering Pipeline", "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.", "acceleratedrendering.configuration.accelerated_item_rendering.mesh_type": "Cached Mesh Type", "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.", "acceleratedrendering.configuration.accelerated_item_rendering.hand_acceleration": "Enable Hand Acceleration", "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.", "acceleratedrendering.configuration.accelerated_item_rendering.gui_acceleration": "Enable GUI Acceleration", "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.", "acceleratedrendering.configuration.accelerated_item_rendering.gui_item_batching": "Enable GUI Item Batching", "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.", "acceleratedrendering.configuration.accelerated_item_rendering.merge_gui_item_batching": "Enable Merge GUI Item Batches", "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.", "acceleratedrendering.configuration.accelerated_item_rendering.button": "Configure", "acceleratedrendering.configuration.accelerated_text_rendering": "Accelerated Text Rendering Settings", "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.", "acceleratedrendering.configuration.accelerated_text_rendering.feature_status": "Enable Accelerated Text Rendering", "acceleratedrendering.configuration.accelerated_text_rendering.feature_status.tooltip": "- DISABLED: Disable accelerated text rendering.\n- ENABLED: Enable accelerated text rendering.", "acceleratedrendering.configuration.accelerated_text_rendering.default_pipeline": "Default Rendering Pipeline", "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.", "acceleratedrendering.configuration.accelerated_text_rendering.mesh_type": "Cached Mesh Type", "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.", "acceleratedrendering.configuration.accelerated_text_rendering.button": "Configure", "acceleratedrendering.configuration.orientation_culling": "Simple Orientation Face Culling Settings", "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.", "acceleratedrendering.configuration.orientation_culling.feature_status": "Enable Simple Orientation Face Culling", "acceleratedrendering.configuration.orientation_culling.feature_status.tooltip": "- DISABLED: Disable simple orientation face culling.\n- ENABLED: Enable simple orientation face culling.", "acceleratedrendering.configuration.orientation_culling.default_culling": "Default Culling Setting", "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.", "acceleratedrendering.configuration.orientation_culling.ignore_cull_state": "Ignore Cull State", "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.", "acceleratedrendering.configuration.orientation_culling.button": "Configure", "acceleratedrendering.configuration.filter": "Filters Settings", "acceleratedrendering.configuration.filter.tooltip": "Filters allows you to prevent specific entities/block entities/items from being accelerated when rendering for better compatibility.", "acceleratedrendering.configuration.filter.feature_status": "Enable Filters", "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.", "acceleratedrendering.configuration.filter.menu_filter": "Enable Menu Filter", "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.", "acceleratedrendering.configuration.filter.entity_filter": "Enable Entity Filter", "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.", "acceleratedrendering.configuration.filter.block_entity_filter": "Enable Block Entity Filter", "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.", "acceleratedrendering.configuration.filter.item_filter": "Enable Item Filter", "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.", "acceleratedrendering.configuration.filter.stage_filter": "Enable Custom Rendering Stage Filter", "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.", "acceleratedrendering.configuration.filter.menu_filter_type": "Menu Filter Type", "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.", "acceleratedrendering.configuration.filter.entity_filter_type": "Entity Filter Type", "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.", "acceleratedrendering.configuration.filter.block_entity_filter_type": "Block Entity Filter Type", "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.", "acceleratedrendering.configuration.filter.item_filter_type": "Item Filter Type", "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.", "acceleratedrendering.configuration.filter.stage_filter_type": "Custom Rendering Stage Filter Type", "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.", "acceleratedrendering.configuration.filter.menu_filter_values": "Menu Filter Values", "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.", "acceleratedrendering.configuration.filter.entity_filter_values": "Entity Filter Values", "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.", "acceleratedrendering.configuration.filter.block_entity_filter_values": "Block Entity Filter Values", "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.", "acceleratedrendering.configuration.filter.item_filter_values": "Item Filter Values", "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.", "acceleratedrendering.configuration.filter.stage_filter_values": "Custom Rendering Stage Filter Values", "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.", "acceleratedrendering.configuration.filter.menu_filter_values.button": "Configure", "acceleratedrendering.configuration.filter.entity_filter_values.button": "Configure", "acceleratedrendering.configuration.filter.block_entity_filter_values.button": "Configure", "acceleratedrendering.configuration.filter.item_filter_values.button": "Configure", "acceleratedrendering.configuration.filter.stage_filter_values.button": "Configure", "acceleratedrendering.configuration.filter.button": "Configure", "acceleratedrendering.configuration.iris_compatibility": "Iris Compatibility Settings", "acceleratedrendering.configuration.iris_compatibility.tooltip": "Iris Compatibility Settings allows Accelerated Rendering to work correctly with Iris.", "acceleratedrendering.configuration.iris_compatibility.feature_status": "Enable Iris Compatibility", "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.", "acceleratedrendering.configuration.iris_compatibility.orientation_culling_compatibility": "Enable Simple Orientation Culling Compatibility", "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.", "acceleratedrendering.configuration.iris_compatibility.shadow_culling": "Enable Shadow Culling", "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.", "acceleratedrendering.configuration.iris_compatibility.polygon_processing": "Enable Polygon Processing", "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.", "acceleratedrendering.configuration.iris_compatibility.button": "Configure", "acceleratedrendering.configuration.curios_compatibility": "Curios Compatibility Settings", "acceleratedrendering.configuration.curios_compatibility.tooltip": "Curios Compatibility Settings allows Accelerated Rendering to work correctly with Curios.", "acceleratedrendering.configuration.curios_compatibility.feature_status": "Enable Curios Compatibility", "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.", "acceleratedrendering.configuration.curios_compatibility.layer_acceleration": "Enable Curios Layer Acceleration", "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.", "acceleratedrendering.configuration.curios_compatibility.item_filter": "Enable Curios Item Filter", "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.", "acceleratedrendering.configuration.curios_compatibility.item_filter_type": "Curios Item Filter Type", "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.\"", "acceleratedrendering.configuration.curios_compatibility.item_filter_values": "Curios Item Filter Values", "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.", "acceleratedrendering.configuration.curios_compatibility.item_filter_values.button": "Configure", "acceleratedrendering.configuration.curios_compatibility.button": "Configure" } ================================================ FILE: src/main/resources/assets/acceleratedrendering/lang/zh_cn.json ================================================ { "acceleratedrendering.configuration.title": "加速渲染配置项", "acceleratedrendering.configuration.section.acceleratedrendering.client.toml.title": "加速渲染客户端配置项", "acceleratedrendering.configuration.section.acceleratedrendering.client.toml": "用于配置由加速渲染提供的优化特性的配置项目录", "acceleratedrendering.configuration.core_settings": "核心配置", "acceleratedrendering.configuration.core_settings.tooltip": "核心配置包含了能影响所有渲染特性的配置", "acceleratedrendering.configuration.core_settings.pooled_ring_buffer_size": "环形缓存池最大数量", "acceleratedrendering.configuration.core_settings.pooled_ring_buffer_size.tooltip": "修改此项数值可能会影响FPS, 越高的值代表允许越多\"in-flight frames\", 反之亦然. 允许的\"in-flight frames\"越多, 提升的FPS越多, 但占用的显存也越多.", "acceleratedrendering.configuration.core_settings.pooled_batching_size": "单次绘制最大允许合批数量", "acceleratedrendering.configuration.core_settings.pooled_batching_size.tooltip": "修改此项数值可能会影响FPS, 越高的值代表允许越多RenderType合并在一次绘制中, 反之亦然, 允许的数量越多, 提升的FPS越多, 但是占用的显存越多, 并且消耗更多CPU资源处理合批.", "acceleratedrendering.configuration.core_settings.cached_image_size": "缓存贴图最大数量", "acceleratedrendering.configuration.core_settings.cached_image_size.tooltip": "修改此项数值可能会影响FPS, 越高的值代表允许越多缓存贴图, 反之亦然, 允许的数量越多, 提升的FPS越多, 但是占用的内存越多.", "acceleratedrendering.configuration.core_settings.dynamic_uv_resolution": "动态RenderType缓存UV分辨率", "acceleratedrendering.configuration.core_settings.dynamic_uv_resolution.tooltip": "修改此项数值可能会影响和显存占用. 越小的值代表越低的UV滚动分辨率和越少的被缓存的RenderType, 反之亦然. 分辨率越高, 闪电苦力怕和旋风人的动画越流畅, 但是占用的显存越多.", "acceleratedrendering.configuration.core_settings.debug_context": "启用调试上下文", "acceleratedrendering.configuration.core_settings.debug_context.tooltip": "- DISABLED: 调试上下文将会被禁用, 可能会在部分启用\"theaded optimization\"的NVIDIA显卡上有严重视觉错误.\n- ENABLED: 调试上下文将会被启用, 以阻止会NVIDIA显卡驱动应用会导致严重视觉错误的\"threaded optimization\".", "acceleratedrendering.configuration.core_settings.force_translucent_acceleration": "启用强制加速半透明", "acceleratedrendering.configuration.core_settings.force_translucent_acceleration.tooltip": "- DISABLED: 除非其他MOD在渲染其面片时显示声明加速半透明, 否则被标记为半透明的RenderType将会在加速管线不支持半透明排序时使用原版渲染管线.\n- ENABLED: 除非其他MOD在渲染其面片时显式声明关闭强制半透明加速, 否则即使加速管线不支持半透明排序, 被标记为半透明的RenderType依然会使用加速管线进行渲染.", "acceleratedrendering.configuration.core_settings.cache_identical_pose": "启用相同变换缓存", "acceleratedrendering.configuration.core_settings.cache_identical_pose.tooltip": "- DISABLED: 除非其他MOD在渲染其面片时显示声明开启相同变换缓存, 否则具有相同变换矩阵和法线矩阵的变化将不会缓存, 部分降低CPU计算压力但是占用更多显存.\n- ENABLED: 除非其他MOD在渲染其面片时显式声明关闭相同变换缓存, 否则具有相同变换矩阵和法线矩阵的变化将会使用缓存中已有的数据, 小幅提升CPU计算压力但是占用更少显存.", "acceleratedrendering.configuration.core_settings.mesh_info_cache_type": "模型实例缓存类型", "acceleratedrendering.configuration.core_settings.mesh_info_cache_type.tooltip": "- SIMPLE: 最基础的缓存实现, 通常用来检测其他缓存类型是否正常工作.\n- HANDLE: 更快的缓存实现, 使用VarHandle和扁平化数据来提高读写性能.\n- UNSAFE: 最快的缓存实现, 使用了不安全的内存操作来跳过多项检查进行读写.", "acceleratedrendering.configuration.core_settings.layer_storage_type": "合批层储存类型", "acceleratedrendering.configuration.core_settings.layer_storage_type.tooltip": "- SORTED: 最基础的实现, 将不透明与半透明模型一同在一个单独的阶段中进行渲染, 性能更好但可能造成半透明模型的视觉错误.\n- SEPARATED: 视觉上更精确的实现, 将不透明与半透明模型分至两个单独的阶段渲染以防止视觉错误, 略慢于基础实现.", "acceleratedrendering.configuration.core_settings.mesh_merge_type": "模型合并类型", "acceleratedrendering.configuration.core_settings.mesh_merge_type.tooltip": "- IGNORED: 拥有完全一致顶点的模型将不会被合并, 占用的内存更少但是为储存重复模型占用的显存更多.\n- MERGED: 拥有完全一致顶点的模型将会被合并, 占用的显存更少但为储存合并所需要的信息所占用的内存更多.", "acceleratedrendering.configuration.core_settings.upload_mesh_immediately": "启用立即上传模型", "acceleratedrendering.configuration.core_settings.upload_mesh_immediately.tooltip": "- DISABLED: 将要被加速的模型将会被统计收集并在最后统一上传以选择更好的上传方法和更好的内存访问效率, 同时这个方法允许更多(2GB以上直到显存限制)的模型缓存容量, 但这个方式可能不会按照正常渲染顺序并造成部分渲染异常.\n- ENABLED: 将要被加速的模型将会在绘制指令后立即上传, 这样相对更低效, 且只有通常2GB左右的模型缓存(大多数情况下足够了), 但是能保证绘制顺序一致以提供最好的兼容性.", "acceleratedrendering.configuration.core_settings.cache_dynamic_render_type": "启用缓存动态RenderType", "acceleratedrendering.configuration.core_settings.cache_dynamic_render_type.tooltip": "- DISABLED: 诸如闪电苦力怕的闪电和旋风人的风所使用的动态RenderType将不会被加速, 占用更少显存的同时动画更流畅, 但可能意外跳过其他MOD使用这些动态RenderType进行渲染的模型的加速.\n- ENABLED: 诸如闪电苦力怕的闪电和旋风人的风所使用的动态RenderType将会被加速以加速其他MOD使用这些动态RenderType进行渲染的模型, 但是占用更多显存, 以及基于分辨率设置可能导致的不太流畅的动画.", "acceleratedrendering.configuration.core_settings.viewport_binding_state": "可视区域还原类型", "acceleratedrendering.configuration.core_settings.viewport_binding_state.tooltip": "- IGNORED: 禁用可视区域还原, 更快, 但可能降低了对修改了可视区域的MOD兼容性.\n- MOJANG: 使用Mojang提供的GLStateManager对可能被其他MOD修改的可视区域进行记录和还原, 以改善兼容性.\n- OPENGL: 使用OpenGL对可能被其他MOD修改的可视区域进行记录和还原, 以在即使MOD不使用Mojang提供的GLStateManager的情况下改善兼容性, 略慢但能保证最佳兼容性.", "acceleratedrendering.configuration.core_settings.scissor_binding_state": "裁切区域还原类型", "acceleratedrendering.configuration.core_settings.scissor_binding_state.tooltip": "- IGNORED: 禁用裁切区域还原, 更快, 但可能降低了对修改了裁切区域的MOD兼容性.\n- MOJANG: 使用Mojang提供的GuiGraphics对可能被其他MOD修改的裁切区域进行记录和还原, 以改善兼容性.\n- OPENGL: 使用OpenGL对可能被其他MOD修改的裁切区域进行记录和还原, 以在即使MOD不使用Mojang提供的GuiGraphics的情况下改善兼容性, 略慢但能保证最佳兼容性.", "acceleratedrendering.configuration.core_settings.button": "配置", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring": "块缓冲还原配置", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.tooltip": "部分MOD和光影会使用块缓冲进行渲染, 可能会与同样使用块缓冲的加速渲染造成冲突.\n块缓冲还原可以在加速前记录块缓冲绑定, 在加速后还原成加速前的块缓冲绑定以实现更好的兼容性", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.feature_status": "启用块缓冲还原", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.feature_status.tooltip": "- DISABLED: 禁用块缓冲还原, 速度更快但可能与使用块缓冲的MOD和光影冲突.\n- ENABLED: 启用块缓冲还原, 速度可能由于需要记录和还原块缓冲绑定而略慢, 但能确保在使用了块缓冲的MOD和光影的环境中正常工作.", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.binding_cache_type": "块缓冲绑定缓存类型", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.binding_cache_type.tooltip": "- SIMPLE: 最基础的缓存实现, 通常用来检测其他缓存类型是否正常工作.\n- HANDLE: 更快的缓存实现, 使用VarHandle和扁平化数据来提高读写性能.\n- UNSAFE: 最快的缓存实现, 使用了不安全的内存操作来跳过多项检查进行读写.", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.shader_storage_type": "着色器储存缓冲还原类型", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.shader_storage_type.tooltip": "- IGNORED: 着色器储存缓冲的还原将被忽略, 可以改善FPS但可能降低与使用了着色器储存缓冲的MOD和光影的兼容性.\n- RESTORED: 着色器储存缓冲将被记录和还原, 可能略微降低FPS但与使用了着色器储存缓冲的MOD和光影有更好的兼容性.", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.atomic_counter_type": "原子计数器缓冲还原类型", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.atomic_counter_type.tooltip": "- IGNORED: 原子计数器缓冲的还原将被忽略, 可以改善FPS但可能降低与使用了原子计数器缓冲的MOD和光影的兼容性.\n- RESTORED: 原子计数器缓冲将被记录和还原, 可能略微降低FPS但与使用了原子计数器缓冲的MOD和光影有更好的兼容性.", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.shader_storage_range": "着色器储存缓冲还原范围", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.shader_storage_range.tooltip": "将要被记录和还原的着色器储存缓冲绑定点范围.\n修改此项数值可能会影响FPS. 越高的值代表越大的着色器储存缓冲还原范围和更好的兼容性, 越小的值代表越少的着色器储存缓冲还原范围但更差的兼容性, 还原范围越大, 开销造成的FPS降低越大.", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.atomic_counter_range": "原子计数器缓冲还原范围", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.atomic_counter_range.tooltip": "将要被记录和还原的原子计数器缓冲绑定点范围.\n修改此项数值可能会影响FPS. 越高的值代表越大的原子计数器缓冲还原范围和更好的兼容性, 越小的值代表越少的原子计数器缓冲还原范围但更差的兼容性, 还原范围越大, 开销造成的FPS降低越大.", "acceleratedrendering.configuration.core_settings.block_buffer_binding_restoring.button": "配置", "acceleratedrendering.configuration.accelerated_entity_rendering": "加速实体渲染配置", "acceleratedrendering.configuration.accelerated_entity_rendering.tooltip": "加速实体渲染使用GPU对ModelPart进行缓存和顶点变换, 而非原版在CPU每次渲染时重建和变换顶点.", "acceleratedrendering.configuration.accelerated_entity_rendering.feature_status": "启用加速实体渲染", "acceleratedrendering.configuration.accelerated_entity_rendering.feature_status.tooltip": "- DISABLED: 禁用加速实体渲染.\n- ENABLED: 启用加速实体渲染.", "acceleratedrendering.configuration.accelerated_entity_rendering.default_pipeline": "默认渲染管线", "acceleratedrendering.configuration.accelerated_entity_rendering.default_pipeline.tooltip": "- VANILLA: 除非其他MOD在渲染其实体时显式声明临时开启加速渲染, 否则实体将不会通过加速管线渲染.\n- ACCELERATED: 除非其他MOD在渲染其实体时时显式声明临时关闭加速渲染, 否则实体将始终通过加速管线渲染.", "acceleratedrendering.configuration.accelerated_entity_rendering.mesh_type": "模型缓存类型", "acceleratedrendering.configuration.accelerated_entity_rendering.mesh_type.tooltip": "- CLIENT: 模型将缓存在客户端(CPU)侧, 占用更少显存, 但渲染时可能会耗费额外时间上传至服务端侧(GPU).\n- SERVER: 模型将缓存在服务端(GPU)侧, 获得更好的渲染性能, 但会占用更多显存.", "acceleratedrendering.configuration.accelerated_entity_rendering.gui_acceleration": "启用GUI实体加速", "acceleratedrendering.configuration.accelerated_entity_rendering.gui_acceleration.tooltip": "- DISABLED: 除非其他MOD在渲染其实体时显式声明临时开启GUI实体加速, 实体将不会在GUI绘制中被加速渲染.\n- ENABLED: 除非其他MOD在渲染其实体时显式声明临时关闭GUI实体加速, 实体将始终会在GUI绘制中被加速渲染.", "acceleratedrendering.configuration.accelerated_entity_rendering.button": "配置", "acceleratedrendering.configuration.accelerated_item_rendering": "加速物品渲染配置", "acceleratedrendering.configuration.accelerated_item_rendering.tooltip": "加速物品渲染使用GPU对物品模型进行缓存和顶点变换, 而非原版在CPU每次渲染时重建和变换顶点.", "acceleratedrendering.configuration.accelerated_item_rendering.feature_status": "启用加速物品渲染", "acceleratedrendering.configuration.accelerated_item_rendering.feature_status.tooltip": "- DISABLED: 禁用加速物品渲染.\n- ENABLED: 启用加速物品渲染.", "acceleratedrendering.configuration.accelerated_item_rendering.bake_mesh_for_quads": "为动态面缓存", "acceleratedrendering.configuration.accelerated_item_rendering.bake_mesh_for_quads.tooltip": "- DISABLED: 除非MOD在渲染其物品模型时显式声明开启动态面缓存, 否则加速渲染将不会为动态物品模型(不属于SimpleBakedModel的模型)提供的面进行模型缓存.\n- ENABLED: 除非MOD在渲染其物品模型时显式声明临时关闭动态面缓存, 否则加速渲染将会为所有动态物品模型(不属于SimpleBakedModel的模型)提供的面进行模型缓存, 加速动态物品模型的渲染, 但如果动态物品模型一直分配新的面数据则有可能崩溃. (没人这么干, 就算这么干了, 那也是他们的错)", "acceleratedrendering.configuration.accelerated_item_rendering.default_pipeline": "默认渲染管线", "acceleratedrendering.configuration.accelerated_item_rendering.default_pipeline.tooltip": "- VANILLA: 除非其他MOD在渲染其物品模型时显式声明临时开启加速渲染, 否则物品模型将不会通过加速管线渲染.\n- ACCELERATED: 除非其他MOD在渲染其物品模型时时显式声明临时关闭加速渲染, 否则物品模型将始终通过加速管线渲染.", "acceleratedrendering.configuration.accelerated_item_rendering.mesh_type": "模型缓存类型", "acceleratedrendering.configuration.accelerated_item_rendering.mesh_type.tooltip": "- CLIENT: 模型将缓存在客户端(CPU)侧, 占用更少显存, 但渲染时可能会耗费额外时间上传至服务端侧(GPU).\n- SERVER: 模型将缓存在服务端(GPU)侧, 获得更好的渲染性能, 但会占用更多显存.", "acceleratedrendering.configuration.accelerated_item_rendering.hand_acceleration": "启用手中物品加速", "acceleratedrendering.configuration.accelerated_item_rendering.hand_acceleration.tooltip": "- DISABLED: 除非其他MOD在渲染其物品模型时显式声明临时开启手中物品加速, 否则加速渲染将不会在渲染手中物品时加速那些被标记为\"太过简单加速后无法弥补加速带来的开销\"的模型.\n- ENABLED: 除非其他MOD在渲染其物品模型时显式声明临时关闭手中物品加速, 否则加速渲染将仍然会在渲染手中物品时加速那些被标记为\"太过简单加速后无法弥补加速带来的开销\"的模型, 这可能会造成额外开销轻微降低FPS, 但是允许加速那些拥有大量顶点的类原版MOD物品模型.", "acceleratedrendering.configuration.accelerated_item_rendering.gui_acceleration": "启用GUI物品加速", "acceleratedrendering.configuration.accelerated_item_rendering.gui_acceleration.tooltip": "- DISABLED: 除非其他MOD在渲染其物品模型时显式声明临时开启GUI物品加速, 否则加速渲染将不会在渲染容器GUI时加速那些被标记为\"太过简单加速后无法弥补加速带来的开销\"的模型.\n- ENABLED: 除非其他MOD在渲染其物品模型时显式声明临时关闭GUI物品加速, 否则加速渲染将仍然会在渲染容器GUI时加速那些被标记为\"太过简单加速后无法弥补加速带来的开销\"的模型, 这可能会造成额外开销轻微降低FPS, 但是允许加速那些拥有大量顶点的类原版MOD物品模型.", "acceleratedrendering.configuration.accelerated_item_rendering.gui_item_batching": "启用GUI物品合批", "acceleratedrendering.configuration.accelerated_item_rendering.gui_item_batching.tooltip": "- DISABLED: 当GUI物品加速开启时, 在容器GUI中被渲染的物品将以每渲染一次物品就执行一次绘制的方式进行渲染, 这样比较低效并对FPS造成较大影响, 但拥有更好的MOD兼容性.\n- ENABLED: 当GUI物品加速开启时, 在容器GUI中被渲染的物品将会统一收集至一次合批中绘制, 这样极大提升了渲染效率但是对MOD的容器GUI兼容性较差.", "acceleratedrendering.configuration.accelerated_item_rendering.merge_gui_item_batching": "启用合并GUI物品批次", "acceleratedrendering.configuration.accelerated_item_rendering.merge_gui_item_batching.tooltip": "- DISABLED: 当GUI物品合批时, 背景和物品栏渲染的物品将独立分为两个批次进行绘制, 这样比较低效并对FPS有轻微影响, 但拥有更好的MOD兼容性.\n- ENABLED: 当GUI物品合批时, 背景和物品栏渲染的物品将合并为一个单独的批次进行绘制, 这样提升了渲染效率但是对MOD的容器GUI兼容性较差.", "acceleratedrendering.configuration.accelerated_item_rendering.button": "配置", "acceleratedrendering.configuration.accelerated_text_rendering": "加速文字渲染配置", "acceleratedrendering.configuration.accelerated_text_rendering.tooltip": "加速文字渲染使用GPU对BakedGlyph进行缓存和顶点变换, 而非原版在CPU每次渲染时重建和变换顶点.", "acceleratedrendering.configuration.accelerated_text_rendering.feature_status": "启用加速文字渲染", "acceleratedrendering.configuration.accelerated_text_rendering.feature_status.tooltip": "- DISABLED: 禁用加速文字渲染.\n- ENABLED: 启用加速文字渲染.", "acceleratedrendering.configuration.accelerated_text_rendering.default_pipeline": "默认渲染管线", "acceleratedrendering.configuration.accelerated_text_rendering.default_pipeline.tooltip": "- VANILLA: 除非其他MOD在渲染其文字时显式声明临时开启加速渲染, 否则文字将不会通过加速管线渲染.\n- ACCELERATED: 除非其他MOD在渲染其文字时时显式声明临时关闭加速渲染, 否则文字将始终通过加速管线渲染.", "acceleratedrendering.configuration.accelerated_text_rendering.mesh_type": "模型缓存类型", "acceleratedrendering.configuration.accelerated_text_rendering.mesh_type.tooltip": "- CLIENT: 模型将缓存在客户端(CPU)侧, 占用更少显存, 但渲染时可能会耗费额外时间上传至服务端侧(GPU).\n- SERVER: 模型将缓存在服务端(GPU)侧, 获得更好的渲染性能, 但会占用更多显存.", "acceleratedrendering.configuration.accelerated_text_rendering.button": "配置", "acceleratedrendering.configuration.orientation_culling": "简单朝向面剔除配置", "acceleratedrendering.configuration.orientation_culling.tooltip": "简单朝向面剔除在绘制调用前使用一个根据3x3矩阵行列式来判断面是否朝向屏幕的ComputeShader(计算着色器)来剔除在屏幕上不可见的面, 减少需要绘制的面数.", "acceleratedrendering.configuration.orientation_culling.feature_status": "启用简单朝向面剔除", "acceleratedrendering.configuration.orientation_culling.feature_status.tooltip": "- DISABLED: 禁用简单朝向面剔除.\n- ENABLED: 启用简单朝向面剔除.", "acceleratedrendering.configuration.orientation_culling.default_culling": "默认剔除设置", "acceleratedrendering.configuration.orientation_culling.default_culling.tooltip": "- DISABLED: 除非其他MOD在渲染其面片时显式声明临时开启简单朝向面剔除, 否则面片将不会被剔除\n- ENABLED: 除非其他MOD在渲染其面片时显式声明临时关闭简单朝向面剔除, 否则面片将始终被剔除.", "acceleratedrendering.configuration.orientation_culling.ignore_cull_state": "强制剔除", "acceleratedrendering.configuration.orientation_culling.ignore_cull_state.tooltip": "- DISABLED: 简单朝向面剔除将不会剔除被声明为不可剔除的实体\n- ENABLED: 简单朝向面剔除将会对所有实体进行强制剔除, 即使其被声明为不可剔除, 可能会造成轻微渲染差异.", "acceleratedrendering.configuration.orientation_culling.button": "配置", "acceleratedrendering.configuration.filter": "过滤器配置", "acceleratedrendering.configuration.filter.tooltip": "过滤器允许为了兼容性手动配置阻止部分实体/方块/物品在渲染时被加速", "acceleratedrendering.configuration.filter.feature_status": "启用过滤器", "acceleratedrendering.configuration.filter.feature_status.tooltip": "- DISABLED: 过滤器将被禁用, 所有的实体/方块实体/物品都将在渲染时被加速.\n- ENABLED: 过滤器将在渲染实体/方块实体/物品时根据过滤器所配置的列表和过滤器类型判断是否为该实体/方块实体进行加速.", "acceleratedrendering.configuration.filter.menu_filter": "启用容器GUI过滤器", "acceleratedrendering.configuration.filter.menu_filter.tooltip": "- DISABLED: 容器GUI过滤器将被禁用, 所有容器GUI中的模型都将被加速.\n- ENABLED: 容器GUI过滤器将在渲染对容器GUI中的模型时时根据过滤器所配置的列表和过滤器类型判断是否为该模型进行加速.", "acceleratedrendering.configuration.filter.entity_filter": "启用实体过滤器", "acceleratedrendering.configuration.filter.entity_filter.tooltip": "- DISABLED: 实体过滤器将被禁用, 所有的实体都将在渲染时被加速.\n- ENABLED: 实体过滤器将在渲染实体时根据过滤器所配置的列表和过滤器类型判断是否为该实体进行加速.", "acceleratedrendering.configuration.filter.block_entity_filter": "启用方块实体过滤器", "acceleratedrendering.configuration.filter.block_entity_filter.tooltip": "- DISABLED: 方块实体过滤器将被禁用, 所有的方块实体都将在渲染时被加速.\n- ENABLED: 方块实体过滤器将在渲染实体时根据过滤器所配置的列表和过滤器类型判断是否为该方块实体进行加速.", "acceleratedrendering.configuration.filter.item_filter": "启用物品过滤器", "acceleratedrendering.configuration.filter.item_filter.tooltip": "- DISABLED: 物品过滤器将被禁用, 所有的物品都将在渲染时被加速.\n- ENABLED: 物品过滤器将在渲染实体时根据过滤器所配置的列表和过滤器类型判断是否为该物品进行加速.", "acceleratedrendering.configuration.filter.stage_filter": "启用自定义渲染阶段过滤器", "acceleratedrendering.configuration.filter.stage_filter.tooltip": "- DISABLED: 自定义渲染阶段过滤器将被禁用, 所有自定义渲染阶段中的模型都将被加速.\n- ENABLED: 自定义渲染阶段过滤器将在渲染对应自定义渲染阶段中的模型时时根据过滤器所配置的列表和过滤器类型判断是否为该模型进行加速.", "acceleratedrendering.configuration.filter.menu_filter_type": "容器GUI过滤器类型", "acceleratedrendering.configuration.filter.menu_filter_type.tooltip": "- BLACKLIST: 不在容器GUI过滤器列表中的容器GUI将通过过滤器并在渲染时加速 (即黑名单).\n- WHITELIST: 只有在容器GUI过滤器列表中的容器GUI才能通过过滤器并在渲染时加速 (即白名单).", "acceleratedrendering.configuration.filter.entity_filter_type": "实体过滤器类型", "acceleratedrendering.configuration.filter.entity_filter_type.tooltip": "- BLACKLIST: 不在实体过滤器列表中的实体类型将通过过滤器并在渲染时加速 (即黑名单).\n- WHITELIST: 只有在实体过滤器列表中的实体类型才能通过过滤器并在渲染时加速 (即白名单).", "acceleratedrendering.configuration.filter.block_entity_filter_type": "方块实体过滤器类型", "acceleratedrendering.configuration.filter.block_entity_filter_type.tooltip": "- BLACKLIST: 不在方块实体过滤器列表中的方块实体类型将通过过滤器并在渲染时加速 (即黑名单).\n- WHITELIST: 只有在方块实体过滤器列表中的方块实体类型才能通过过滤器并在渲染时加速 (即白名单).", "acceleratedrendering.configuration.filter.item_filter_type": "物品过滤器类型", "acceleratedrendering.configuration.filter.item_filter_type.tooltip": " BLACKLIST: 不在物品过滤器列表中的物品将通过过滤器并在渲染时加速 (即黑名单).\n- WHITELIST: 只有在物品过滤器列表中的物品才能通过过滤器并在渲染时加速 (即白名单).", "acceleratedrendering.configuration.filter.stage_filter_type": "自定义渲染阶段过滤器类型", "acceleratedrendering.configuration.filter.stage_filter_type.tooltip": "- BLACKLIST: 不在自定义渲染阶段过滤器列表中的自定义渲染通道将通过过滤器并在渲染时加速 (即黑名单).\n- WHITELIST: 只有在自定义渲染阶段过滤器列表中的自定义渲染阶段才能通过过滤器并在渲染时加速 (即白名单).", "acceleratedrendering.configuration.filter.menu_filter_values": "容器GUI过滤器列表", "acceleratedrendering.configuration.filter.menu_filter_values.tooltip": "你可以通过这个列表配置容器GUI过滤器.\n容器GUI过滤器将根据这个列表和过滤器类型来判断对应容器GUI能否通过过滤器.", "acceleratedrendering.configuration.filter.entity_filter_values": "实体过滤器列表", "acceleratedrendering.configuration.filter.entity_filter_values.tooltip": "你可以通过这个列表配置实体过滤器.\n实体过滤器将根据这个列表和过滤器类型来判断对应实体能否通过过滤器.", "acceleratedrendering.configuration.filter.block_entity_filter_values": "方块实体过滤器列表", "acceleratedrendering.configuration.filter.block_entity_filter_values.tooltip": "你可以通过这个列表配置方块实体过滤器.\n方块实体过滤器将根据这个列表和过滤器类型来判断对应方块实体能否通过过滤器.", "acceleratedrendering.configuration.filter.item_filter_values": "物品过滤器列表", "acceleratedrendering.configuration.filter.item_filter_values.tooltip": "你可以通过这个列表配置物品过滤器.\n物品过滤器将根据这个列表和过滤器类型来判断对应物品能否通过过滤器.", "acceleratedrendering.configuration.filter.stage_filter_values": "自定义渲染阶段过滤器列表", "acceleratedrendering.configuration.filter.stage_filter_values.tooltip": "你可以通过这个列表配置自定义渲染阶段过滤器.\n自定义渲染阶过滤器将根据这个列表和过滤器类型来判断对应自定义渲染阶能否通过过滤器.\n除非其他MOD添加了新的自定义渲染阶段, 否则不推荐修改次列表.", "acceleratedrendering.configuration.filter.menu_filter_values.button": "配置列表", "acceleratedrendering.configuration.filter.entity_filter_values.button": "配置列表", "acceleratedrendering.configuration.filter.block_entity_filter_values.button": "配置列表", "acceleratedrendering.configuration.filter.item_filter_values.button": "配置列表", "acceleratedrendering.configuration.filter.stage_filter_values.button": "配置列表", "acceleratedrendering.configuration.filter.button": "配置", "acceleratedrendering.configuration.iris_compatibility": "Iris兼容性配置", "acceleratedrendering.configuration.iris_compatibility.tooltip": "Iris兼容性配置允许加速渲染在Iris环境下正常工作.", "acceleratedrendering.configuration.iris_compatibility.feature_status": "启用Iris兼容性", "acceleratedrendering.configuration.iris_compatibility.feature_status.tooltip": "- DISABLED: 加速渲染将与Iris不兼容, 并在与Iris一同工作时造成视觉错误.\n- ENABLED: 加速渲染将使用与Iris顶点格式匹配的兼容Shader用于在Iris环境中正常工作并兼容Iris.", "acceleratedrendering.configuration.iris_compatibility.orientation_culling_compatibility": "启用朝向法线剔除兼容", "acceleratedrendering.configuration.iris_compatibility.orientation_culling_compatibility.tooltip": "- DISABLED: 在Iris环境下简单朝向面剔除将不可用, 因为其剔除Shader仅为原版顶点格式设计.\n- ENABLED: 简单朝向面剔除将使用与Iris顶点格式匹配的兼容Shader用于在Iris环境中正常剔除.", "acceleratedrendering.configuration.iris_compatibility.shadow_culling": "启用阴影剔除", "acceleratedrendering.configuration.iris_compatibility.shadow_culling.tooltip": "- DISABLED: 除非其他MOD在渲染其阴影时显示声明启用阴影剔除, 否则当实体渲染阴影时, 多余的面将不会被剔除, 这可能导致由多余面造成的FPS下降.\n- ENABLED: 除非其他MOD在渲染其阴影时显示声明禁用阴影剔除, 否则当实体渲染阴影时, 多余的面将会被剔除以提升FPS, 但这可能会导致不正确的阴影渲染.", "acceleratedrendering.configuration.iris_compatibility.polygon_processing": "启用多边形额外数据计算", "acceleratedrendering.configuration.iris_compatibility.polygon_processing.tooltip": "- DISABLED: 除非其他MOD在渲染其面片时显示声明启用额外数据计算, 否则加速渲染管线将不会计算或上传顶点中由Iris提供的额外信息, 可能会造成视觉错误或不正确的渲染结果.\n- ENABLED: 除非其他MOD在渲染其面片时显示声明禁用额外数据计算, 否则加速渲染管线将会使用ComputeShader(计算着色器)计算并上传顶点中由Iris提供的额外信息.", "acceleratedrendering.configuration.iris_compatibility.button": "配置", "acceleratedrendering.configuration.curios_compatibility": "Curios兼容性配置", "acceleratedrendering.configuration.curios_compatibility.tooltip": "Curios兼容性配置允许加速渲染在Curios环境下正常工作.", "acceleratedrendering.configuration.curios_compatibility.feature_status": "启用Curios兼容性", "acceleratedrendering.configuration.curios_compatibility.feature_status.tooltip": "- DISABLED: 加速渲染将不会中断对于实体中Curios层的加速.\n- ENABLED: 加速渲染将会终止实体中Curios层的加速防止部分MOD因为过于离谱的渲染代码导致损坏加速渲染的缓存机制.", "acceleratedrendering.configuration.curios_compatibility.layer_acceleration": "启用Curios层加速", "acceleratedrendering.configuration.curios_compatibility.layer_acceleration.tooltip": "- DISABLED: 除非其他MOD在渲染其饰品或装备时显式声明启用Curios层加速, 否则加速渲染将不会对Curios层进行加速, 以此确保加速渲染不会因为部分MOD过于离谱的渲染代码导致崩溃.\n- ENABLED: 除非其他MOD在渲染其饰品或装备时显式声明关闭Curios层加速, 否则加速渲染将会默认开启Curios层加速.", "acceleratedrendering.configuration.curios_compatibility.item_filter": "启用Curios物品过滤器", "acceleratedrendering.configuration.curios_compatibility.item_filter.tooltip": "- DISABLED: Curios物品过滤器将被禁用, 所有Curios饰品或装备是否加速都由\"启用Curios层加速\" (Enable Curios Layer Acceleration) 这个选项控制.\n- ENABLED: Curios物品过滤器将在渲染Curios饰品或装备时根据过滤器所配置的列表和过滤器类型判断是否阻止没通过过滤器的饰品或装备的加速.", "acceleratedrendering.configuration.curios_compatibility.item_filter_type": "Curios物品过滤器类型", "acceleratedrendering.configuration.curios_compatibility.item_filter_type.tooltip": "- BLACKLIST: 不在Curios物品过滤器列表中的Curios物品将通过过滤器 (即黑名单).\n- WHITELIST: 只有在Curios物品过滤器列表中的Curios物品才能通过过滤器 (即白名单).", "acceleratedrendering.configuration.curios_compatibility.item_filter_values": "Curios物品过滤器列表", "acceleratedrendering.configuration.curios_compatibility.item_filter_values.tooltip": "你可以通过这个列表配置Curios物品过滤器.\nCurios物品过滤器将根据这个列表和过滤器类型来判断对应Curios物品能否通过过滤器.", "acceleratedrendering.configuration.curios_compatibility.item_filter_values.button": "配置列表", "acceleratedrendering.configuration.curios_compatibility.button": "配置" } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/compat/culling/iris_block_quad_culling_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; uint uv2; uint normal; uint iris_entity; uint iris_data_0; uint iris_data_1; uint iris_data_2; uint iris_data_3; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct Polygon { uint vertex1; uint vertex2; uint vertex3; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict readonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) restrict readonly buffer Varyings { VaryingData varyings[]; }; layout(binding=6, std430) restrict writeonly buffer PolygonsOut { Polygon polygonsOut[]; }; layout(binding=0, offset=0) uniform atomic_uint indexCounter; layout(location=0) uniform mat4 viewMatrix; layout(location=1) uniform mat4 projectMatrix; layout(location=2) uniform uint polygonCount; layout(location=3) uniform uint vertexOffset; layout(location=4) uniform uint varyingOffset; void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 4u; if (index >= polygonCount) { return; } uint index0 = varyingOffset + base + 0u; uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; uint index4 = vertexOffset + base + 3u; uint noCull = varyings[index0 - varyings[index0].offset].noCull; Vertex vertex1 = vertices[index1]; Vertex vertex2 = vertices[index2]; Vertex vertex3 = vertices[index3]; Vertex vertex4 = vertices[index4]; mat4 matrix = projectMatrix * viewMatrix; vec4 pos1 = matrix * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0); vec4 pos2 = matrix * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0); vec4 pos3 = matrix * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0); vec4 pos4 = matrix * vec4(vertex4.x, vertex4.y, vertex4.z, 1.0); float det1 = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw)); float det2 = determinant(mat3(pos3.xyw, pos4.xyw, pos1.xyw)); if (noCull > 0u || det1 > 0.0 || det2 > 0.0) { uint indexOut = atomicCounterAdd(indexCounter, 6u) / 3u; polygonsOut[indexOut + 0].vertex1 = index1; polygonsOut[indexOut + 0].vertex2 = index2; polygonsOut[indexOut + 0].vertex3 = index3; polygonsOut[indexOut + 1].vertex1 = index3; polygonsOut[indexOut + 1].vertex2 = index4; polygonsOut[indexOut + 1].vertex3 = index1; } } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/compat/culling/iris_block_triangle_culling_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; uint uv2; uint normal; uint iris_entity; uint iris_data_0; uint iris_data_1; uint iris_data_2; uint iris_data_3; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct Polygon { uint vertex1; uint vertex2; uint vertex3; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict readonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) restrict readonly buffer Varyings { VaryingData varyings[]; }; layout(binding=6, std430) restrict writeonly buffer PolygonsOut { Polygon polygonsOut[]; }; layout(binding=0, offset=0) uniform atomic_uint indexCounter; layout(location=0) uniform mat4 viewMatrix; layout(location=1) uniform mat4 projectMatrix; layout(location=2) uniform uint polygonCount; layout(location=3) uniform uint vertexOffset; layout(location=4) uniform uint varyingOffset; void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 3u; if (index >= polygonCount) { return; } uint index0 = varyingOffset + base + 0u; uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; uint noCull = varyings[index0 - varyings[index0].offset].noCull; Vertex vertex1 = vertices[index1]; Vertex vertex2 = vertices[index2]; Vertex vertex3 = vertices[index3]; mat4 matrix = projectMatrix * viewMatrix; vec4 pos1 = matrix * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0); vec4 pos2 = matrix * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0); vec4 pos3 = matrix * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0); float det = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw)); if (noCull > 0u || det > 0.0) { uint indexOut = atomicCounterAdd(indexCounter, 3u) / 3u; polygonsOut[indexOut + 0].vertex1 = index1; polygonsOut[indexOut + 0].vertex2 = index2; polygonsOut[indexOut + 0].vertex3 = index3; } } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/compat/culling/iris_entity_quad_culling_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; int uv1; int uv2; uint normal; uint iris_data_0; uint iris_data_1; uint iris_data_2; uint iris_data_3; uint iris_data_4; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct Polygon { uint vertex1; uint vertex2; uint vertex3; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict readonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) restrict readonly buffer Varyings { VaryingData varyings[]; }; layout(binding=6, std430) restrict writeonly buffer PolygonsOut { Polygon polygonsOut[]; }; layout(binding=0, offset=0) uniform atomic_uint indexCounter; layout(location=0) uniform mat4 viewMatrix; layout(location=1) uniform mat4 projectMatrix; layout(location=2) uniform uint polygonCount; layout(location=3) uniform uint vertexOffset; layout(location=4) uniform uint varyingOffset; void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 4u; if (index >= polygonCount) { return; } uint index0 = varyingOffset + base + 0u; uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; uint index4 = vertexOffset + base + 3u; uint noCull = varyings[index0 - varyings[index0].offset].noCull; Vertex vertex1 = vertices[index1]; Vertex vertex2 = vertices[index2]; Vertex vertex3 = vertices[index3]; Vertex vertex4 = vertices[index4]; mat4 matrix = projectMatrix * viewMatrix; vec4 pos1 = matrix * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0); vec4 pos2 = matrix * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0); vec4 pos3 = matrix * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0); vec4 pos4 = matrix * vec4(vertex4.x, vertex4.y, vertex4.z, 1.0); float det1 = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw)); float det2 = determinant(mat3(pos3.xyw, pos4.xyw, pos1.xyw)); if (noCull > 0u || det1 > 0.0 || det2 > 0.0) { uint indexOut = atomicCounterAdd(indexCounter, 6u) / 3u; polygonsOut[indexOut + 0].vertex1 = index1; polygonsOut[indexOut + 0].vertex2 = index2; polygonsOut[indexOut + 0].vertex3 = index3; polygonsOut[indexOut + 1].vertex1 = index3; polygonsOut[indexOut + 1].vertex2 = index4; polygonsOut[indexOut + 1].vertex3 = index1; } } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/compat/culling/iris_entity_triangle_culling_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; int uv1; int uv2; uint normal; uint iris_data_0; uint iris_data_1; uint iris_data_2; uint iris_data_3; uint iris_data_4; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct Polygon { uint vertex1; uint vertex2; uint vertex3; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict readonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) restrict readonly buffer Varyings { VaryingData varyings[]; }; layout(binding=6, std430) restrict writeonly buffer PolygonsOut { Polygon polygonsOut[]; }; layout(binding=0, offset=0) uniform atomic_uint indexCounter; layout(location=0) uniform mat4 viewMatrix; layout(location=1) uniform mat4 projectMatrix; layout(location=2) uniform uint polygonCount; layout(location=3) uniform uint vertexOffset; layout(location=4) uniform uint varyingOffset; void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 3u; if (index >= polygonCount) { return; } uint index0 = varyingOffset + base + 0u; uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; uint noCull = varyings[index0 - varyings[index0].offset].noCull; Vertex vertex1 = vertices[index1]; Vertex vertex2 = vertices[index2]; Vertex vertex3 = vertices[index3]; mat4 matrix = projectMatrix * viewMatrix; vec4 pos1 = matrix * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0); vec4 pos2 = matrix * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0); vec4 pos3 = matrix * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0); float det = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw)); if (noCull > 0u || det > 0.0) { uint indexOut = atomicCounterAdd(indexCounter, 3u) / 3u; polygonsOut[indexOut + 0].vertex1 = index1; polygonsOut[indexOut + 0].vertex2 = index2; polygonsOut[indexOut + 0].vertex3 = index3; } } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/compat/processing/iris_block_quad_processing_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; int uv2; uint normal; uint iris_entity; float iris_midcoord_u; float iris_midcoord_v; uint iris_at_tangent; uint iris_mid_block; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict buffer Vertices { Vertex vertices[]; }; layout(location=0) uniform uint polygonCount; layout(location=1) uniform uint vertexOffset; void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 4u; if (index >= polygonCount) { return; } uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; uint index4 = vertexOffset + base + 3u; Vertex vertex1 = vertices[index1]; Vertex vertex2 = vertices[index2]; Vertex vertex3 = vertices[index3]; Vertex vertex4 = vertices[index4]; vec3 pos1 = vec3(vertex1.x, vertex1.y, vertex1.z); vec3 pos2 = vec3(vertex2.x, vertex2.y, vertex2.z); vec3 pos3 = vec3(vertex3.x, vertex3.y, vertex3.z); vec3 pos4 = vec3(vertex4.x, vertex4.y, vertex4.z); vec3 midBlock1 = (vec3(0.5) - pos1) * 64.0; vec3 midBlock2 = (vec3(0.5) - pos2) * 64.0; vec3 midBlock3 = (vec3(0.5) - pos3) * 64.0; vec3 midBlock4 = (vec3(0.5) - pos4) * 64.0; vec2 uv1 = vec2(vertex1.u0, vertex1.v0); vec2 uv2 = vec2(vertex2.u0, vertex2.v0); vec2 uv3 = vec2(vertex3.u0, vertex3.v0); vec2 uv4 = vec2(vertex4.u0, vertex4.v0); vec2 midUV = (uv1 + uv2 + uv3 + uv4) / 4; vec3 normal = unpackSnorm4x8(vertex1.normal).xyz; vec3 edge1 = pos2 - pos1; vec3 edge2 = pos3 - pos1; vec2 dUV1 = uv2 - uv1; vec2 dUV2 = uv3 - uv1; float fdenom = dUV1.x * dUV2.y - dUV2.x * dUV1.y; float f = fdenom == 0.0 ? 1.0 : 1.0 / fdenom; vec3 tangent = normalize(f * (dUV2.y * edge1 - dUV1.y * edge2)); vec3 aBitangent = normalize(f * (-dUV2.x * edge1 + dUV1.x * edge2)); vec3 pBitangent = cross(tangent, normal); vec4 tangent4 = vec4(tangent, dot(aBitangent, pBitangent) < 0.0 ? -1.0 : 1.0); uint packedTangent = packSnorm4x8(tangent4); vertices[index1].iris_mid_block = packSnorm4x8(vec4(midBlock1, -1.0)); vertices[index2].iris_mid_block = packSnorm4x8(vec4(midBlock2, -1.0)); vertices[index3].iris_mid_block = packSnorm4x8(vec4(midBlock3, -1.0)); vertices[index4].iris_mid_block = packSnorm4x8(vec4(midBlock4, -1.0)); vertices[index1].iris_at_tangent = packedTangent; vertices[index2].iris_at_tangent = packedTangent; vertices[index3].iris_at_tangent = packedTangent; vertices[index4].iris_at_tangent = packedTangent; vertices[index1].iris_midcoord_u = midUV.x; vertices[index2].iris_midcoord_u = midUV.x; vertices[index3].iris_midcoord_u = midUV.x; vertices[index4].iris_midcoord_u = midUV.x; vertices[index1].iris_midcoord_v = midUV.y; vertices[index2].iris_midcoord_v = midUV.y; vertices[index3].iris_midcoord_v = midUV.y; vertices[index4].iris_midcoord_v = midUV.y; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/compat/processing/iris_block_triangle_processing_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; int uv2; uint normal; uint iris_entity; float iris_midcoord_u; float iris_midcoord_v; uint iris_at_tangent; uint iris_mid_block; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict buffer Vertices { Vertex vertices[]; }; layout(location=0) uniform uint polygonCount; layout(location=1) uniform uint vertexOffset; uint computeTangentSmooth(vec3 pos1, vec3 pos2, vec3 pos3, vec2 uv1, vec2 uv2, vec2 uv3, vec3 normal); void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 3u; if (index >= polygonCount) { return; } uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; Vertex vertex1 = vertices[index1]; Vertex vertex2 = vertices[index2]; Vertex vertex3 = vertices[index3]; vec3 pos1 = vec3(vertex1.x, vertex1.y, vertex1.z); vec3 pos2 = vec3(vertex2.x, vertex2.y, vertex2.z); vec3 pos3 = vec3(vertex3.x, vertex3.y, vertex3.z); vec3 midBlock1 = (vec3(0.5) - pos1) * 64.0; vec3 midBlock2 = (vec3(0.5) - pos2) * 64.0; vec3 midBlock3 = (vec3(0.5) - pos3) * 64.0; vec2 uv1 = vec2(vertex1.u0, vertex1.v0); vec2 uv2 = vec2(vertex2.u0, vertex2.v0); vec2 uv3 = vec2(vertex3.u0, vertex3.v0); vec2 midUV = (uv1 + uv2 + uv3) / 3; vec3 normal1 = unpackSnorm4x8(vertex1.normal).xyz; vec3 normal2 = unpackSnorm4x8(vertex2.normal).xyz; vec3 normal3 = unpackSnorm4x8(vertex3.normal).xyz; vertices[index1].iris_mid_block = packSnorm4x8 (vec4(midBlock1, -1.0)); vertices[index2].iris_mid_block = packSnorm4x8 (vec4(midBlock2, -1.0)); vertices[index3].iris_mid_block = packSnorm4x8 (vec4(midBlock3, -1.0)); vertices[index1].iris_at_tangent = computeTangentSmooth (pos1, pos2, pos3, uv1, uv2, uv3, normal1); vertices[index2].iris_at_tangent = computeTangentSmooth (pos1, pos2, pos3, uv1, uv2, uv3, normal2); vertices[index3].iris_at_tangent = computeTangentSmooth (pos1, pos2, pos3, uv1, uv2, uv3, normal3); vertices[index1].iris_midcoord_u = midUV.x; vertices[index2].iris_midcoord_u = midUV.x; vertices[index3].iris_midcoord_u = midUV.x; vertices[index1].iris_midcoord_v = midUV.y; vertices[index2].iris_midcoord_v = midUV.y; vertices[index3].iris_midcoord_v = midUV.y; } uint computeTangentSmooth(vec3 pos1, vec3 pos2, vec3 pos3, vec2 uv1, vec2 uv2, vec2 uv3, vec3 normal) { float dot1 = dot(pos1, normal); float dot2 = dot(pos2, normal); float dot3 = dot(pos3, normal); pos1 -= dot1 * normal; pos2 -= dot2 * normal; pos3 -= dot3 * normal; vec3 edge1 = pos2 - pos1; vec3 edge2 = pos3 - pos1; vec2 dUV1 = uv2 - uv1; vec2 dUV2 = uv3 - uv1; float fdenom = dUV1.x * dUV2.y - dUV2.x * dUV1.y; float f = fdenom == 0.0 ? 1.0 : 1.0 / fdenom; vec3 tangent = normalize (f * (dUV2.y * edge1 - dUV1.y * edge2)); vec3 aBitangent = normalize (f * (-dUV2.x * edge1 + dUV1.x * edge2)); vec3 pBitangent = cross (tangent, normal); vec4 tangent4 = vec4 (tangent, dot(aBitangent, pBitangent) < 0.0 ? -1.0 : 1.0); return packSnorm4x8(tangent4); } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/compat/processing/iris_entity_quad_processing_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; int uv1; int uv2; uint normal; uint iris_entity_0; uint iris_entity_1; float iris_midcoord_u; float iris_midcoord_v; uint iris_at_tangent; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict buffer Vertices { Vertex vertices[]; }; layout(location=0) uniform uint polygonCount; layout(location=1) uniform uint vertexOffset; void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 4u; if (index >= polygonCount) { return; } uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; uint index4 = vertexOffset + base + 3u; Vertex vertex1 = vertices[index1]; Vertex vertex2 = vertices[index2]; Vertex vertex3 = vertices[index3]; Vertex vertex4 = vertices[index4]; vec3 pos1 = vec3(vertex1.x, vertex1.y, vertex1.z); vec3 pos2 = vec3(vertex2.x, vertex2.y, vertex2.z); vec3 pos3 = vec3(vertex3.x, vertex3.y, vertex3.z); vec3 pos4 = vec3(vertex4.x, vertex4.y, vertex4.z); vec2 uv1 = vec2(vertex1.u0, vertex1.v0); vec2 uv2 = vec2(vertex2.u0, vertex2.v0); vec2 uv3 = vec2(vertex3.u0, vertex3.v0); vec2 uv4 = vec2(vertex4.u0, vertex4.v0); vec2 midUV = (uv1 + uv2 + uv3 + uv4) / 4; vec3 normal = unpackSnorm4x8(vertex1.normal).xyz; vec3 edge1 = pos2 - pos1; vec3 edge2 = pos3 - pos1; vec2 dUV1 = uv2 - uv1; vec2 dUV2 = uv3 - uv1; float fdenom = dUV1.x * dUV2.y - dUV2.x * dUV1.y; float f = fdenom == 0.0 ? 1.0 : 1.0 / fdenom; vec3 tangent = normalize(f * (dUV2.y * edge1 - dUV1.y * edge2)); vec3 aBitangent = normalize(f * (-dUV2.x * edge1 + dUV1.x * edge2)); vec3 pBitangent = cross(tangent, normal); vec4 tangent4 = vec4(tangent, dot(aBitangent, pBitangent) < 0.0 ? -1.0 : 1.0); uint packedTangent = packSnorm4x8(tangent4); vertices[index1].iris_at_tangent = packedTangent; vertices[index2].iris_at_tangent = packedTangent; vertices[index3].iris_at_tangent = packedTangent; vertices[index4].iris_at_tangent = packedTangent; vertices[index1].iris_midcoord_u = midUV.x; vertices[index2].iris_midcoord_u = midUV.x; vertices[index3].iris_midcoord_u = midUV.x; vertices[index4].iris_midcoord_u = midUV.x; vertices[index1].iris_midcoord_v = midUV.y; vertices[index2].iris_midcoord_v = midUV.y; vertices[index3].iris_midcoord_v = midUV.y; vertices[index4].iris_midcoord_v = midUV.y; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/compat/processing/iris_entity_triangle_processing_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; int uv1; int uv2; uint normal; uint iris_entity_0; uint iris_entity_1; float iris_midcoord_u; float iris_midcoord_v; uint iris_at_tangent; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict buffer Vertices { Vertex vertices[]; }; layout(location=0) uniform uint polygonCount; layout(location=1) uniform uint vertexOffset; uint computeTangentSmooth(vec3 pos1, vec3 pos2, vec3 pos3, vec2 uv1, vec2 uv2, vec2 uv3, vec3 normal); void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 3u; if (index >= polygonCount) { return; } uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; Vertex vertex1 = vertices[index1]; Vertex vertex2 = vertices[index2]; Vertex vertex3 = vertices[index3]; vec3 pos1 = vec3(vertex1.x, vertex1.y, vertex1.z); vec3 pos2 = vec3(vertex2.x, vertex2.y, vertex2.z); vec3 pos3 = vec3(vertex3.x, vertex3.y, vertex3.z); vec2 uv1 = vec2(vertex1.u0, vertex1.v0); vec2 uv2 = vec2(vertex2.u0, vertex2.v0); vec2 uv3 = vec2(vertex3.u0, vertex3.v0); vec2 midUV = (uv1 + uv2 + uv3) / 3; vec3 normal1 = unpackSnorm4x8(vertex1.normal).xyz; vec3 normal2 = unpackSnorm4x8(vertex2.normal).xyz; vec3 normal3 = unpackSnorm4x8(vertex3.normal).xyz; vertices[index1].iris_at_tangent = computeTangentSmooth(pos1, pos2, pos3, uv1, uv2, uv3, normal1); vertices[index2].iris_at_tangent = computeTangentSmooth(pos1, pos2, pos3, uv1, uv2, uv3, normal2); vertices[index3].iris_at_tangent = computeTangentSmooth(pos1, pos2, pos3, uv1, uv2, uv3, normal3); vertices[index1].iris_midcoord_u = midUV.x; vertices[index2].iris_midcoord_u = midUV.x; vertices[index3].iris_midcoord_u = midUV.x; vertices[index1].iris_midcoord_v = midUV.y; vertices[index2].iris_midcoord_v = midUV.y; vertices[index3].iris_midcoord_v = midUV.y; } uint computeTangentSmooth(vec3 pos1, vec3 pos2, vec3 pos3, vec2 uv1, vec2 uv2, vec2 uv3, vec3 normal) { float dot1 = dot(pos1, normal); float dot2 = dot(pos2, normal); float dot3 = dot(pos3, normal); pos1 -= dot1 * normal; pos2 -= dot2 * normal; pos3 -= dot3 * normal; vec3 edge1 = pos2 - pos1; vec3 edge2 = pos3 - pos1; vec2 dUV1 = uv2 - uv1; vec2 dUV2 = uv3 - uv1; float fdenom = dUV1.x * dUV2.y - dUV2.x * dUV1.y; float f = fdenom == 0.0 ? 1.0 : 1.0 / fdenom; vec3 tangent = normalize (f * (dUV2.y * edge1 - dUV1.y * edge2)); vec3 aBitangent = normalize (f * (-dUV2.x * edge1 + dUV1.x * edge2)); vec3 pBitangent = cross (tangent, normal); vec4 tangent4 = vec4 (tangent, dot(aBitangent, pBitangent) < 0.0 ? -1.0 : 1.0); return packSnorm4x8(tangent4); } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/compat/processing/iris_glyph_quad_processing_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; int uv2; uint normal; uint iris_entity_0; uint iris_entity_1; float iris_midcoord_u; float iris_midcoord_v; uint iris_at_tangent; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict buffer Vertices { Vertex vertices[]; }; layout(location=0) uniform uint polygonCount; layout(location=1) uniform uint vertexOffset; void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 4u; if (index >= polygonCount) { return; } uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; uint index4 = vertexOffset + base + 3u; Vertex vertex1 = vertices[index1]; Vertex vertex2 = vertices[index2]; Vertex vertex3 = vertices[index3]; Vertex vertex4 = vertices[index4]; vec3 pos1 = vec3(vertex1.x, vertex1.y, vertex1.z); vec3 pos2 = vec3(vertex2.x, vertex2.y, vertex2.z); vec3 pos3 = vec3(vertex3.x, vertex3.y, vertex3.z); vec2 uv1 = vec2(vertex1.u0, vertex1.v0); vec2 uv2 = vec2(vertex2.u0, vertex2.v0); vec2 uv3 = vec2(vertex3.u0, vertex3.v0); vec2 uv4 = vec2(vertex4.u0, vertex4.v0); vec2 midUV = (uv1 + uv2 + uv3 + uv4) / 4; vec3 normal = normalize(cross(pos2 - pos1, pos3 - pos1)); uint packedNormal = packSnorm4x8(vec4(normal, 0.0)); vec3 edge1 = pos2 - pos1; vec3 edge2 = pos3 - pos1; vec2 dUV1 = uv2 - uv1; vec2 dUV2 = uv3 - uv1; float fdenom = dUV1.x * dUV2.y - dUV2.x * dUV1.y; float f = fdenom == 0.0 ? 1.0 : 1.0 / fdenom; vec3 tangent = normalize(f * (dUV2.y * edge1 - dUV1.y * edge2)); vec3 aBitangent = normalize(f * (-dUV2.x * edge1 + dUV1.x * edge2)); vec3 pBitangent = cross(tangent, normal); vec4 tangent4 = vec4(tangent, dot(aBitangent, pBitangent) < 0.0 ? -1.0 : 1.0); uint packedTangent = packSnorm4x8(tangent4); vertices[index1].normal = packedNormal; vertices[index2].normal = packedNormal; vertices[index3].normal = packedNormal; vertices[index4].normal = packedNormal; vertices[index1].iris_at_tangent = packedTangent; vertices[index2].iris_at_tangent = packedTangent; vertices[index3].iris_at_tangent = packedTangent; vertices[index4].iris_at_tangent = packedTangent; vertices[index1].iris_midcoord_u = midUV.x; vertices[index2].iris_midcoord_u = midUV.x; vertices[index3].iris_midcoord_u = midUV.x; vertices[index4].iris_midcoord_u = midUV.x; vertices[index1].iris_midcoord_v = midUV.y; vertices[index2].iris_midcoord_v = midUV.y; vertices[index3].iris_midcoord_v = midUV.y; vertices[index4].iris_midcoord_v = midUV.y; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/compat/processing/iris_glyph_triangle_processing_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; int uv2; uint normal; uint iris_entity_0; uint iris_entity_1; float iris_midcoord_u; float iris_midcoord_v; uint iris_at_tangent; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict buffer Vertices { Vertex vertices[]; }; layout(location=0) uniform uint polygonCount; layout(location=1) uniform uint vertexOffset; uint computeTangentSmooth(vec3 pos1, vec3 pos2, vec3 pos3, vec2 uv1, vec2 uv2, vec2 uv3, vec3 normal); void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 3u; if (index >= polygonCount) { return; } uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; Vertex vertex1 = vertices[index1]; Vertex vertex2 = vertices[index2]; Vertex vertex3 = vertices[index3]; vec3 pos1 = vec3(vertex1.x, vertex1.y, vertex1.z); vec3 pos2 = vec3(vertex2.x, vertex2.y, vertex2.z); vec3 pos3 = vec3(vertex3.x, vertex3.y, vertex3.z); vec2 uv1 = vec2(vertex1.u0, vertex1.v0); vec2 uv2 = vec2(vertex2.u0, vertex2.v0); vec2 uv3 = vec2(vertex3.u0, vertex3.v0); vec2 midUV = (uv1 + uv2 + uv3) / 3; vec3 normal = normalize(cross(pos2 - pos1, pos3 - pos1)); uint packedNormal = packSnorm4x8(vec4(normal, 0.0)); vertices[index1].normal = packedNormal; vertices[index2].normal = packedNormal; vertices[index3].normal = packedNormal; vertices[index1].iris_at_tangent = computeTangentSmooth(pos1, pos2, pos3, uv1, uv2, uv3, normal); vertices[index2].iris_at_tangent = computeTangentSmooth(pos1, pos2, pos3, uv1, uv2, uv3, normal); vertices[index3].iris_at_tangent = computeTangentSmooth(pos1, pos2, pos3, uv1, uv2, uv3, normal); vertices[index1].iris_midcoord_u = midUV.x; vertices[index2].iris_midcoord_u = midUV.x; vertices[index3].iris_midcoord_u = midUV.x; vertices[index1].iris_midcoord_v = midUV.y; vertices[index2].iris_midcoord_v = midUV.y; vertices[index3].iris_midcoord_v = midUV.y; } uint computeTangentSmooth(vec3 pos1, vec3 pos2, vec3 pos3, vec2 uv1, vec2 uv2, vec2 uv3, vec3 normal) { float dot1 = dot(pos1, normal); float dot2 = dot(pos2, normal); float dot3 = dot(pos3, normal); pos1 -= dot1 * normal; pos2 -= dot2 * normal; pos3 -= dot3 * normal; vec3 edge1 = pos2 - pos1; vec3 edge2 = pos3 - pos1; vec2 dUV1 = uv2 - uv1; vec2 dUV2 = uv3 - uv1; float fdenom = dUV1.x * dUV2.y - dUV2.x * dUV1.y; float f = fdenom == 0.0 ? 1.0 : 1.0 / fdenom; vec3 tangent = normalize (f * (dUV2.y * edge1 - dUV1.y * edge2)); vec3 aBitangent = normalize (f * (-dUV2.x * edge1 + dUV1.x * edge2)); vec3 pBitangent = cross (tangent, normal); vec4 tangent4 = vec4 (tangent, dot(aBitangent, pBitangent) < 0.0 ? -1.0 : 1.0); return packSnorm4x8(tangent4); } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/compat/transform/iris_block_vertex_transform_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; uint uv2; uint normal; uint iris_entity; uint iris_data_0; uint iris_data_1; uint iris_data_2; uint iris_data_3; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; layout(local_size_x = 128) in; layout(binding=0, std430) restrict readonly buffer VerticesIn { Vertex verticesIn[]; }; layout(binding=1, std430) restrict writeonly buffer VerticesOut { Vertex verticesOut[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=3, std430) restrict readonly buffer VaryingsIn { VaryingData varyingsIn[]; }; layout(binding=4, std430) restrict writeonly buffer VaryingsOut { VaryingData varyingsOut[]; }; layout(binding=5, std430) restrict readonly buffer Meshes { Vertex meshVertices[]; }; layout(location=0) uniform uint vertexCount; layout(location=1) uniform uint vertexOffset; layout(location=2) uniform uint varyingOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint vertexOut = indexIn + vertexOffset; uint varyingOut = indexIn + varyingOffset; if (indexIn >= vertexCount) { return; } int offset = varyingsIn[indexIn] .offset; uint reference = indexIn - offset; int sharing = varyingsIn[reference] .sharing; int mesh = varyingsIn[reference] .mesh; mat4 transformMatrix; mat3 normalMatrix; if (sharing != -1) { transformMatrix = sharings[sharing].transform; normalMatrix = sharings[sharing].normal; } else { transformMatrix = mat4(1.0); normalMatrix = mat3(1.0); } Vertex vertexIn; vec4 colorMesh; uvec2 uv2Mesh; if (mesh != -1) { vertexIn = meshVertices[mesh + offset]; colorMesh = unpackUnorm4x8 ( vertexIn.color); uv2Mesh = floatBitsToUint (unpackSnorm2x16( vertexIn.uv2)); } else { vertexIn = verticesIn[indexIn]; colorMesh = vec4 (1.0); uv2Mesh = uvec2 (0u); } vec4 colorIn = unpackUnorm4x8 ( verticesIn[reference].color); uvec2 uv2In = floatBitsToUint (unpackSnorm2x16( verticesIn[reference].uv2)); vec4 posOut = transformMatrix * vec4 (vertexIn.x, vertexIn.y, vertexIn.z, 1.0); vec3 normalOut = normalMatrix * unpackSnorm4x8(vertexIn.normal).xyz; vec4 colorOut = colorMesh * colorIn; uvec2 uv2Out = max (uv2In, uv2Mesh); verticesOut[vertexOut].x = posOut.x; verticesOut[vertexOut].y = posOut.y; verticesOut[vertexOut].z = posOut.z; verticesOut[vertexOut].u0 = vertexIn.u0; verticesOut[vertexOut].v0 = vertexIn.v0; verticesOut[vertexOut].color = packUnorm4x8 (colorOut); // verticesOut[vertexOut].uv1 = verticesIn[reference].uv1; verticesOut[vertexOut].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); verticesOut[vertexOut].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); verticesOut[vertexOut].iris_entity = -1; varyingsOut[varyingOut].offset = offset; varyingsOut[varyingOut].noCull = varyingsIn[reference].noCull; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/compat/transform/iris_entity_vertex_transform_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; uint uv1; uint uv2; uint normal; uint iris_entity_0; uint iris_entity_1; uint iris_data_2; uint iris_data_3; uint iris_data_4; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; layout(local_size_x = 128) in; layout(binding=0, std430) restrict readonly buffer VerticesIn { Vertex verticesIn[]; }; layout(binding=1, std430) restrict writeonly buffer VerticesOut { Vertex verticesOut[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=3, std430) restrict readonly buffer VaryingsIn { VaryingData varyingsIn[]; }; layout(binding=4, std430) restrict writeonly buffer VaryingsOut { VaryingData varyingsOut[]; }; layout(binding=5, std430) restrict readonly buffer Meshes { Vertex meshVertices[]; }; layout(location=0) uniform uint vertexCount; layout(location=1) uniform uint vertexOffset; layout(location=2) uniform uint varyingOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint vertexOut = indexIn + vertexOffset; uint varyingOut = indexIn + varyingOffset; if (indexIn >= vertexCount) { return; } int offset = varyingsIn[indexIn] .offset; uint reference = indexIn - offset; int sharing = varyingsIn[reference] .sharing; int mesh = varyingsIn[reference] .mesh; mat4 transformMatrix; mat3 normalMatrix; if (sharing != -1) { transformMatrix = sharings[sharing].transform; normalMatrix = sharings[sharing].normal; } else { transformMatrix = mat4(1.0); normalMatrix = mat3(1.0); } Vertex vertexIn; vec4 colorMesh; uvec2 uv2Mesh; if (mesh != -1) { vertexIn = meshVertices[mesh + offset]; colorMesh = unpackUnorm4x8 ( vertexIn.color); uv2Mesh = floatBitsToUint (unpackSnorm2x16( vertexIn.uv2)); } else { vertexIn = verticesIn[indexIn]; colorMesh = vec4 (1.0); uv2Mesh = uvec2 (0u); } vec4 colorIn = unpackUnorm4x8 ( verticesIn[reference].color); uvec2 uv2In = floatBitsToUint (unpackSnorm2x16( verticesIn[reference].uv2)); vec4 posOut = transformMatrix * vec4 (vertexIn.x, vertexIn.y, vertexIn.z, 1.0); vec3 normalOut = normalMatrix * unpackSnorm4x8(vertexIn.normal).xyz; vec4 colorOut = colorMesh * colorIn; uvec2 uv2Out = max (uv2In, uv2Mesh); verticesOut[vertexOut].x = posOut.x; verticesOut[vertexOut].y = posOut.y; verticesOut[vertexOut].z = posOut.z; verticesOut[vertexOut].u0 = vertexIn.u0; verticesOut[vertexOut].v0 = vertexIn.v0; verticesOut[vertexOut].color = packUnorm4x8 (colorOut); verticesOut[vertexOut].uv1 = verticesIn[reference].uv1; verticesOut[vertexOut].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); verticesOut[vertexOut].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); verticesOut[vertexOut].iris_entity_0 = verticesIn[reference].iris_entity_0; verticesOut[vertexOut].iris_entity_1 = verticesIn[reference].iris_entity_1; varyingsOut[varyingOut].offset = offset; varyingsOut[varyingOut].noCull = varyingsIn[reference].noCull; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/compat/transform/iris_glyph_vertex_transform_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; uint uv2; uint normal; uint iris_entity_0; uint iris_entity_1; uint iris_data_2; uint iris_data_3; uint iris_data_4; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; layout(local_size_x = 128) in; layout(binding=0, std430) restrict readonly buffer VerticesIn { Vertex verticesIn[]; }; layout(binding=1, std430) restrict writeonly buffer VerticesOut { Vertex verticesOut[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=3, std430) restrict readonly buffer VaryingsIn { VaryingData varyingsIn[]; }; layout(binding=4, std430) restrict writeonly buffer VaryingsOut { VaryingData varyingsOut[]; }; layout(binding=5, std430) restrict readonly buffer Meshes { Vertex meshVertices[]; }; layout(location=0) uniform uint vertexCount; layout(location=1) uniform uint vertexOffset; layout(location=2) uniform uint varyingOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint vertexOut = indexIn + vertexOffset; uint varyingOut = indexIn + varyingOffset; if (indexIn >= vertexCount) { return; } int offset = varyingsIn[indexIn] .offset; uint reference = indexIn - offset; int sharing = varyingsIn[reference] .sharing; int mesh = varyingsIn[reference] .mesh; mat4 transformMatrix; // mat3 normalMatrix; if (sharing != -1) { transformMatrix = sharings[sharing].transform; // normalMatrix = sharings[sharing].normal; } else { transformMatrix = mat4(1.0); // normalMatrix = mat3(1.0); } Vertex vertexIn; vec4 colorMesh; uvec2 uv2Mesh; if (mesh != -1) { vertexIn = meshVertices[mesh + offset]; colorMesh = unpackUnorm4x8 ( vertexIn.color); uv2Mesh = floatBitsToUint (unpackSnorm2x16( vertexIn.uv2)); } else { vertexIn = verticesIn[indexIn]; colorMesh = vec4 (1.0); uv2Mesh = uvec2 (0u); } vec4 colorIn = unpackUnorm4x8 ( verticesIn[reference].color); uvec2 uv2In = floatBitsToUint (unpackSnorm2x16( verticesIn[reference].uv2)); vec4 posOut = transformMatrix * vec4 (vertexIn.x, vertexIn.y, vertexIn.z, 1.0); // vec3 normalOut = normalMatrix * unpackSnorm4x8(vertexIn.normal).xyz; vec4 colorOut = colorMesh * colorIn; uvec2 uv2Out = max (uv2In, uv2Mesh); verticesOut[vertexOut].x = posOut.x; verticesOut[vertexOut].y = posOut.y; verticesOut[vertexOut].z = posOut.z; verticesOut[vertexOut].u0 = vertexIn.u0; verticesOut[vertexOut].v0 = vertexIn.v0; verticesOut[vertexOut].color = packUnorm4x8 (colorOut); // verticesOut[vertexOut].uv1 = verticesIn[reference].uv1; verticesOut[vertexOut].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); // verticesOut[vertexOut].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); verticesOut[vertexOut].iris_entity_0 = verticesIn[reference].iris_entity_0; verticesOut[vertexOut].iris_entity_1 = verticesIn[reference].iris_entity_1; varyingsOut[varyingOut].offset = offset; varyingsOut[varyingOut].noCull = varyingsIn[reference].noCull; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/compat/uploading/iris_block_mesh_uploading_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; uint uv2; uint normal; uint iris_entity; uint iris_data_0; uint iris_data_1; uint iris_data_2; uint iris_data_3; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct MeshInfo { int sharing; int noCull; uint color; uint uv1; uint uv2; }; layout(local_size_x = 128) in; layout(binding=1, std430) writeonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) writeonly buffer Varyings { VaryingData varyings[]; }; layout(binding=7, std430) readonly buffer Meshes { Vertex meshVertices[]; }; layout(binding=8, std430) readonly buffer MeshInfos { MeshInfo meshInfos[]; }; layout(location=0) uniform uint meshCount; layout(location=1) uniform uint meshSize; layout(location=2) uniform uint vertexOffset; layout(location=3) uniform uint varyingOffset; layout(location=4) uniform uint meshOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint meshIndex = indexIn / meshSize; uint index = indexIn % meshSize; if (meshIndex >= meshCount) { return; } Vertex vertex = meshVertices [meshOffset + index]; MeshInfo meshInfo = meshInfos [meshIndex]; SharingData sharingData = sharings [meshInfo.sharing]; uint vertexIndex = index + meshIndex * meshSize + vertexOffset; uint varyingIndex = index + meshIndex * meshSize + varyingOffset; vec4 colorIn = unpackUnorm4x8 (meshInfo .color); vec4 colorMesh = unpackUnorm4x8 (vertex .color); uvec2 uv2In = floatBitsToUint (unpackSnorm2x16(meshInfo .uv2)); uvec2 uv2Mesh = floatBitsToUint (unpackSnorm2x16(vertex .uv2)); vec4 colorOut = colorIn * colorMesh; uvec2 uv2Out = max(uv2In, uv2Mesh); vec4 posOut = sharingData.transform * vec4 (vertex.x, vertex.y, vertex.z, 1.0); vec3 normalOut = sharingData.normal * unpackSnorm4x8(vertex.normal).xyz; vertices[vertexIndex].x = posOut.x; vertices[vertexIndex].y = posOut.y; vertices[vertexIndex].z = posOut.z; vertices[vertexIndex].color = packUnorm4x8(colorOut); vertices[vertexIndex].u0 = vertex.u0; vertices[vertexIndex].v0 = vertex.v0; // vertices[vertexIndex].uv1 = meshInfo.uv1; vertices[vertexIndex].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); vertices[vertexIndex].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); // vertices[vertexIndex].iris_entity_0 = vertex.iris_entity_0; // vertices[vertexIndex].iris_entity_1 = vertex.iris_entity_1; vertices[vertexIndex].iris_entity = -1; varyings[varyingIndex].offset = 0; varyings[varyingIndex].sharing = meshInfo.sharing; varyings[varyingIndex].noCull = meshInfo.noCull; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/compat/uploading/iris_entity_mesh_uploading_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; uint uv1; uint uv2; uint normal; uint iris_entity_0; uint iris_entity_1; uint iris_data_2; uint iris_data_3; uint iris_data_4; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct MeshInfo { int sharing; int noCull; uint color; uint uv1; uint uv2; uint iris_entity_0; uint iris_entity_1; }; layout(local_size_x = 128) in; layout(binding=1, std430) writeonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) writeonly buffer Varyings { VaryingData varyings[]; }; layout(binding=7, std430) readonly buffer Meshes { Vertex meshVertices[]; }; layout(binding=8, std430) readonly buffer MeshInfos { MeshInfo meshInfos[]; }; layout(location=0) uniform uint meshCount; layout(location=1) uniform uint meshSize; layout(location=2) uniform uint vertexOffset; layout(location=3) uniform uint varyingOffset; layout(location=4) uniform uint meshOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint meshIndex = indexIn / meshSize; uint index = indexIn % meshSize; if (meshIndex >= meshCount) { return; } Vertex vertex = meshVertices [meshOffset + index]; MeshInfo meshInfo = meshInfos [meshIndex]; SharingData sharingData = sharings [meshInfo.sharing]; uint vertexIndex = index + meshIndex * meshSize + vertexOffset; uint varyingIndex = index + meshIndex * meshSize + varyingOffset; vec4 colorIn = unpackUnorm4x8 (meshInfo .color); vec4 colorMesh = unpackUnorm4x8 (vertex .color); uvec2 uv2In = floatBitsToUint (unpackSnorm2x16(meshInfo .uv2)); uvec2 uv2Mesh = floatBitsToUint (unpackSnorm2x16(vertex .uv2)); vec4 colorOut = colorIn * colorMesh; uvec2 uv2Out = max(uv2In, uv2Mesh); vec4 posOut = sharingData.transform * vec4 (vertex.x, vertex.y, vertex.z, 1.0); vec3 normalOut = sharingData.normal * unpackSnorm4x8(vertex.normal).xyz; vertices[vertexIndex].x = posOut.x; vertices[vertexIndex].y = posOut.y; vertices[vertexIndex].z = posOut.z; vertices[vertexIndex].color = packUnorm4x8(colorOut); vertices[vertexIndex].u0 = vertex.u0; vertices[vertexIndex].v0 = vertex.v0; vertices[vertexIndex].uv1 = meshInfo.uv1; vertices[vertexIndex].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); vertices[vertexIndex].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); vertices[vertexIndex].iris_entity_0 = meshInfo.iris_entity_0; vertices[vertexIndex].iris_entity_1 = meshInfo.iris_entity_1; varyings[varyingIndex].offset = 0; varyings[varyingIndex].sharing = meshInfo.sharing; varyings[varyingIndex].noCull = meshInfo.noCull; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/compat/uploading/iris_glyph_mesh_uploading_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; uint uv2; uint normal; uint iris_entity_0; uint iris_entity_1; uint iris_data_2; uint iris_data_3; uint iris_data_4; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct MeshInfo { int sharing; int noCull; uint color; uint uv1; uint uv2; uint iris_entity_0; uint iris_entity_1; }; layout(local_size_x = 128) in; layout(binding=1, std430) writeonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) writeonly buffer Varyings { VaryingData varyings[]; }; layout(binding=7, std430) readonly buffer Meshes { Vertex meshVertices[]; }; layout(binding=8, std430) readonly buffer MeshInfos { MeshInfo meshInfos[]; }; layout(location=0) uniform uint meshCount; layout(location=1) uniform uint meshSize; layout(location=2) uniform uint vertexOffset; layout(location=3) uniform uint varyingOffset; layout(location=4) uniform uint meshOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint meshIndex = indexIn / meshSize; uint index = indexIn % meshSize; if (meshIndex >= meshCount) { return; } Vertex vertex = meshVertices [meshOffset + index]; MeshInfo meshInfo = meshInfos [meshIndex]; SharingData sharingData = sharings [meshInfo.sharing]; uint vertexIndex = index + meshIndex * meshSize + vertexOffset; uint varyingIndex = index + meshIndex * meshSize + varyingOffset; vec4 colorIn = unpackUnorm4x8 (meshInfo .color); vec4 colorMesh = unpackUnorm4x8 (vertex .color); uvec2 uv2In = floatBitsToUint (unpackSnorm2x16(meshInfo .uv2)); uvec2 uv2Mesh = floatBitsToUint (unpackSnorm2x16(vertex .uv2)); vec4 colorOut = colorIn * colorMesh; uvec2 uv2Out = max(uv2In, uv2Mesh); vec4 posOut = sharingData.transform * vec4 (vertex.x, vertex.y, vertex.z, 1.0); // vec3 normalOut = sharingData.normal * unpackSnorm4x8(vertex.normal).xyz; vertices[vertexIndex].x = posOut.x; vertices[vertexIndex].y = posOut.y; vertices[vertexIndex].z = posOut.z; vertices[vertexIndex].color = packUnorm4x8(colorOut); vertices[vertexIndex].u0 = vertex.u0; vertices[vertexIndex].v0 = vertex.v0; // vertices[vertexIndex].uv1 = meshInfo.uv1; vertices[vertexIndex].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); // vertices[vertexIndex].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); vertices[vertexIndex].iris_entity_0 = meshInfo.iris_entity_0; vertices[vertexIndex].iris_entity_1 = meshInfo.iris_entity_1; varyings[varyingIndex].offset = 0; varyings[varyingIndex].sharing = meshInfo.sharing; varyings[varyingIndex].noCull = meshInfo.noCull; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/culling/block_quad_culling_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; int uv2; uint normal; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct Polygon { uint vertex1; uint vertex2; uint vertex3; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict readonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) restrict readonly buffer Varyings { VaryingData varyings[]; }; layout(binding=6, std430) restrict writeonly buffer PolygonsOut { Polygon polygonsOut[]; }; layout(binding=0, offset=0) uniform atomic_uint indexCounter; layout(location=0) uniform mat4 viewMatrix; layout(location=1) uniform mat4 projectMatrix; layout(location=2) uniform uint polygonCount; layout(location=3) uniform uint vertexOffset; layout(location=4) uniform uint varyingOffset; void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 4u; if (index >= polygonCount) { return; } uint index0 = varyingOffset + base + 0u; uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; uint index4 = vertexOffset + base + 3u; uint noCull = varyings[index0 - varyings[index0].offset].noCull; Vertex vertex1 = vertices[index1]; Vertex vertex2 = vertices[index2]; Vertex vertex3 = vertices[index3]; Vertex vertex4 = vertices[index4]; mat4 matrix = projectMatrix * viewMatrix; vec4 pos1 = matrix * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0); vec4 pos2 = matrix * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0); vec4 pos3 = matrix * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0); vec4 pos4 = matrix * vec4(vertex4.x, vertex4.y, vertex4.z, 1.0); float det1 = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw)); float det2 = determinant(mat3(pos3.xyw, pos4.xyw, pos1.xyw)); if (noCull > 0u || det1 > 0.0 || det2 > 0.0) { uint indexOut = atomicCounterAdd(indexCounter, 6u) / 3u; polygonsOut[indexOut + 0].vertex1 = index1; polygonsOut[indexOut + 0].vertex2 = index2; polygonsOut[indexOut + 0].vertex3 = index3; polygonsOut[indexOut + 1].vertex1 = index3; polygonsOut[indexOut + 1].vertex2 = index4; polygonsOut[indexOut + 1].vertex3 = index1; } } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/culling/block_triangle_culling_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; int uv2; uint normal; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct Polygon { uint vertex1; uint vertex2; uint vertex3; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict readonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) restrict readonly buffer Varyings { VaryingData varyings[]; }; layout(binding=6, std430) restrict writeonly buffer PolygonsOut { Polygon polygonsOut[]; }; layout(binding=0, offset=0) uniform atomic_uint indexCounter; layout(location=0) uniform mat4 viewMatrix; layout(location=1) uniform mat4 projectMatrix; layout(location=2) uniform uint polygonCount; layout(location=3) uniform uint vertexOffset; layout(location=4) uniform uint varyingOffset; void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 3u; if (index >= polygonCount) { return; } uint index0 = varyingOffset + base + 0u; uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; uint noCull = varyings[index0 - varyings[index0].offset].noCull; Vertex vertex1 = vertices[index1]; Vertex vertex2 = vertices[index2]; Vertex vertex3 = vertices[index3]; mat4 matrix = projectMatrix * viewMatrix; vec4 pos1 = matrix * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0); vec4 pos2 = matrix * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0); vec4 pos3 = matrix * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0); float det = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw)); if (noCull > 0u || det > 0.0) { uint indexOut = atomicCounterAdd(indexCounter, 3u) / 3u; polygonsOut[indexOut + 0].vertex1 = index1; polygonsOut[indexOut + 0].vertex2 = index2; polygonsOut[indexOut + 0].vertex3 = index3; } } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/culling/entity_quad_culling_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; int uv1; int uv2; uint normal; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct Polygon { uint vertex1; uint vertex2; uint vertex3; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict readonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) restrict readonly buffer Varyings { VaryingData varyings[]; }; layout(binding=6, std430) restrict writeonly buffer PolygonsOut { Polygon polygonsOut[]; }; layout(binding=0, offset=0) uniform atomic_uint indexCounter; layout(location=0) uniform mat4 viewMatrix; layout(location=1) uniform mat4 projectMatrix; layout(location=2) uniform uint polygonCount; layout(location=3) uniform uint vertexOffset; layout(location=4) uniform uint varyingOffset; void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 4u; if (index >= polygonCount) { return; } uint index0 = varyingOffset + base + 0u; uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; uint index4 = vertexOffset + base + 3u; uint noCull = varyings[index0 - varyings[index0].offset].noCull; Vertex vertex1 = vertices[index1]; Vertex vertex2 = vertices[index2]; Vertex vertex3 = vertices[index3]; Vertex vertex4 = vertices[index4]; mat4 matrix = projectMatrix * viewMatrix; vec4 pos1 = matrix * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0); vec4 pos2 = matrix * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0); vec4 pos3 = matrix * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0); vec4 pos4 = matrix * vec4(vertex4.x, vertex4.y, vertex4.z, 1.0); float det1 = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw)); float det2 = determinant(mat3(pos3.xyw, pos4.xyw, pos1.xyw)); if (noCull > 0u || det1 > 0.0 || det2 > 0.0) { uint indexOut = atomicCounterAdd(indexCounter, 6u) / 3u; polygonsOut[indexOut + 0].vertex1 = index1; polygonsOut[indexOut + 0].vertex2 = index2; polygonsOut[indexOut + 0].vertex3 = index3; polygonsOut[indexOut + 1].vertex1 = index3; polygonsOut[indexOut + 1].vertex2 = index4; polygonsOut[indexOut + 1].vertex3 = index1; } } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/culling/entity_triangle_culling_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; int uv1; int uv2; uint normal; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct Polygon { uint vertex1; uint vertex2; uint vertex3; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict readonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) restrict readonly buffer Varyings { VaryingData varyings[]; }; layout(binding=6, std430) restrict writeonly buffer PolygonsOut { Polygon polygonsOut[]; }; layout(binding=0, offset=0) uniform atomic_uint indexCounter; layout(location=0) uniform mat4 viewMatrix; layout(location=1) uniform mat4 projectMatrix; layout(location=2) uniform uint polygonCount; layout(location=3) uniform uint vertexOffset; layout(location=4) uniform uint varyingOffset; void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 3u; if (index >= polygonCount) { return; } uint index0 = varyingOffset + base + 0u; uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; uint noCull = varyings[index0 - varyings[index0].offset].noCull; Vertex vertex1 = vertices[index1]; Vertex vertex2 = vertices[index2]; Vertex vertex3 = vertices[index3]; mat4 matrix = projectMatrix * viewMatrix; vec4 pos1 = matrix * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0); vec4 pos2 = matrix * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0); vec4 pos3 = matrix * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0); float det = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw)); if (noCull > 0u || det > 0.0) { uint indexOut = atomicCounterAdd(indexCounter, 3u) / 3u; polygonsOut[indexOut + 0].vertex1 = index1; polygonsOut[indexOut + 0].vertex2 = index2; polygonsOut[indexOut + 0].vertex3 = index3; } } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/culling/pass_through_quad_culling_shader.compute ================================================ #version 460 core struct Polygon { uint vertex1; uint vertex2; uint vertex3; uint vertex4; uint vertex5; uint vertex6; }; layout(local_size_x = 128) in; layout(binding=6, std430) restrict writeonly buffer PolygonsOut { Polygon polygonsOut[]; }; layout(binding=0, offset=0) uniform atomic_uint indexCounter; layout(location=0) uniform uint polygonCount; layout(location=1) uniform uint vertexOffset; void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 4u; if (index >= polygonCount) { return; } uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; uint index4 = vertexOffset + base + 3u; atomicCounterAdd(indexCounter, 6u); polygonsOut[index].vertex1 = index1; polygonsOut[index].vertex2 = index2; polygonsOut[index].vertex3 = index3; polygonsOut[index].vertex4 = index3; polygonsOut[index].vertex5 = index4; polygonsOut[index].vertex6 = index1; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/culling/pass_through_triangle_culling_shader.compute ================================================ #version 460 core struct Polygon { uint vertex1; uint vertex2; uint vertex3; }; layout(local_size_x = 128) in; layout(binding=6, std430) restrict writeonly buffer PolygonsOut { Polygon polygonsOut[]; }; layout(binding=0, offset=0) uniform atomic_uint indexCounter; layout(location=0) uniform uint polygonCount; layout(location=1) uniform uint vertexOffset; void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 3u; if (index >= polygonCount) { return; } uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; atomicCounterAdd(indexCounter, 3u); polygonsOut[index].vertex1 = index1; polygonsOut[index].vertex2 = index2; polygonsOut[index].vertex3 = index3; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/culling/pos_tex_color_quad_culling_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; float u0; float v0; uint color; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct Polygon { uint vertex1; uint vertex2; uint vertex3; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict readonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) restrict readonly buffer Varyings { VaryingData varyings[]; }; layout(binding=6, std430) restrict writeonly buffer PolygonsOut { Polygon polygonsOut[]; }; layout(binding=0, offset=0) uniform atomic_uint indexCounter; layout(location=0) uniform mat4 viewMatrix; layout(location=1) uniform mat4 projectMatrix; layout(location=2) uniform uint polygonCount; layout(location=3) uniform uint vertexOffset; layout(location=4) uniform uint varyingOffset; void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 4u; if (index >= polygonCount) { return; } uint index0 = varyingOffset + base + 0u; uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; uint index4 = vertexOffset + base + 3u; uint noCull = varyings[index0 - varyings[index0].offset].noCull; Vertex vertex1 = vertices[index1]; Vertex vertex2 = vertices[index2]; Vertex vertex3 = vertices[index3]; Vertex vertex4 = vertices[index4]; mat4 matrix = projectMatrix * viewMatrix; vec4 pos1 = matrix * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0); vec4 pos2 = matrix * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0); vec4 pos3 = matrix * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0); vec4 pos4 = matrix * vec4(vertex4.x, vertex4.y, vertex4.z, 1.0); float det1 = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw)); float det2 = determinant(mat3(pos3.xyw, pos4.xyw, pos1.xyw)); if (noCull > 0u || det1 > 0.0 || det2 > 0.0) { uint indexOut = atomicCounterAdd(indexCounter, 6u) / 3u; polygonsOut[indexOut + 0].vertex1 = index1; polygonsOut[indexOut + 0].vertex2 = index2; polygonsOut[indexOut + 0].vertex3 = index3; polygonsOut[indexOut + 1].vertex1 = index3; polygonsOut[indexOut + 1].vertex2 = index4; polygonsOut[indexOut + 1].vertex3 = index1; } } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/culling/pos_tex_color_triangle_culling_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; float u0; float v0; uint color; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct Polygon { uint vertex1; uint vertex2; uint vertex3; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict readonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) restrict readonly buffer Varyings { VaryingData varyings[]; }; layout(binding=6, std430) restrict writeonly buffer PolygonsOut { Polygon polygonsOut[]; }; layout(binding=0, offset=0) uniform atomic_uint indexCounter; layout(location=0) uniform mat4 viewMatrix; layout(location=1) uniform mat4 projectMatrix; layout(location=2) uniform uint polygonCount; layout(location=3) uniform uint vertexOffset; layout(location=4) uniform uint varyingOffset; void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 3u; if (index >= polygonCount) { return; } uint index0 = varyingOffset + base + 0u; uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; uint noCull = varyings[index0 - varyings[index0].offset].noCull; Vertex vertex1 = vertices[index1]; Vertex vertex2 = vertices[index2]; Vertex vertex3 = vertices[index3]; mat4 matrix = projectMatrix * viewMatrix; vec4 pos1 = matrix * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0); vec4 pos2 = matrix * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0); vec4 pos3 = matrix * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0); float det = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw)); if (noCull > 0u || det > 0.0) { uint indexOut = atomicCounterAdd(indexCounter, 3u) / 3u; polygonsOut[indexOut + 0].vertex1 = index1; polygonsOut[indexOut + 0].vertex2 = index2; polygonsOut[indexOut + 0].vertex3 = index3; } } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/culling/pos_tex_quad_culling_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; float u0; float v0; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct Polygon { uint vertex1; uint vertex2; uint vertex3; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict readonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) restrict readonly buffer Varyings { VaryingData varyings[]; }; layout(binding=6, std430) restrict writeonly buffer PolygonsOut { Polygon polygonsOut[]; }; layout(binding=0, offset=0) uniform atomic_uint indexCounter; layout(location=0) uniform mat4 viewMatrix; layout(location=1) uniform mat4 projectMatrix; layout(location=2) uniform uint polygonCount; layout(location=3) uniform uint vertexOffset; layout(location=4) uniform uint varyingOffset; void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 4u; if (index >= polygonCount) { return; } uint index0 = varyingOffset + base + 0u; uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; uint index4 = vertexOffset + base + 3u; uint noCull = varyings[index0 - varyings[index0].offset].noCull; Vertex vertex1 = vertices[index1]; Vertex vertex2 = vertices[index2]; Vertex vertex3 = vertices[index3]; Vertex vertex4 = vertices[index4]; mat4 matrix = projectMatrix * viewMatrix; vec4 pos1 = matrix * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0); vec4 pos2 = matrix * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0); vec4 pos3 = matrix * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0); vec4 pos4 = matrix * vec4(vertex4.x, vertex4.y, vertex4.z, 1.0); float det1 = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw)); float det2 = determinant(mat3(pos3.xyw, pos4.xyw, pos1.xyw)); if (noCull > 0u || det1 > 0.0 || det2 > 0.0) { uint indexOut = atomicCounterAdd(indexCounter, 6u) / 3u; polygonsOut[indexOut + 0].vertex1 = index1; polygonsOut[indexOut + 0].vertex2 = index2; polygonsOut[indexOut + 0].vertex3 = index3; polygonsOut[indexOut + 1].vertex1 = index3; polygonsOut[indexOut + 1].vertex2 = index4; polygonsOut[indexOut + 1].vertex3 = index1; } } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/culling/pos_tex_triangle_culling_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; float u0; float v0; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct Polygon { uint vertex1; uint vertex2; uint vertex3; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict readonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) restrict readonly buffer Varyings { VaryingData varyings[]; }; layout(binding=6, std430) restrict writeonly buffer PolygonsOut { Polygon polygonsOut[]; }; layout(binding=0, offset=0) uniform atomic_uint indexCounter; layout(location=0) uniform mat4 viewMatrix; layout(location=1) uniform mat4 projectMatrix; layout(location=2) uniform uint polygonCount; layout(location=3) uniform uint vertexOffset; layout(location=4) uniform uint varyingOffset; void main() { uint index = gl_GlobalInvocationID.x; uint base = index * 3u; if (index >= polygonCount) { return; } uint index0 = varyingOffset + base + 0u; uint index1 = vertexOffset + base + 0u; uint index2 = vertexOffset + base + 1u; uint index3 = vertexOffset + base + 2u; uint noCull = varyings[index0 - varyings[index0].offset].noCull; Vertex vertex1 = vertices[index1]; Vertex vertex2 = vertices[index2]; Vertex vertex3 = vertices[index3]; mat4 matrix = projectMatrix * viewMatrix; vec4 pos1 = matrix * vec4(vertex1.x, vertex1.y, vertex1.z, 1.0); vec4 pos2 = matrix * vec4(vertex2.x, vertex2.y, vertex2.z, 1.0); vec4 pos3 = matrix * vec4(vertex3.x, vertex3.y, vertex3.z, 1.0); float det = determinant(mat3(pos1.xyw, pos2.xyw, pos3.xyw)); if (noCull > 0u || det > 0.0) { uint indexOut = atomicCounterAdd(indexCounter, 3u) / 3u; polygonsOut[indexOut + 0].vertex1 = index1; polygonsOut[indexOut + 0].vertex2 = index2; polygonsOut[indexOut + 0].vertex3 = index3; } } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/transform/block_vertex_transform_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; uint uv2; uint normal; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; layout(local_size_x = 128) in; layout(binding=0, std430) restrict readonly buffer VerticesIn { Vertex verticesIn[]; }; layout(binding=1, std430) restrict writeonly buffer VerticesOut { Vertex verticesOut[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=3, std430) restrict readonly buffer VaryingsIn { VaryingData varyingsIn[]; }; layout(binding=4, std430) restrict writeonly buffer VaryingsOut { VaryingData varyingsOut[]; }; layout(binding=5, std430) restrict readonly buffer Meshes { Vertex meshVertices[]; }; layout(location=0) uniform uint vertexCount; layout(location=1) uniform uint vertexOffset; layout(location=2) uniform uint varyingOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint vertexOut = indexIn + vertexOffset; uint varyingOut = indexIn + varyingOffset; if (indexIn >= vertexCount) { return; } int offset = varyingsIn[indexIn] .offset; uint reference = indexIn - offset; int sharing = varyingsIn[reference] .sharing; int mesh = varyingsIn[reference] .mesh; mat4 transformMatrix; mat3 normalMatrix; if (sharing != -1) { transformMatrix = sharings[sharing].transform; normalMatrix = sharings[sharing].normal; } else { transformMatrix = mat4(1.0); normalMatrix = mat3(1.0); } Vertex vertexIn; vec4 colorMesh; uvec2 uv2Mesh; if (mesh != -1) { vertexIn = meshVertices[mesh + offset]; colorMesh = unpackUnorm4x8 ( vertexIn.color); uv2Mesh = floatBitsToUint (unpackSnorm2x16( vertexIn.uv2)); } else { vertexIn = verticesIn[indexIn]; colorMesh = vec4 (1.0); uv2Mesh = uvec2 (0u); } vec4 colorIn = unpackUnorm4x8 ( verticesIn[reference].color); uvec2 uv2In = floatBitsToUint (unpackSnorm2x16( verticesIn[reference].uv2)); vec4 posOut = transformMatrix * vec4 (vertexIn.x, vertexIn.y, vertexIn.z, 1.0); vec3 normalOut = normalMatrix * unpackSnorm4x8(vertexIn.normal).xyz; vec4 colorOut = colorMesh * colorIn; uvec2 uv2Out = max (uv2In, uv2Mesh); verticesOut[vertexOut].x = posOut.x; verticesOut[vertexOut].y = posOut.y; verticesOut[vertexOut].z = posOut.z; verticesOut[vertexOut].u0 = vertexIn.u0; verticesOut[vertexOut].v0 = vertexIn.v0; verticesOut[vertexOut].color = packUnorm4x8 (colorOut); // verticesOut[vertexOut].uv1 = verticesIn[reference].uv1; verticesOut[vertexOut].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); verticesOut[vertexOut].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); varyingsOut[varyingOut].offset = offset; varyingsOut[varyingOut].noCull = varyingsIn[reference].noCull; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/transform/entity_vertex_transform_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; uint uv1; uint uv2; uint normal; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; layout(local_size_x = 128) in; layout(binding=0, std430) restrict readonly buffer VerticesIn { Vertex verticesIn[]; }; layout(binding=1, std430) restrict writeonly buffer VerticesOut { Vertex verticesOut[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=3, std430) restrict readonly buffer VaryingsIn { VaryingData varyingsIn[]; }; layout(binding=4, std430) restrict writeonly buffer VaryingsOut { VaryingData varyingsOut[]; }; layout(binding=5, std430) restrict readonly buffer Meshes { Vertex meshVertices[]; }; layout(location=0) uniform uint vertexCount; layout(location=1) uniform uint vertexOffset; layout(location=2) uniform uint varyingOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint vertexOut = indexIn + vertexOffset; uint varyingOut = indexIn + varyingOffset; if (indexIn >= vertexCount) { return; } int offset = varyingsIn[indexIn] .offset; uint reference = indexIn - offset; int sharing = varyingsIn[reference] .sharing; int mesh = varyingsIn[reference] .mesh; mat4 transformMatrix; mat3 normalMatrix; if (sharing != -1) { transformMatrix = sharings[sharing].transform; normalMatrix = sharings[sharing].normal; } else { transformMatrix = mat4(1.0); normalMatrix = mat3(1.0); } Vertex vertexIn; vec4 colorMesh; uvec2 uv2Mesh; if (mesh != -1) { vertexIn = meshVertices[mesh + offset]; colorMesh = unpackUnorm4x8 ( vertexIn.color); uv2Mesh = floatBitsToUint (unpackSnorm2x16( vertexIn.uv2)); } else { vertexIn = verticesIn[indexIn]; colorMesh = vec4 (1.0); uv2Mesh = uvec2 (0u); } vec4 colorIn = unpackUnorm4x8 ( verticesIn[reference].color); uvec2 uv2In = floatBitsToUint (unpackSnorm2x16( verticesIn[reference].uv2)); vec4 posOut = transformMatrix * vec4 (vertexIn.x, vertexIn.y, vertexIn.z, 1.0); vec3 normalOut = normalMatrix * unpackSnorm4x8(vertexIn.normal).xyz; vec4 colorOut = colorMesh * colorIn; uvec2 uv2Out = max (uv2In, uv2Mesh); verticesOut[vertexOut].x = posOut.x; verticesOut[vertexOut].y = posOut.y; verticesOut[vertexOut].z = posOut.z; verticesOut[vertexOut].u0 = vertexIn.u0; verticesOut[vertexOut].v0 = vertexIn.v0; verticesOut[vertexOut].color = packUnorm4x8 (colorOut); verticesOut[vertexOut].uv1 = verticesIn[reference].uv1; verticesOut[vertexOut].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); verticesOut[vertexOut].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); varyingsOut[varyingOut].offset = offset; varyingsOut[varyingOut].noCull = varyingsIn[reference].noCull; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/transform/pos_color_tex_light_vertex_transform_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; uint uv2; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; layout(local_size_x = 128) in; layout(binding=0, std430) restrict readonly buffer VerticesIn { Vertex verticesIn[]; }; layout(binding=1, std430) restrict writeonly buffer VerticesOut { Vertex verticesOut[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=3, std430) restrict readonly buffer VaryingsIn { VaryingData varyingsIn[]; }; layout(binding=4, std430) restrict writeonly buffer VaryingsOut { VaryingData varyingsOut[]; }; layout(binding=5, std430) restrict readonly buffer Meshes { Vertex meshVertices[]; }; layout(location=0) uniform uint vertexCount; layout(location=1) uniform uint vertexOffset; layout(location=2) uniform uint varyingOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint vertexOut = indexIn + vertexOffset; uint varyingOut = indexIn + varyingOffset; if (indexIn >= vertexCount) { return; } int offset = varyingsIn[indexIn] .offset; uint reference = indexIn - offset; int sharing = varyingsIn[reference] .sharing; int mesh = varyingsIn[reference] .mesh; mat4 transformMatrix; // mat3 normalMatrix; if (sharing != -1) { transformMatrix = sharings[sharing].transform; // normalMatrix = sharings[sharing].normal; } else { transformMatrix = mat4(1.0); // normalMatrix = mat3(1.0); } Vertex vertexIn; vec4 colorMesh; uvec2 uv2Mesh; if (mesh != -1) { vertexIn = meshVertices[mesh + offset]; colorMesh = unpackUnorm4x8 ( vertexIn.color); uv2Mesh = floatBitsToUint (unpackSnorm2x16( vertexIn.uv2)); } else { vertexIn = verticesIn[indexIn]; colorMesh = vec4 (1.0); uv2Mesh = uvec2 (0u); } vec4 colorIn = unpackUnorm4x8 ( verticesIn[reference].color); uvec2 uv2In = floatBitsToUint (unpackSnorm2x16( verticesIn[reference].uv2)); vec4 posOut = transformMatrix * vec4 (vertexIn.x, vertexIn.y, vertexIn.z, 1.0); // vec3 normalOut = normalMatrix * unpackSnorm4x8(vertexIn.normal).xyz; vec4 colorOut = colorMesh * colorIn; uvec2 uv2Out = max (uv2In, uv2Mesh); verticesOut[vertexOut].x = posOut.x; verticesOut[vertexOut].y = posOut.y; verticesOut[vertexOut].z = posOut.z; verticesOut[vertexOut].u0 = vertexIn.u0; verticesOut[vertexOut].v0 = vertexIn.v0; verticesOut[vertexOut].color = packUnorm4x8 (colorOut); // verticesOut[vertexOut].uv1 = verticesIn[reference].uv1; verticesOut[vertexOut].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); // verticesOut[vertexOut].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); varyingsOut[varyingOut].offset = offset; varyingsOut[varyingOut].noCull = varyingsIn[reference].noCull; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/transform/pos_color_vertex_transform_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; layout(local_size_x = 128) in; layout(binding=0, std430) restrict readonly buffer VerticesIn { Vertex verticesIn[]; }; layout(binding=1, std430) restrict writeonly buffer VerticesOut { Vertex verticesOut[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=3, std430) restrict readonly buffer VaryingsIn { VaryingData varyingsIn[]; }; layout(binding=4, std430) restrict writeonly buffer VaryingsOut { VaryingData varyingsOut[]; }; layout(binding=5, std430) restrict readonly buffer Meshes { Vertex meshVertices[]; }; layout(location=0) uniform uint vertexCount; layout(location=1) uniform uint vertexOffset; layout(location=2) uniform uint varyingOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint vertexOut = indexIn + vertexOffset; uint varyingOut = indexIn + varyingOffset; if (indexIn >= vertexCount) { return; } int offset = varyingsIn[indexIn] .offset; uint reference = indexIn - offset; int sharing = varyingsIn[reference] .sharing; int mesh = varyingsIn[reference] .mesh; mat4 transformMatrix; // mat3 normalMatrix; if (sharing != -1) { transformMatrix = sharings[sharing].transform; // normalMatrix = sharings[sharing].normal; } else { transformMatrix = mat4(1.0); // normalMatrix = mat3(1.0); } Vertex vertexIn; vec4 colorMesh; // uvec2 uv2Mesh; if (mesh != -1) { vertexIn = meshVertices[mesh + offset]; colorMesh = unpackUnorm4x8 ( vertexIn.color); // uv2Mesh = floatBitsToUint (unpackSnorm2x16( vertexIn.uv2)); } else { vertexIn = verticesIn[indexIn]; colorMesh = vec4 (1.0); // uv2Mesh = uvec2 (0u); } vec4 colorIn = unpackUnorm4x8 ( verticesIn[reference].color); // uvec2 uv2In = floatBitsToUint (unpackSnorm2x16( verticesIn[reference].uv2)); vec4 posOut = transformMatrix * vec4 (vertexIn.x, vertexIn.y, vertexIn.z, 1.0); // vec3 normalOut = normalMatrix * unpackSnorm4x8(vertexIn.normal).xyz; vec4 colorOut = colorMesh * colorIn; // uvec2 uv2Out = max (uv2In, uv2Mesh); verticesOut[vertexOut].x = posOut.x; verticesOut[vertexOut].y = posOut.y; verticesOut[vertexOut].z = posOut.z; // verticesOut[vertexOut].u0 = vertexIn.u0; // verticesOut[vertexOut].v0 = vertexIn.v0; verticesOut[vertexOut].color = packUnorm4x8 (colorOut); // verticesOut[vertexOut].uv1 = verticesIn[reference].uv1; // verticesOut[vertexOut].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); // verticesOut[vertexOut].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); varyingsOut[varyingOut].offset = offset; varyingsOut[varyingOut].noCull = varyingsIn[reference].noCull; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/transform/pos_tex_color_vertex_transform_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; float u0; float v0; uint color; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; layout(local_size_x = 128) in; layout(binding=0, std430) restrict readonly buffer VerticesIn { Vertex verticesIn[]; }; layout(binding=1, std430) restrict writeonly buffer VerticesOut { Vertex verticesOut[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=3, std430) restrict readonly buffer VaryingsIn { VaryingData varyingsIn[]; }; layout(binding=4, std430) restrict writeonly buffer VaryingsOut { VaryingData varyingsOut[]; }; layout(binding=5, std430) restrict readonly buffer Meshes { Vertex meshVertices[]; }; layout(location=0) uniform uint vertexCount; layout(location=1) uniform uint vertexOffset; layout(location=2) uniform uint varyingOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint vertexOut = indexIn + vertexOffset; uint varyingOut = indexIn + varyingOffset; if (indexIn >= vertexCount) { return; } int offset = varyingsIn[indexIn] .offset; uint reference = indexIn - offset; int sharing = varyingsIn[reference] .sharing; int mesh = varyingsIn[reference] .mesh; mat4 transformMatrix; // mat3 normalMatrix; if (sharing != -1) { transformMatrix = sharings[sharing].transform; // normalMatrix = sharings[sharing].normal; } else { transformMatrix = mat4(1.0); // normalMatrix = mat3(1.0); } Vertex vertexIn; vec4 colorMesh; // uvec2 uv2Mesh; if (mesh != -1) { vertexIn = meshVertices[mesh + offset]; colorMesh = unpackUnorm4x8 ( vertexIn.color); // uv2Mesh = floatBitsToUint (unpackSnorm2x16( vertexIn.uv2)); } else { vertexIn = verticesIn[indexIn]; colorMesh = vec4 (1.0); // uv2Mesh = uvec2 (0u); } vec4 colorIn = unpackUnorm4x8 ( verticesIn[reference].color); // uvec2 uv2In = floatBitsToUint (unpackSnorm2x16( verticesIn[reference].uv2)); vec4 posOut = transformMatrix * vec4 (vertexIn.x, vertexIn.y, vertexIn.z, 1.0); // vec3 normalOut = normalMatrix * unpackSnorm4x8(vertexIn.normal).xyz; vec4 colorOut = colorMesh * colorIn; // uvec2 uv2Out = max (uv2In, uv2Mesh); verticesOut[vertexOut].x = posOut.x; verticesOut[vertexOut].y = posOut.y; verticesOut[vertexOut].z = posOut.z; verticesOut[vertexOut].u0 = vertexIn.u0; verticesOut[vertexOut].v0 = vertexIn.v0; verticesOut[vertexOut].color = packUnorm4x8 (colorOut); // verticesOut[vertexOut].uv1 = verticesIn[reference].uv1; // verticesOut[vertexOut].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); // verticesOut[vertexOut].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); varyingsOut[varyingOut].offset = offset; varyingsOut[varyingOut].noCull = varyingsIn[reference].noCull; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/transform/pos_tex_vertex_transform_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; float u0; float v0; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; layout(local_size_x = 128) in; layout(binding=0, std430) restrict readonly buffer VerticesIn { Vertex verticesIn[]; }; layout(binding=1, std430) restrict writeonly buffer VerticesOut { Vertex verticesOut[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=3, std430) restrict readonly buffer VaryingsIn { VaryingData varyingsIn[]; }; layout(binding=4, std430) restrict writeonly buffer VaryingsOut { VaryingData varyingsOut[]; }; layout(binding=5, std430) restrict readonly buffer Meshes { Vertex meshVertices[]; }; layout(location=0) uniform uint vertexCount; layout(location=1) uniform uint vertexOffset; layout(location=2) uniform uint varyingOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint vertexOut = indexIn + vertexOffset; uint varyingOut = indexIn + varyingOffset; if (indexIn >= vertexCount) { return; } int offset = varyingsIn[indexIn] .offset; uint reference = indexIn - offset; int sharing = varyingsIn[reference] .sharing; int mesh = varyingsIn[reference] .mesh; mat4 transformMatrix; // mat3 normalMatrix; if (sharing != -1) { transformMatrix = sharings[sharing].transform; // normalMatrix = sharings[sharing].normal; } else { transformMatrix = mat4(1.0); // normalMatrix = mat3(1.0); } Vertex vertexIn; // vec4 colorMesh; // uvec2 uv2Mesh; if (mesh != -1) { vertexIn = meshVertices[mesh + offset]; // colorMesh = unpackUnorm4x8 ( vertexIn.color); // uv2Mesh = floatBitsToUint (unpackSnorm2x16( vertexIn.uv2)); } else { vertexIn = verticesIn[indexIn]; // colorMesh = vec4 (1.0); // uv2Mesh = uvec2 (0u); } // vec4 colorIn = unpackUnorm4x8 ( verticesIn[reference].color); // uvec2 uv2In = floatBitsToUint (unpackSnorm2x16( verticesIn[reference].uv2)); vec4 posOut = transformMatrix * vec4 (vertexIn.x, vertexIn.y, vertexIn.z, 1.0); // vec3 normalOut = normalMatrix * unpackSnorm4x8(vertexIn.normal).xyz; // vec4 colorOut = colorMesh * colorIn; // uvec2 uv2Out = max (uv2In, uv2Mesh); verticesOut[vertexOut].x = posOut.x; verticesOut[vertexOut].y = posOut.y; verticesOut[vertexOut].z = posOut.z; verticesOut[vertexOut].u0 = vertexIn.u0; verticesOut[vertexOut].v0 = vertexIn.v0; // verticesOut[vertexOut].color = packUnorm4x8 (colorOut); // verticesOut[vertexOut].uv1 = verticesIn[reference].uv1; // verticesOut[vertexOut].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); // verticesOut[vertexOut].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); varyingsOut[varyingOut].offset = offset; varyingsOut[varyingOut].noCull = varyingsIn[reference].noCull; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/transform/pos_vertex_transform_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; layout(local_size_x = 128) in; layout(binding=0, std430) restrict readonly buffer VerticesIn { Vertex verticesIn[]; }; layout(binding=1, std430) restrict writeonly buffer VerticesOut { Vertex verticesOut[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=3, std430) restrict readonly buffer VaryingsIn { VaryingData varyingsIn[]; }; layout(binding=4, std430) restrict writeonly buffer VaryingsOut { VaryingData varyingsOut[]; }; layout(binding=5, std430) restrict readonly buffer Meshes { Vertex meshVertices[]; }; layout(location=0) uniform uint vertexCount; layout(location=1) uniform uint vertexOffset; layout(location=2) uniform uint varyingOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint vertexOut = indexIn + vertexOffset; uint varyingOut = indexIn + varyingOffset; if (indexIn >= vertexCount) { return; } int offset = varyingsIn[indexIn] .offset; uint reference = indexIn - offset; int sharing = varyingsIn[reference] .sharing; int mesh = varyingsIn[reference] .mesh; mat4 transformMatrix; // mat3 normalMatrix; if (sharing != -1) { transformMatrix = sharings[sharing].transform; // normalMatrix = sharings[sharing].normal; } else { transformMatrix = mat4(1.0); // normalMatrix = mat3(1.0); } Vertex vertexIn; // vec4 colorMesh; // uvec2 uv2Mesh; if (mesh != -1) { vertexIn = meshVertices[mesh + offset]; // colorMesh = unpackUnorm4x8 ( vertexIn.color); // uv2Mesh = floatBitsToUint (unpackSnorm2x16( vertexIn.uv2)); } else { vertexIn = verticesIn[indexIn]; // colorMesh = vec4 (1.0); // uv2Mesh = uvec2 (0u); } // vec4 colorIn = unpackUnorm4x8 ( verticesIn[reference].color); // uvec2 uv2In = floatBitsToUint (unpackSnorm2x16( verticesIn[reference].uv2)); vec4 posOut = transformMatrix * vec4 (vertexIn.x, vertexIn.y, vertexIn.z, 1.0); // vec3 normalOut = normalMatrix * unpackSnorm4x8(vertexIn.normal).xyz; // vec4 colorOut = colorMesh * colorIn; // uvec2 uv2Out = max (uv2In, uv2Mesh); verticesOut[vertexOut].x = posOut.x; verticesOut[vertexOut].y = posOut.y; verticesOut[vertexOut].z = posOut.z; // verticesOut[vertexOut].u0 = vertexIn.u0; // verticesOut[vertexOut].v0 = vertexIn.v0; // verticesOut[vertexOut].color = packUnorm4x8 (colorOut); // verticesOut[vertexOut].uv1 = verticesIn[reference].uv1; // verticesOut[vertexOut].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); // verticesOut[vertexOut].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); varyingsOut[varyingOut].offset = offset; varyingsOut[varyingOut].noCull = varyingsIn[reference].noCull; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/uploading/block_mesh_uploading_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; uint uv2; uint normal; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct MeshInfo { int sharing; int noCull; uint color; uint uv1; uint uv2; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict writeonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) restrict writeonly buffer Varyings { VaryingData varyings[]; }; layout(binding=7, std430) restrict readonly buffer Meshes { Vertex meshVertices[]; }; layout(binding=8, std430) restrict readonly buffer MeshInfos { MeshInfo meshInfos[]; }; layout(location=0) uniform uint meshCount; layout(location=1) uniform uint meshSize; layout(location=2) uniform uint vertexOffset; layout(location=3) uniform uint varyingOffset; layout(location=4) uniform uint meshOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint meshIndex = indexIn / meshSize; uint index = indexIn % meshSize; if (meshIndex >= meshCount) { return; } Vertex vertex = meshVertices [meshOffset + index]; MeshInfo meshInfo = meshInfos [meshIndex]; SharingData sharingData = sharings [meshInfo.sharing]; uint vertexIndex = index + meshIndex * meshSize + vertexOffset; uint varyingIndex = index + meshIndex * meshSize + varyingOffset; vec4 colorIn = unpackUnorm4x8 (meshInfo .color); vec4 colorMesh = unpackUnorm4x8 (vertex .color); uvec2 uv2In = floatBitsToUint (unpackSnorm2x16(meshInfo .uv2)); uvec2 uv2Mesh = floatBitsToUint (unpackSnorm2x16(vertex .uv2)); vec4 colorOut = colorIn * colorMesh; uvec2 uv2Out = max(uv2In, uv2Mesh); vec4 posOut = sharingData.transform * vec4 (vertex.x, vertex.y, vertex.z, 1.0); vec3 normalOut = sharingData.normal * unpackSnorm4x8(vertex.normal).xyz; vertices[vertexIndex].x = posOut.x; vertices[vertexIndex].y = posOut.y; vertices[vertexIndex].z = posOut.z; vertices[vertexIndex].color = packUnorm4x8(colorOut); vertices[vertexIndex].u0 = vertex.u0; vertices[vertexIndex].v0 = vertex.v0; // vertices[vertexIndex].uv1 = meshInfo .uv1; vertices[vertexIndex].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); vertices[vertexIndex].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); varyings[varyingIndex].offset = 0; varyings[varyingIndex].sharing = meshInfo.sharing; varyings[varyingIndex].noCull = meshInfo.noCull; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/uploading/entity_mesh_uploading_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; uint uv1; uint uv2; uint normal; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct MeshInfo { int sharing; int noCull; uint color; uint uv1; uint uv2; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict writeonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) restrict writeonly buffer Varyings { VaryingData varyings[]; }; layout(binding=7, std430) restrict readonly buffer Meshes { Vertex meshVertices[]; }; layout(binding=8, std430) restrict readonly buffer MeshInfos { MeshInfo meshInfos[]; }; layout(location=0) uniform uint meshCount; layout(location=1) uniform uint meshSize; layout(location=2) uniform uint vertexOffset; layout(location=3) uniform uint varyingOffset; layout(location=4) uniform uint meshOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint meshIndex = indexIn / meshSize; uint index = indexIn % meshSize; if (meshIndex >= meshCount) { return; } Vertex vertex = meshVertices [meshOffset + index]; MeshInfo meshInfo = meshInfos [meshIndex]; SharingData sharingData = sharings [meshInfo.sharing]; uint vertexIndex = index + meshIndex * meshSize + vertexOffset; uint varyingIndex = index + meshIndex * meshSize + varyingOffset; vec4 colorIn = unpackUnorm4x8 (meshInfo .color); vec4 colorMesh = unpackUnorm4x8 (vertex .color); uvec2 uv2In = floatBitsToUint (unpackSnorm2x16(meshInfo .uv2)); uvec2 uv2Mesh = floatBitsToUint (unpackSnorm2x16(vertex .uv2)); vec4 colorOut = colorIn * colorMesh; uvec2 uv2Out = max(uv2In, uv2Mesh); vec4 posOut = sharingData.transform * vec4 (vertex.x, vertex.y, vertex.z, 1.0); vec3 normalOut = sharingData.normal * unpackSnorm4x8(vertex.normal).xyz; vertices[vertexIndex].x = posOut.x; vertices[vertexIndex].y = posOut.y; vertices[vertexIndex].z = posOut.z; vertices[vertexIndex].color = packUnorm4x8(colorOut); vertices[vertexIndex].u0 = vertex.u0; vertices[vertexIndex].v0 = vertex.v0; vertices[vertexIndex].uv1 = meshInfo.uv1; vertices[vertexIndex].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); vertices[vertexIndex].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); varyings[varyingIndex].offset = 0; varyings[varyingIndex].sharing = meshInfo.sharing; varyings[varyingIndex].noCull = meshInfo.noCull; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/uploading/pos_color_mesh_uploading_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct MeshInfo { int sharing; int noCull; uint color; uint uv1; uint uv2; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict writeonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) restrict writeonly buffer Varyings { VaryingData varyings[]; }; layout(binding=7, std430) restrict readonly buffer Meshes { Vertex meshVertices[]; }; layout(binding=8, std430) restrict readonly buffer MeshInfos { MeshInfo meshInfos[]; }; layout(location=0) uniform uint meshCount; layout(location=1) uniform uint meshSize; layout(location=2) uniform uint vertexOffset; layout(location=3) uniform uint varyingOffset; layout(location=4) uniform uint meshOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint meshIndex = indexIn / meshSize; uint index = indexIn % meshSize; if (meshIndex >= meshCount) { return; } Vertex vertex = meshVertices [meshOffset + index]; MeshInfo meshInfo = meshInfos [meshIndex]; SharingData sharingData = sharings [meshInfo.sharing]; uint vertexIndex = index + meshIndex * meshSize + vertexOffset; uint varyingIndex = index + meshIndex * meshSize + varyingOffset; vec4 colorIn = unpackUnorm4x8 (meshInfo .color); vec4 colorMesh = unpackUnorm4x8 (vertex .color); // uvec2 uv2In = floatBitsToUint (unpackSnorm2x16(meshInfo .uv2)); // uvec2 uv2Mesh = floatBitsToUint (unpackSnorm2x16(vertex .uv2)); vec4 colorOut = colorIn * colorMesh; // uvec2 uv2Out = max(uv2In, uv2Mesh); vec4 posOut = sharingData.transform * vec4 (vertex.x, vertex.y, vertex.z, 1.0); // vec3 normalOut = sharingData.normal * unpackSnorm4x8(vertex.normal).xyz; vertices[vertexIndex].x = posOut.x; vertices[vertexIndex].y = posOut.y; vertices[vertexIndex].z = posOut.z; vertices[vertexIndex].color = packUnorm4x8(colorOut); // vertices[vertexIndex].u0 = vertex.u0; // vertices[vertexIndex].v0 = vertex.v0; // vertices[vertexIndex].uv1 = meshInfo .uv1; // vertices[vertexIndex].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); // vertices[vertexIndex].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); varyings[varyingIndex].offset = 0; varyings[varyingIndex].sharing = meshInfo.sharing; varyings[varyingIndex].noCull = meshInfo.noCull; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/uploading/pos_color_tex_light_mesh_uploading_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; uint color; float u0; float v0; uint uv2; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct MeshInfo { int sharing; int noCull; uint color; uint uv1; uint uv2; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict writeonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) restrict writeonly buffer Varyings { VaryingData varyings[]; }; layout(binding=7, std430) restrict readonly buffer Meshes { Vertex meshVertices[]; }; layout(binding=8, std430) restrict readonly buffer MeshInfos { MeshInfo meshInfos[]; }; layout(location=0) uniform uint meshCount; layout(location=1) uniform uint meshSize; layout(location=2) uniform uint vertexOffset; layout(location=3) uniform uint varyingOffset; layout(location=4) uniform uint meshOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint meshIndex = indexIn / meshSize; uint index = indexIn % meshSize; if (meshIndex >= meshCount) { return; } Vertex vertex = meshVertices [meshOffset + index]; MeshInfo meshInfo = meshInfos [meshIndex]; SharingData sharingData = sharings [meshInfo.sharing]; uint vertexIndex = index + meshIndex * meshSize + vertexOffset; uint varyingIndex = index + meshIndex * meshSize + varyingOffset; vec4 colorIn = unpackUnorm4x8 (meshInfo .color); vec4 colorMesh = unpackUnorm4x8 (vertex .color); uvec2 uv2In = floatBitsToUint (unpackSnorm2x16(meshInfo .uv2)); uvec2 uv2Mesh = floatBitsToUint (unpackSnorm2x16(vertex .uv2)); vec4 colorOut = colorIn * colorMesh; uvec2 uv2Out = max(uv2In, uv2Mesh); vec4 posOut = sharingData.transform * vec4 (vertex.x, vertex.y, vertex.z, 1.0); // vec3 normalOut = sharingData.normal * unpackSnorm4x8(vertex.normal).xyz; vertices[vertexIndex].x = posOut.x; vertices[vertexIndex].y = posOut.y; vertices[vertexIndex].z = posOut.z; vertices[vertexIndex].color = packUnorm4x8(colorOut); vertices[vertexIndex].u0 = vertex.u0; vertices[vertexIndex].v0 = vertex.v0; // vertices[vertexIndex].uv1 = meshInfo .uv1; vertices[vertexIndex].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); // vertices[vertexIndex].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); varyings[varyingIndex].offset = 0; varyings[varyingIndex].sharing = meshInfo.sharing; varyings[varyingIndex].noCull = meshInfo.noCull; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/uploading/pos_mesh_uploading_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct MeshInfo { int sharing; int noCull; uint color; uint uv1; uint uv2; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict writeonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) restrict writeonly buffer Varyings { VaryingData varyings[]; }; layout(binding=7, std430) restrict readonly buffer Meshes { Vertex meshVertices[]; }; layout(binding=8, std430) restrict readonly buffer MeshInfos { MeshInfo meshInfos[]; }; layout(location=0) uniform uint meshCount; layout(location=1) uniform uint meshSize; layout(location=2) uniform uint vertexOffset; layout(location=3) uniform uint varyingOffset; layout(location=4) uniform uint meshOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint meshIndex = indexIn / meshSize; uint index = indexIn % meshSize; if (meshIndex >= meshCount) { return; } Vertex vertex = meshVertices [meshOffset + index]; MeshInfo meshInfo = meshInfos [meshIndex]; SharingData sharingData = sharings [meshInfo.sharing]; uint vertexIndex = index + meshIndex * meshSize + vertexOffset; uint varyingIndex = index + meshIndex * meshSize + varyingOffset; // vec4 colorIn = unpackUnorm4x8 (meshInfo .color); // vec4 colorMesh = unpackUnorm4x8 (vertex .color); // uvec2 uv2In = floatBitsToUint (unpackSnorm2x16(meshInfo .uv2)); // uvec2 uv2Mesh = floatBitsToUint (unpackSnorm2x16(vertex .uv2)); // vec4 colorOut = colorIn * colorMesh; // uvec2 uv2Out = max(uv2In, uv2Mesh); vec4 posOut = sharingData.transform * vec4 (vertex.x, vertex.y, vertex.z, 1.0); // vec3 normalOut = sharingData.normal * unpackSnorm4x8(vertex.normal).xyz; vertices[vertexIndex].x = posOut.x; vertices[vertexIndex].y = posOut.y; vertices[vertexIndex].z = posOut.z; // vertices[vertexIndex].color = packUnorm4x8(colorOut); // vertices[vertexIndex].u0 = vertex.u0; // vertices[vertexIndex].v0 = vertex.v0; // vertices[vertexIndex].uv1 = meshInfo .uv1; // vertices[vertexIndex].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); // vertices[vertexIndex].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); varyings[varyingIndex].offset = 0; varyings[varyingIndex].sharing = meshInfo.sharing; varyings[varyingIndex].noCull = meshInfo.noCull; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/uploading/pos_tex_color_mesh_uploading_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; float u0; float v0; uint color; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct MeshInfo { int sharing; int noCull; uint color; uint uv1; uint uv2; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict writeonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) restrict writeonly buffer Varyings { VaryingData varyings[]; }; layout(binding=7, std430) restrict readonly buffer Meshes { Vertex meshVertices[]; }; layout(binding=8, std430) restrict readonly buffer MeshInfos { MeshInfo meshInfos[]; }; layout(location=0) uniform uint meshCount; layout(location=1) uniform uint meshSize; layout(location=2) uniform uint vertexOffset; layout(location=3) uniform uint varyingOffset; layout(location=4) uniform uint meshOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint meshIndex = indexIn / meshSize; uint index = indexIn % meshSize; if (meshIndex >= meshCount) { return; } Vertex vertex = meshVertices [meshOffset + index]; MeshInfo meshInfo = meshInfos [meshIndex]; SharingData sharingData = sharings [meshInfo.sharing]; uint vertexIndex = index + meshIndex * meshSize + vertexOffset; uint varyingIndex = index + meshIndex * meshSize + varyingOffset; vec4 colorIn = unpackUnorm4x8 (meshInfo .color); vec4 colorMesh = unpackUnorm4x8 (vertex .color); // uvec2 uv2In = floatBitsToUint (unpackSnorm2x16(meshInfo .uv2)); // uvec2 uv2Mesh = floatBitsToUint (unpackSnorm2x16(vertex .uv2)); vec4 colorOut = colorIn * colorMesh; // uvec2 uv2Out = max(uv2In, uv2Mesh); vec4 posOut = sharingData.transform * vec4 (vertex.x, vertex.y, vertex.z, 1.0); // vec3 normalOut = sharingData.normal * unpackSnorm4x8(vertex.normal).xyz; vertices[vertexIndex].x = posOut.x; vertices[vertexIndex].y = posOut.y; vertices[vertexIndex].z = posOut.z; vertices[vertexIndex].color = packUnorm4x8(colorOut); vertices[vertexIndex].u0 = vertex.u0; vertices[vertexIndex].v0 = vertex.v0; // vertices[vertexIndex].uv1 = meshInfo .uv1; // vertices[vertexIndex].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); // vertices[vertexIndex].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); varyings[varyingIndex].offset = 0; varyings[varyingIndex].sharing = meshInfo.sharing; varyings[varyingIndex].noCull = meshInfo.noCull; } ================================================ FILE: src/main/resources/assets/acceleratedrendering/shaders/core/uploading/pos_tex_mesh_uploading_shader.compute ================================================ #version 460 core struct Vertex { float x; float y; float z; float u0; float v0; }; struct VaryingData { int offset; int sharing; int mesh; int noCull; }; struct SharingData { mat4 transform; mat3 normal; }; struct MeshInfo { int sharing; int noCull; uint color; uint uv1; uint uv2; }; layout(local_size_x = 128) in; layout(binding=1, std430) restrict writeonly buffer Vertices { Vertex vertices[]; }; layout(binding=2, std430) restrict readonly buffer Sharings { SharingData sharings[]; }; layout(binding=4, std430) restrict writeonly buffer Varyings { VaryingData varyings[]; }; layout(binding=7, std430) restrict readonly buffer Meshes { Vertex meshVertices[]; }; layout(binding=8, std430) restrict readonly buffer MeshInfos { MeshInfo meshInfos[]; }; layout(location=0) uniform uint meshCount; layout(location=1) uniform uint meshSize; layout(location=2) uniform uint vertexOffset; layout(location=3) uniform uint varyingOffset; layout(location=4) uniform uint meshOffset; void main() { uint indexIn = gl_GlobalInvocationID.x; uint meshIndex = indexIn / meshSize; uint index = indexIn % meshSize; if (meshIndex >= meshCount) { return; } Vertex vertex = meshVertices [meshOffset + index]; MeshInfo meshInfo = meshInfos [meshIndex]; SharingData sharingData = sharings [meshInfo.sharing]; uint vertexIndex = index + meshIndex * meshSize + vertexOffset; uint varyingIndex = index + meshIndex * meshSize + varyingOffset; // vec4 colorIn = unpackUnorm4x8 (meshInfo .color); // vec4 colorMesh = unpackUnorm4x8 (vertex .color); // uvec2 uv2In = floatBitsToUint (unpackSnorm2x16(meshInfo .uv2)); // uvec2 uv2Mesh = floatBitsToUint (unpackSnorm2x16(vertex .uv2)); // vec4 colorOut = colorIn * colorMesh; // uvec2 uv2Out = max(uv2In, uv2Mesh); vec4 posOut = sharingData.transform * vec4 (vertex.x, vertex.y, vertex.z, 1.0); // vec3 normalOut = sharingData.normal * unpackSnorm4x8(vertex.normal).xyz; vertices[vertexIndex].x = posOut.x; vertices[vertexIndex].y = posOut.y; vertices[vertexIndex].z = posOut.z; // vertices[vertexIndex].color = packUnorm4x8(colorOut); vertices[vertexIndex].u0 = vertex.u0; vertices[vertexIndex].v0 = vertex.v0; // vertices[vertexIndex].uv1 = meshInfo .uv1; // vertices[vertexIndex].uv2 = packSnorm2x16 (uintBitsToFloat(uv2Out)); // vertices[vertexIndex].normal = packSnorm4x8 (vec4 (normalize(normalOut), 0.0)); varyings[varyingIndex].offset = 0; varyings[varyingIndex].sharing = meshInfo.sharing; varyings[varyingIndex].noCull = meshInfo.noCull; }