Skip to content

Commit

Permalink
Trying to figure out snapshots being slow
Browse files Browse the repository at this point in the history
  • Loading branch information
Aeltumn committed Jan 8, 2025
1 parent 52bd975 commit dc6a1ee
Show file tree
Hide file tree
Showing 12 changed files with 184 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class NoxesiumConfig {
* Whether dynamic UI limiting should be used.
*/
public boolean shouldUseDynamicUiLimiting() {
return supportsDynamicUiLimiting && enableUiLimiting;
return supportsDynamicUiLimiting && enableDynamicUiLimiting;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.noxcrew.noxesium.feature.ui.render;

import com.mojang.blaze3d.platform.GlStateManager;
import com.noxcrew.noxesium.NoxesiumMod;
import com.noxcrew.noxesium.feature.ui.BufferHelper;
import com.noxcrew.noxesium.feature.ui.render.api.PerSecondRepeatingTask;
import com.noxcrew.noxesium.feature.ui.render.buffer.ElementBuffer;
import com.noxcrew.noxesium.feature.ui.render.buffer.SnapshotableElementBuffer;
Expand All @@ -17,9 +19,9 @@ public class DynamicElement extends Element {
private final PerSecondRepeatingTask nextRender =
new PerSecondRepeatingTask(NoxesiumMod.getInstance().getConfig().maxUiFramerate);

private boolean canCheck = true;
private boolean movementDirection = false;
private boolean hasBufferLayoutChanged = false;
private boolean hasRedrawnRecently = false;
private long lastChange = System.currentTimeMillis();
private int matches = 0;

Expand All @@ -45,8 +47,8 @@ public void resetToMax() {
/**
* Returns the percentage of matching frames.
*/
public String matchRate() {
return String.format("%.2f", ((double) matches) / 60d);
public int matchRate() {
return (int) ((((double) matches) / 60d) * 100d);
}

/**
Expand All @@ -72,13 +74,6 @@ public boolean isReady() {
return true;
}

/**
* Indicates that a check should run the very next frame.
*/
public void requestCheck() {
canCheck = true;
}

/**
* Returns whether this element is often changing. Used to determine
* when it should be split up this buffer.
Expand All @@ -104,7 +99,6 @@ public void tick() {
// Determine if all buffers are the same,
// return the entire method if any buffer is not ready.
var verdict = !hasBufferLayoutChanged;
hasBufferLayoutChanged = false;
if (isNotEmpty()) {
for (var buffer : buffers) {
if (buffer instanceof SnapshotableElementBuffer pboBuffer) {
Expand All @@ -119,6 +113,9 @@ public void tick() {
}
}

// Update after we are committed to this tick
hasBufferLayoutChanged = false;

// This means we are lowering fps, if anything changes more than thrice we go back.
if (verdict) {
matches = Math.min(60, matches + 1);
Expand Down Expand Up @@ -157,15 +154,26 @@ public void tick() {
}

/**
* Tries to make a snapshot of the current buffer.
* Tries to make a snapshots of all buffers that can if
* this frame is useful.
*/
private void trySnapshot() {
if (elementsWereDrawn && canCheck) {
var target = getTargetBuffer();
if (target instanceof SnapshotableElementBuffer pboBuffer) {
pboBuffer.snapshot();
}
public void trySnapshot() {
// Only snapshot if we've redrawn recently
if (buffers.isEmpty() || !hasRedrawnRecently) return;

// Return if any buffer can't snapshot
for (var buffer : buffers) {
if (!buffer.canSnapshot()) return;
}

// Update after we are committed
hasRedrawnRecently = false;

// Try to snapshot on every buffer and then unbind the main target
for (var buffer : buffers) {
buffer.snapshot();
}
// SharedVertexBuffer.rebindMainRenderTarget();
}

@Override
Expand All @@ -176,38 +184,23 @@ public boolean update(long nanoTime, GuiGraphics guiGraphics, Runnable draw) {
buffer.awaitFence();
}

if (super.update(nanoTime, guiGraphics, draw)) {
// Unset check once we're done with this frame, but
// snapshot first!
if (canCheck) {
trySnapshot();
canCheck = false;
}
return true;
var result = super.update(nanoTime, guiGraphics, draw);
if (result) {
hasRedrawnRecently = true;
}
return false;
return result;
}

@Override
public boolean shouldRedraw(long nanoTime) {
// If we can check we still increase the next render frame,
// but we ignore its result!
return nextRender.canInvoke(nanoTime) || canCheck;
return nextRender.canInvoke(nanoTime);
}

@Override
public List<ElementBuffer> getBuffers() {
return (List<ElementBuffer>) (List<?>) buffers;
}

@Override
protected void onBufferUntargeted(ElementBuffer buffer) {
super.onBufferUntargeted(buffer);

// Before targeting a new buffer we attempt to snapshot the previous one!
trySnapshot();
}

@Override
protected void onBufferRemoved(ElementBuffer buffer) {
super.onBufferRemoved(buffer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
import com.noxcrew.noxesium.feature.ui.BufferHelper;
import com.noxcrew.noxesium.feature.ui.layer.NoxesiumLayeredDraw;
import com.noxcrew.noxesium.feature.ui.render.api.NoxesiumRenderState;
import com.noxcrew.noxesium.feature.ui.render.api.PerSecondRepeatingTask;
import com.noxcrew.noxesium.feature.ui.render.buffer.BufferData;
import net.minecraft.client.DeltaTracker;
import net.minecraft.client.gui.GuiGraphics;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import net.minecraft.client.DeltaTracker;
import net.minecraft.client.gui.GuiGraphics;

/**
* Stores the entire render state of the current UI.
Expand All @@ -19,7 +21,7 @@ public class NoxesiumUiRenderState extends NoxesiumRenderState {

private final List<LayerGroup> groups = new CopyOnWriteArrayList<>();
private final Random random = new Random();
private long nextUpdate = -1;
private final PerSecondRepeatingTask updateGroupsTask = new PerSecondRepeatingTask(2.0);
private int lastSize = 0;

/**
Expand Down Expand Up @@ -94,7 +96,7 @@ public boolean render(GuiGraphics guiGraphics, DeltaTracker deltaTracker, Noxesi
*/
private void updateGroups(NoxesiumLayeredDraw layeredDraw, long nanoTime, boolean dynamic) {
// Update which groups exist if the layered draw object has changed
var intendedSize = dynamic ? layeredDraw.size() : 1;
var intendedSize = layeredDraw.size();
if (lastSize != intendedSize) {
lastSize = intendedSize;
resetGroups();
Expand All @@ -121,35 +123,29 @@ private void updateGroups(NoxesiumLayeredDraw layeredDraw, long nanoTime, boolea
group.update();
}

// If we're in dynamic mode we try to update groups.
if (dynamic) {
// Try to split up or merge together groups, but don't run this too frequently!
if (nextUpdate == -1 || nanoTime >= nextUpdate) {
// Schedule when we can next update the groups
nextUpdate = nanoTime + random.nextLong(500000000);

// Iterate through all groups and make changes
var index = 0;
while (index < groups.size()) {
var group = groups.get(index++);

// Try to merge if there are neighboring groups
if (index > 2 && index < groups.size()) {
if (group.canMerge(groups.get(index))) {
group.join(groups.get(index));
groups.remove(index).close();
index--;
} else if (groups.get(index - 2).canMerge(group)) {
groups.get(index - 2).join(group);
groups.remove(index - 1).close();
index--;
}
// Try to split up or merge together groups, but don't run this too frequently!
if (dynamic && updateGroupsTask.canInvoke(nanoTime)) {
// Iterate through all groups and make changes
var index = 0;
while (index < groups.size()) {
var group = groups.get(index++);

// Try to merge if there are neighboring groups
if (index > 2 && index < groups.size()) {
if (group.canMerge(groups.get(index))) {
group.join(groups.get(index));
groups.remove(index).close();
index--;
} else if (groups.get(index - 2).canMerge(group)) {
groups.get(index - 2).join(group);
groups.remove(index - 1).close();
index--;
}
}

// Try to split up the group
if (group.shouldSplit()) {
groups.add(index++, group.split());
}
// Try to split up the group
if (group.shouldSplit()) {
groups.add(index++, group.split());
}
}
}
Expand All @@ -166,24 +162,12 @@ private void resetGroups() {
}

@Override
public void requestCheck() {
public List<DynamicElement> getDynamics() {
var result = new ArrayList<DynamicElement>();
for (var group : groups) {
group.dynamic().requestCheck();
}
}

@Override
public void updateRenderFramerate() {
for (var group : groups) {
group.dynamic().resetToMax();
}
}

@Override
public void tick() {
for (var group : groups) {
group.dynamic().tick();
result.add(group.dynamic());
}
return result;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.noxcrew.noxesium.feature.ui.render.api;

import com.noxcrew.noxesium.feature.ui.render.DynamicElement;

import java.io.Closeable;
import java.util.List;

/**
* The basis for a render state object.
Expand All @@ -12,18 +15,44 @@ public abstract class NoxesiumRenderState implements Closeable {
*/
public final PerSecondTrackedValue renders = new PerSecondTrackedValue();

/**
* Returns all dynamic elements in this state.
*/
public abstract List<DynamicElement> getDynamics();

/**
* Attempts to take a snapshot if required.
*/
public void trySnapshot() {
for (var dynamic : getDynamics()) {
dynamic.trySnapshot();
}
}

/**
* Ticks this render state.
*/
public abstract void tick();
public void tick() {
for (var dynamic : getDynamics()) {
dynamic.tick();
}
}

/**
* Indicates that a check should run the very next frame.
*/
public abstract void requestCheck();
public void requestCheck() {
for (var dynamic : getDynamics()) {
dynamic.redraw();
}
}

/**
* Triggers an update of the render framerate.
*/
public abstract void updateRenderFramerate();
public void updateRenderFramerate() {
for (var dynamic : getDynamics()) {
dynamic.resetToMax();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,28 @@ default void updateRenderFramerate() {
}
}

/**
* Triggers a snapshot attempt.
*/
default void trySnapshot() {
// Ignore if not on dynamic mode.
// if (!NoxesiumMod.getInstance().getConfig().shouldUseDynamicUiLimiting()) return;

var state = get();
if (state != null) {
state.trySnapshot();
}
}

/**
* Indicates that a check should run the very next frame.
*/
default void requestCheck() {
// Ignore checks if we're not using dynamic UI limiting!
if (!NoxesiumMod.getInstance().getConfig().shouldUseDynamicUiLimiting()) return;
// However, if we are using dynamic UI limiting we want to make
// sure we always draw on frames after a client tick happened as
// it has the newest frame data.
// if (!NoxesiumMod.getInstance().getConfig().shouldUseDynamicUiLimiting()) return;

var state = get();
if (state != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ public class ElementBuffer implements Closeable {

private final AtomicBoolean configuring = new AtomicBoolean(false);

private RenderTarget target;
private BlendState blendState;
protected RenderTarget target;
protected BlendState blendState;

/**
* Binds this buffer to the render target, replacing any previous target.
Expand Down
Loading

0 comments on commit dc6a1ee

Please sign in to comment.