Skip to content
This repository has been archived by the owner on Oct 17, 2020. It is now read-only.

Commit

Permalink
Changed the algorithm responsible for dynamic chunk updates to be bas…
Browse files Browse the repository at this point in the history
…ed on actual FPS, instead of estimated vsync idle time. Works more reliably.
  • Loading branch information
mstefarov committed Oct 21, 2014
1 parent 0883784 commit f68c6a4
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 26 deletions.
30 changes: 11 additions & 19 deletions src/main/java/com/mojang/minecraft/Minecraft.java
Expand Up @@ -96,7 +96,6 @@
import com.mojang.util.StreamingUtil;
import com.mojang.util.Timer;
import com.mojang.util.Vec3D;
import java.text.DecimalFormat;

public final class Minecraft implements Runnable {

Expand Down Expand Up @@ -883,6 +882,7 @@ private void onFrame() {
// Get current time in seconds
double now = System.nanoTime() / Timer.NANOSEC_PER_SEC;
double secondsPassed = (now - timer.lastHR);
timer.lastFrameDuration = secondsPassed;
timer.lastHR = now;

// Cap seconds-passed to range [0,1]
Expand Down Expand Up @@ -1095,33 +1095,28 @@ private void onFrame() {
// Calculate the limit on chunk-updates-per-frame
int maxUpdates;
if (settings.limitFramerate) {
maxUpdates = Math.max(Renderer.dynamicChunkUpdateLimit, Renderer.MIN_CHUNK_UPDATES_PER_FRAME);
maxUpdates = Math.max(renderer.dynamicChunkUpdateLimit, renderer.MIN_CHUNK_UPDATES_PER_FRAME);
} else {
maxUpdates = Renderer.MIN_CHUNK_UPDATES_PER_FRAME;
}
chunkUpdates = Math.min(chunkUpdates, maxUpdates);

// Actually update the chunks. Measure how long it takes.
long timeBeforeChunkUpdates = System.nanoTime();
for (int i = 0; i < chunkUpdates; ++i) {
Chunk chunk = levelRenderer.chunksToUpdate.remove(lastChunkId - i);
chunk.update();
chunk.loaded = false;
}
long chunkUpdateTime = System.nanoTime() - timeBeforeChunkUpdates;

// Adjust measured average-time-per-chunk-update
timer.chunkUpdateTime = timer.chunkUpdateTime * 0.5
+ (chunkUpdateTime / Timer.NANOSEC_PER_SEC / chunkUpdates) * 0.5;

// Next frame, use up to 90% of available CPU time for chunks
Renderer.dynamicChunkUpdateLimit = (int) Math.floor(timer.syncTime / timer.chunkUpdateTime * 0.9);

DecimalFormat formatter = new DecimalFormat("#0.00000");
LogUtil.logInfo("sT=" + formatter.format(timer.syncTime)
+ " | cUT=" + formatter.format(timer.chunkUpdateTime)
+ " | dCUL=" + Renderer.dynamicChunkUpdateLimit
+ " | mU=" + maxUpdates);
// Adjust chunks-per-frame based on framerate. Back off is under 30fps.
if(timer.lastFrameDuration > 1/30d ){
renderer.everBackedOffFromChunkUpdates=(renderer.dynamicChunkUpdateLimit>renderer.MIN_CHUNK_UPDATES_PER_FRAME);
renderer.dynamicChunkUpdateLimit = Math.max(Renderer.MIN_CHUNK_UPDATES_PER_FRAME, renderer.dynamicChunkUpdateLimit-=2);
}else if(renderer.everBackedOffFromChunkUpdates){
renderer.dynamicChunkUpdateLimit+=1;
}else{
renderer.dynamicChunkUpdateLimit+=3;
}
}

// Mark fog-obscured chunks as invisible
Expand Down Expand Up @@ -1437,10 +1432,7 @@ private void onFrame() {
}

Thread.yield();
long timeBeforeSync = System.nanoTime();
Display.update();
long syncNanosecs = System.nanoTime() - timeBeforeSync;
timer.syncTime = timer.syncTime * .5 + (syncNanosecs / Timer.NANOSEC_PER_SEC) * .5;
}
}

Expand Down
7 changes: 4 additions & 3 deletions src/main/java/com/mojang/minecraft/render/Renderer.java
Expand Up @@ -20,10 +20,11 @@
import org.lwjgl.opengl.GL11;

public final class Renderer {

// Chunk update timing
public static final int MIN_CHUNK_UPDATES_PER_FRAME = 4;
public static int dynamicChunkUpdateLimit = MIN_CHUNK_UPDATES_PER_FRAME;

public int dynamicChunkUpdateLimit = MIN_CHUNK_UPDATES_PER_FRAME;
public boolean everBackedOffFromChunkUpdates= false;

public Minecraft minecraft;
public float fogColorMultiplier = 1F;
public boolean displayActive = false;
Expand Down
7 changes: 3 additions & 4 deletions src/main/java/com/mojang/util/Timer.java
Expand Up @@ -4,18 +4,17 @@ public class Timer {
public static final double NANOSEC_PER_SEC = 1000000000D;
public float tps;

public double firstHR;
public double lastHR;
public int elapsedTicks;
public float delta;
public float speed = 1F;
public float elapsedDelta = 0F;
public long lastHRClock;

public double syncTime;
public double chunkUpdateTime;
public double lastFrameDuration;

public Timer(float tps) {
this.tps = tps;
lastHRClock = System.nanoTime() / 1000000L;
this.firstHR = System.nanoTime()/NANOSEC_PER_SEC;
}
}

0 comments on commit f68c6a4

Please sign in to comment.