diff options
| author | shedaniel <daniel@shedaniel.me> | 2022-06-22 02:12:12 +0800 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2023-05-29 21:05:02 +0800 |
| commit | 9e822be1e85509bd533412c802b283a58e08346b (patch) | |
| tree | 93cca89bc06d6fa5378ade2f42b304d136d18d26 /runtime/src/main/java | |
| parent | 52e9609e7ac8e15bdca8ceaafe7160c1c8b7d6c7 (diff) | |
| download | RoughlyEnoughItems-9e822be1e85509bd533412c802b283a58e08346b.tar.gz RoughlyEnoughItems-9e822be1e85509bd533412c802b283a58e08346b.tar.bz2 RoughlyEnoughItems-9e822be1e85509bd533412c802b283a58e08346b.zip | |
Batching Cached Renders
Diffstat (limited to 'runtime/src/main/java')
7 files changed, 184 insertions, 24 deletions
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/BatchedEntryRendererManager.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/BatchedEntryRendererManager.java index bc75c91a0..852723f1d 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/BatchedEntryRendererManager.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/BatchedEntryRendererManager.java @@ -55,13 +55,17 @@ public class BatchedEntryRendererManager { addAll(widgets); } + public boolean isFastEntryRendering() { + return fastEntryRendering; + } + public void addAll(Collection<? extends EntryWidget> widgets) { if (fastEntryRendering) { for (EntryWidget widget : widgets) { add(widget); } } else { - toRender.addAll(widgets); + addAllSlow(widgets); } } @@ -93,6 +97,15 @@ public class BatchedEntryRendererManager { return; } } + + addSlow(widget); + } + + public void addAllSlow(Collection<? extends EntryWidget> widgets) { + toRender.addAll(widgets); + } + + public void addSlow(EntryWidget widget) { toRender.add(widget); } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/CachedEntryListRender.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/CachedEntryListRender.java index 19aa37f23..663bf6a0f 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/CachedEntryListRender.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/CachedEntryListRender.java @@ -24,10 +24,12 @@ package me.shedaniel.rei.impl.client.gui.widget; import com.mojang.blaze3d.pipeline.RenderTarget; +import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.Lighting; import com.mojang.blaze3d.platform.NativeImage; import com.mojang.blaze3d.platform.Window; import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.PoseStack; import it.unimi.dsi.fastutil.longs.Long2LongMap; import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap; @@ -41,6 +43,9 @@ import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; import me.shedaniel.rei.api.common.util.EntryStacks; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.RenderStateShard; +import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.texture.DynamicTexture; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.PackType; @@ -48,12 +53,18 @@ import net.minecraft.util.Unit; import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.function.Supplier; public class CachedEntryListRender { public static final int RESOLUTION = 64; public static DynamicTexture cachedTexture; public static ResourceLocation cachedTextureLocation; public static Long2LongMap hash = new Long2LongOpenHashMap(); + public static LazyResettable<RenderType> renderType = new LazyResettable<>(() -> RenderType.create("rei_cache", DefaultVertexFormat.POSITION_TEX, VertexFormat.Mode.QUADS, 256, + RenderType.CompositeState.builder() + .setTextureState(new RenderStateShard.TextureStateShard(cachedTextureLocation, false, false)) + .setShaderState(new RenderStateShard.ShaderStateShard(GameRenderer::getPositionTexShader)) + .createCompositeState(false))); public static class Sprite { public final float u0; @@ -82,6 +93,7 @@ public class CachedEntryListRender { if (cachedTextureLocation != null) { Minecraft.getInstance().getTextureManager().release(cachedTextureLocation); cachedTextureLocation = null; + renderType.reset(); } if (cachedTexture != null) { cachedTexture.close(); @@ -165,6 +177,7 @@ public class CachedEntryListRender { cachedTexture = new DynamicTexture(nativeImage); cachedTextureLocation = minecraft.getTextureManager().register("rei_cached_entries", cachedTexture); + renderType.reset(); target.destroyBuffers(); Minecraft.getInstance().getMainRenderTarget().bindWrite(true); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/CachingEntryRenderer.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/CachingEntryRenderer.java new file mode 100644 index 000000000..78ae8e365 --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/CachingEntryRenderer.java @@ -0,0 +1,102 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * + * 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. + */ + +package me.shedaniel.rei.impl.client.gui.widget.entrylist; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Matrix4f; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.entry.renderer.BatchedEntryRenderer; +import me.shedaniel.rei.api.client.gui.widgets.Tooltip; +import me.shedaniel.rei.api.client.gui.widgets.TooltipContext; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.impl.client.gui.widget.CachedEntryListRender; +import net.minecraft.client.gui.GuiComponent; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import org.jetbrains.annotations.Nullable; + +import java.util.function.IntSupplier; + +public class CachingEntryRenderer implements BatchedEntryRenderer<Object, CachedEntryListRender.Sprite> { + private final CachedEntryListRender.Sprite sprite; + private final IntSupplier blitOffset; + + public CachingEntryRenderer(CachedEntryListRender.Sprite sprite, IntSupplier blitOffset) { + this.sprite = sprite; + this.blitOffset = blitOffset; + } + + @Override + public CachedEntryListRender.Sprite getExtraData(EntryStack<Object> entry) { + return sprite; + } + + @Override + public int getBatchIdentifier(EntryStack<Object> entry, Rectangle bounds, CachedEntryListRender.Sprite extraData) { + return 0; + } + + @Override + public void startBatch(EntryStack<Object> entry, CachedEntryListRender.Sprite extraData, PoseStack matrices, float delta) { + RenderSystem.setShaderTexture(0, CachedEntryListRender.cachedTextureLocation); + RenderSystem.setShader(GameRenderer::getPositionTexShader); + } + + @Override + public void renderBase(EntryStack<Object> entry, CachedEntryListRender.Sprite extraData, PoseStack matrices, MultiBufferSource.BufferSource immediate, Rectangle bounds, int mouseX, int mouseY, float delta) { + VertexConsumer consumer = immediate.getBuffer(CachedEntryListRender.renderType.get()); + Matrix4f pose = matrices.last().pose(); + int blitOffset = this.blitOffset.getAsInt(); + consumer.vertex(pose, bounds.x, bounds.getMaxY(), blitOffset).uv(extraData.u0, extraData.v1).endVertex(); + consumer.vertex(pose, bounds.getMaxX(), bounds.getMaxY(), blitOffset).uv(extraData.u1, extraData.v1).endVertex(); + consumer.vertex(pose, bounds.getMaxX(), bounds.y, blitOffset).uv(extraData.u1, extraData.v0).endVertex(); + consumer.vertex(pose, bounds.x, bounds.y, blitOffset).uv(extraData.u0, extraData.v0).endVertex(); + } + + @Override + public void afterBase(EntryStack<Object> entry, CachedEntryListRender.Sprite extraData, PoseStack matrices, float delta) { + } + + @Override + public void renderOverlay(EntryStack<Object> entry, CachedEntryListRender.Sprite extraData, PoseStack matrices, MultiBufferSource.BufferSource immediate, Rectangle bounds, int mouseX, int mouseY, float delta) { + } + + @Override + public void endBatch(EntryStack<Object> entry, CachedEntryListRender.Sprite extraData, PoseStack matrices, float delta) { + } + + @Override + public void render(EntryStack<Object> entry, PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) { + RenderSystem.setShaderTexture(0, CachedEntryListRender.cachedTextureLocation); + GuiComponent.innerBlit(matrices.last().pose(), bounds.x, bounds.getMaxX(), bounds.y, bounds.getMaxY(), this.blitOffset.getAsInt(), sprite.u0, sprite.u1, sprite.v0, sprite.v1); + } + + @Override + @Nullable + public Tooltip getTooltip(EntryStack<Object> entry, TooltipContext context) { + return entry.getDefinition().getRenderer().getTooltip(entry.cast(), context); + } +} diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListStackEntry.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListStackEntry.java index 2e24d959d..a4117d202 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListStackEntry.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListStackEntry.java @@ -33,6 +33,7 @@ import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.impl.client.gui.widget.CachedEntryListRender; import me.shedaniel.rei.impl.client.gui.widget.DisplayedEntryWidget; import me.shedaniel.rei.impl.common.entry.type.collapsed.CollapsedStack; +import org.jetbrains.annotations.Nullable; import static me.shedaniel.rei.impl.client.gui.widget.entrylist.EntryListWidget.entrySize; @@ -105,6 +106,11 @@ public class EntryListStackEntry extends DisplayedEntryWidget { this.collapsedStack = collapsedStack; } + @Nullable + public CollapsedStack getCollapsedStack() { + return collapsedStack; + } + @Override protected long getCyclingInterval() { return 100; diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListWidget.java index c7606848b..cb70e91c0 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListWidget.java @@ -39,6 +39,7 @@ import me.shedaniel.rei.api.client.gui.drag.DraggableStackVisitorWidget; import me.shedaniel.rei.api.client.gui.drag.DraggedAcceptorResult; import me.shedaniel.rei.api.client.gui.drag.DraggingContext; import me.shedaniel.rei.api.client.gui.screen.DisplayScreen; +import me.shedaniel.rei.api.client.gui.widgets.Slot; import me.shedaniel.rei.api.client.gui.widgets.Tooltip; import me.shedaniel.rei.api.client.gui.widgets.Widget; import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds; @@ -66,7 +67,6 @@ import net.minecraft.world.InteractionResult; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.ApiStatus; -import java.util.Collections; import java.util.List; @SuppressWarnings("UnstableApiUsage") @@ -75,7 +75,6 @@ public abstract class EntryListWidget extends WidgetWithBounds implements Overla private static final int SIZE = 18; protected final RegionRenderingDebugger debugger = new RegionRenderingDebugger(); protected Rectangle bounds, innerBounds; - protected List<EntryListStackEntry> entries = Collections.emptyList(); public final NumberAnimator<Double> scaleIndicator = ValueAnimator.ofDouble(0.0D) .withConvention(() -> 0.0D, 8000); @@ -250,7 +249,7 @@ public abstract class EntryListWidget extends WidgetWithBounds implements Overla @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { if (containsChecked(mouse(), false)) - for (Widget widget : entries) + for (Widget widget : getEntryWidgets()) if (widget.keyPressed(keyCode, scanCode, modifiers)) return true; return false; @@ -308,7 +307,7 @@ public abstract class EntryListWidget extends WidgetWithBounds implements Overla @Override public List<? extends Widget> children() { - return entries; + return getEntryWidgets(); } @Override @@ -357,7 +356,7 @@ public abstract class EntryListWidget extends WidgetWithBounds implements Overla public EntryStack<?> getFocusedStack() { Point mouse = mouse(); if (containsChecked(mouse, false)) { - for (EntryListStackEntry entry : entries) { + for (Slot entry : getEntryWidgets()) { EntryStack<?> currentEntry = entry.getCurrentEntry(); if (!currentEntry.isEmpty() && entry.containsMouse(mouse)) { return currentEntry.copy(); @@ -366,4 +365,6 @@ public abstract class EntryListWidget extends WidgetWithBounds implements Overla } return EntryStack.empty(); } + + protected abstract List<EntryListStackEntry> getEntryWidgets(); } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/PaginatedEntryListWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/PaginatedEntryListWidget.java index 74afab82e..672c16aa3 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/PaginatedEntryListWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/PaginatedEntryListWidget.java @@ -25,10 +25,12 @@ package me.shedaniel.rei.impl.client.gui.widget.entrylist; import com.google.common.collect.Lists; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.*; +import com.mojang.math.Matrix4f; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.config.ConfigObject; +import me.shedaniel.rei.api.client.entry.renderer.BatchedEntryRenderer; import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer; import me.shedaniel.rei.api.client.gui.widgets.Tooltip; import me.shedaniel.rei.api.client.gui.widgets.TooltipContext; @@ -38,15 +40,21 @@ import me.shedaniel.rei.impl.client.gui.widget.BatchedEntryRendererManager; import me.shedaniel.rei.impl.client.gui.widget.CachedEntryListRender; import me.shedaniel.rei.impl.client.gui.widget.EntryWidget; import me.shedaniel.rei.impl.common.entry.type.collapsed.CollapsedStack; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; import net.minecraft.util.Mth; +import net.minecraft.util.Unit; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.stream.Stream; public class PaginatedEntryListWidget extends CollapsingEntryListWidget { private List</*EntryStack<?> | EntryIngredient*/ Object> stacks = new ArrayList<>(); + protected List<EntryListStackEntry> entries = Collections.emptyList(); private int page; @Override @@ -63,30 +71,35 @@ public class PaginatedEntryListWidget extends CollapsingEntryListWidget { protected void renderEntries(boolean fastEntryRendering, PoseStack matrices, int mouseX, int mouseY, float delta) { if (ConfigObject.getInstance().doesCacheEntryRendering()) { for (EntryListStackEntry entry : entries) { + CollapsedStack collapsedStack = entry.getCollapsedStack(); + if (collapsedStack != null && !collapsedStack.isExpanded()) { + continue; + } + if (entry.our == null) { CachedEntryListRender.Sprite sprite = CachedEntryListRender.get(entry.getCurrentEntry()); if (sprite != null) { - entry.our = ClientEntryStacks.setRenderer(entry.getCurrentEntry().copy().cast(), stack -> new EntryRenderer<Object>() { - @Override - public void render(EntryStack<Object> entry, PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) { - RenderSystem.setShaderTexture(0, CachedEntryListRender.cachedTextureLocation); - innerBlit(matrices.last().pose(), bounds.x, bounds.getMaxX(), bounds.y, bounds.getMaxY(), getBlitOffset(), sprite.u0, sprite.u1, sprite.v0, sprite.v1); - } - - @Override - @Nullable - public Tooltip getTooltip(EntryStack<Object> entry, TooltipContext context) { - return stack.getDefinition().getRenderer().getTooltip(entry.cast(), context); - } - }); + CachingEntryRenderer renderer = new CachingEntryRenderer(sprite, this::getBlitOffset); + entry.our = ClientEntryStacks.setRenderer(entry.getCurrentEntry().copy().cast(), stack -> renderer); } } } - - BatchedEntryRendererManager.renderSlow(debugger.debugTime, debugger.size, debugger.time, matrices, mouseX, mouseY, delta, entries); + } + + BatchedEntryRendererManager manager = new BatchedEntryRendererManager(); + if (manager.isFastEntryRendering()) { + for (EntryListStackEntry entry : entries) { + CollapsedStack collapsedStack = entry.getCollapsedStack(); + if (collapsedStack != null && !collapsedStack.isExpanded()) { + manager.addSlow(entry); + } else { + manager.add(entry); + } + } } else { - new BatchedEntryRendererManager(entries).render(debugger.debugTime, debugger.size, debugger.time, matrices, mouseX, mouseY, delta); + manager.addAllSlow(entries); } + manager.render(debugger.debugTime, debugger.size, debugger.time, matrices, mouseX, mouseY, delta); } @Override @@ -144,4 +157,9 @@ public class PaginatedEntryListWidget extends CollapsingEntryListWidget { public Stream<EntryStack<?>> getEntries() { return entries.stream().map(EntryWidget::getCurrentEntry); } + + @Override + protected List<EntryListStackEntry> getEntryWidgets() { + return entries; + } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/ScrolledEntryListWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/ScrolledEntryListWidget.java index a42beca17..a569488fa 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/ScrolledEntryListWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/ScrolledEntryListWidget.java @@ -40,11 +40,13 @@ import net.minecraft.client.gui.screens.Screen; import net.minecraft.util.Mth; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.stream.Stream; public class ScrolledEntryListWidget extends CollapsingEntryListWidget { private List</*EntryStack<?> | EntryIngredient*/ Object> stacks = new ArrayList<>(); + protected List<EntryListStackEntry> entries = Collections.emptyList(); protected int blockedCount; protected final ScrollingContainer scrolling = new ScrollingContainer() { @Override @@ -90,7 +92,7 @@ public class ScrolledEntryListWidget extends CollapsingEntryListWidget { List<EntryStack<?>> ingredient = (List<EntryStack<?>>) stack; if (!ingredient.isEmpty()) { entry.entries(ingredient); - helper.add(entry); + helper.addSlow(entry); } } @@ -188,4 +190,9 @@ public class ScrolledEntryListWidget extends CollapsingEntryListWidget { .map(EntryWidget::getCurrentEntry) .filter(Predicates.not(EntryStack::isEmpty)); } + + @Override + protected List<EntryListStackEntry> getEntryWidgets() { + return entries; + } } |
