Made chunk loading smarter, boosted the FPS a lot

This commit is contained in:
LAX1DUDE 2022-07-03 13:49:55 -07:00
parent 1b2cb34bb1
commit 8aeaf404ca
7 changed files with 130 additions and 123 deletions

View file

@ -137,9 +137,11 @@ public class Minecraft implements Runnable {
/** The profiler instance */
public final Profiler mcProfiler = new Profiler();
private long field_83002_am = -1L;
public int chunkUpdates = 0;
public int chunkGeometryUpdates = 0;
public static int debugChunkUpdates = 0;
public static int debugChunkGeometryUpdates = 0;
/**
* Set to true to keep the game loop running. Set to false by shutdown() to
@ -724,6 +726,8 @@ public class Minecraft implements Runnable {
fpsCounter = 0;
debugChunkUpdates = chunkUpdates;
chunkUpdates = 0;
debugChunkGeometryUpdates = chunkGeometryUpdates;
chunkGeometryUpdates = 0;
secondTimer = System.currentTimeMillis();
}
this.mcProfiler.startSection("syncDisplay");

View file

@ -8,7 +8,7 @@ public enum EnumOptions {
CHAT_VISIBILITY("options.chat.visibility", false, false), CHAT_COLOR("options.chat.color", false, true), CHAT_LINKS("options.chat.links", false, true), CHAT_OPACITY("options.chat.opacity", true, false),
CHAT_LINKS_PROMPT("options.chat.links.prompt", false, true), USE_SERVER_TEXTURES("options.serverTextures", false, true), SNOOPER_ENABLED("options.snooper", false, true), USE_FULLSCREEN("options.fullscreen", false, true),
PATCH_ANGLE("options.patchAnisotropic", false, true), ENABLE_FOG("options.fog", false, true), SHOW_CAPE("options.showCape", false, true), ANTIALIASING("options.framebufferAntialias", false, false), CHAT_SCALE("options.chat.scale", true, false), CHAT_WIDTH("options.chat.width", true, false),
CHAT_HEIGHT_FOCUSED("options.chat.height.focused", true, false), CHAT_HEIGHT_UNFOCUSED("options.chat.height.unfocused", true, false);
CHAT_HEIGHT_FOCUSED("options.chat.height.focused", true, false), CHAT_HEIGHT_UNFOCUSED("options.chat.height.unfocused", true, false), CHUNK_UPDATES("options.chunkUpdates", false, false);
private final boolean enumFloat;
private final boolean enumBoolean;

View file

@ -87,5 +87,11 @@ class EnumOptionsHelper {
} catch (NoSuchFieldError var10) {
;
}
try {
enumOptionsMappingHelperArray[EnumOptions.CHUNK_UPDATES.ordinal()] = 16;
} catch (NoSuchFieldError var10) {
;
}
}
}

View file

@ -135,6 +135,7 @@ public class GameSettings {
public boolean allowFNAWSkins = true;
public boolean showOtherCapes = true;
public int chunkUpdatePerFrame = 0;
public GameSettings(Minecraft par1Minecraft) {
this.keyBindings = new KeyBinding[] { this.keyBindAttack, this.keyBindUseItem, this.keyBindForward, this.keyBindLeft, this.keyBindBack, this.keyBindRight, this.keyBindJump, this.keyBindSneak, this.keyBindDrop, this.keyBindInventory,
@ -291,6 +292,10 @@ public class GameSettings {
this.limitFramerate = (this.limitFramerate + par2 + 3) % 3;
}
if (par1EnumOptions == EnumOptions.CHUNK_UPDATES) {
this.chunkUpdatePerFrame = (this.chunkUpdatePerFrame + par2) % 5;
}
if (par1EnumOptions == EnumOptions.DIFFICULTY) {
this.difficulty = this.difficulty + par2 & 3;
}
@ -460,8 +465,9 @@ public class GameSettings {
: (par1EnumOptions == EnumOptions.FRAMERATE_LIMIT ? var3 + getTranslation(LIMIT_FRAMERATES, this.limitFramerate)
: (par1EnumOptions == EnumOptions.AMBIENT_OCCLUSION ? var3 + getTranslation(AMBIENT_OCCLUSIONS, this.ambientOcclusion)
: (par1EnumOptions == EnumOptions.ANTIALIASING ? var3 + getTranslation(ANTIALIASING, this.antialiasMode)
: (par1EnumOptions == EnumOptions.CHUNK_UPDATES ? var3 + (chunkUpdatePerFrame + 1)
: (par1EnumOptions == EnumOptions.GRAPHICS ? (this.fancyGraphics ? var3 + var2.translateKey("options.graphics.fancy") : var3 + var2.translateKey("options.graphics.fast"))
: var3))))))));
: var3)))))))));
}
}
@ -519,6 +525,7 @@ public class GameSettings {
if(yee.hasKey("showSkinRightLeg")) showSkinRightLeg = yee.getBoolean("showSkinRightLeg");
if(yee.hasKey("allowFNAWSkins")) allowFNAWSkins = yee.getBoolean("allowFNAWSkins");
if(yee.hasKey("showOtherCapes")) showOtherCapes = yee.getBoolean("showOtherCapes");
if(yee.hasKey("chunkUpdates")) chunkUpdatePerFrame = yee.getInteger("chunkUpdates");
for (int var4 = 0; var4 < this.keyBindings.length; ++var4) {
if(yee.hasKey(keyBindings[var4].keyDescription)) this.keyBindings[var4].keyCode = yee.getInteger(keyBindings[var4].keyDescription);
@ -581,6 +588,7 @@ public class GameSettings {
yee.setBoolean("showSkinRightLeg", showSkinRightLeg);
yee.setBoolean("allowFNAWSkins", allowFNAWSkins);
yee.setBoolean("showOtherCapes", showOtherCapes);
yee.setInteger("chunkUpdates", chunkUpdatePerFrame);
for (int var4 = 0; var4 < this.keyBindings.length; ++var4) {
yee.setInteger(keyBindings[var4].keyDescription, keyBindings[var4].keyCode);

View file

@ -17,7 +17,7 @@ public class GuiVideoSettings extends GuiScreen {
/** An array of all of EnumOption's video options. */
private static EnumOptions[] videoOptions = new EnumOptions[] { EnumOptions.GRAPHICS, EnumOptions.RENDER_DISTANCE, EnumOptions.AMBIENT_OCCLUSION, EnumOptions.FRAMERATE_LIMIT, EnumOptions.ANAGLYPH, EnumOptions.VIEW_BOBBING,
EnumOptions.GUI_SCALE, EnumOptions.GAMMA, EnumOptions.RENDER_CLOUDS, EnumOptions.ENABLE_FOG, EnumOptions.PARTICLES, EnumOptions.PATCH_ANGLE };
EnumOptions.GUI_SCALE, EnumOptions.GAMMA, EnumOptions.RENDER_CLOUDS, EnumOptions.ENABLE_FOG, EnumOptions.PARTICLES, EnumOptions.PATCH_ANGLE, EnumOptions.CHUNK_UPDATES };
public GuiVideoSettings(GuiScreen par1GuiScreen, GameSettings par2GameSettings) {
this.parentGuiScreen = par1GuiScreen;
@ -31,7 +31,7 @@ public class GuiVideoSettings extends GuiScreen {
StringTranslate var1 = StringTranslate.getInstance();
this.screenTitle = var1.translateKey("options.videoTitle");
this.buttonList.clear();
this.buttonList.add(new GuiButton(200, this.width / 2 - 100, this.height / 6 + 168, var1.translateKey("gui.done")));
this.buttonList.add(new GuiButton(200, this.width / 2 - 100, this.height / 6 + 178, var1.translateKey("gui.done")));
this.is64bit = true;
/*
String[] var2 = new String[] { "sun.arch.data.model", "com.ibm.vm.bitmode", "os.arch" };

View file

@ -145,6 +145,8 @@ public class RenderGlobal implements IWorldAccess {
*/
int frustumCheckOffset = 0;
private int occlusionForcedIndexShift = 0;
public RenderGlobal(Minecraft par1Minecraft, RenderEngine par2RenderEngine) {
this.mc = par1Minecraft;
this.renderEngine = par2RenderEngine;
@ -415,7 +417,8 @@ public class RenderGlobal implements IWorldAccess {
}
public String getDebugInfoShort() {
return "" + Minecraft.debugFPS + "fps | C: " + this.renderersBeingRendered + "/" + this.renderersLoaded + ", E: " + this.countEntitiesRendered + "+" + tileEntities.size()+", U: "+Minecraft.debugChunkUpdates;
return "" + Minecraft.debugFPS + "fps | C: " + this.renderersBeingRendered + "/" + this.renderersLoaded + ", E: " + this.countEntitiesRendered + "+" + tileEntities.size() +
", U: " + Minecraft.debugChunkGeometryUpdates + "/" + Minecraft.debugChunkUpdates;
}
/**
@ -564,11 +567,11 @@ public class RenderGlobal implements IWorldAccess {
RenderHelper.disableStandardItemLighting();
byte var17 = 0;
int var34;
long queryRate = 50l;
long stallRateVisible = 50l;
long stallRateVisible = 60l;
long stallRate = 500l;
int cooldownRate = 10;
int cooldownRate = 13;
long ct = System.currentTimeMillis();
if(par2 == 0) {
@ -578,26 +581,36 @@ public class RenderGlobal implements IWorldAccess {
int ccx = c.chunkX - fx;
int ccy = c.chunkY - fy;
int ccz = c.chunkZ - fz;
if((ccx < 2 && ccx > -2 && ccy < 2 && ccy > -2 && ccz < 2 && ccz > -2) || glOcclusionQuery[c.chunkIndex] == -1) {
boolean forced = ccx < 2 && ccx > -2 && ccy < 2 && ccy > -2 && ccz < 2 && ccz > -2;
if(forced) {
c.hasOcclusionData = 5;
}
if(forced || glOcclusionQuery[c.chunkIndex] == -1) {
c.isNowVisible = true;
c.isVisible = cooldownRate;
}else if(!c.skipAllRenderPasses() && c.isInFrustum) {
if(occlusionQueryAvailable[c.chunkIndex]) {
if(EaglerAdapter.glGetQueryResultAvailable(glOcclusionQuery[c.chunkIndex])) {
if(EaglerAdapter.glGetQueryResult(glOcclusionQuery[c.chunkIndex])) {
c.isNowVisible = true;
c.isVisible = cooldownRate;
}else {
if(c.isVisible <= 0) {
c.isNowVisible = false;
}else if(occlusionQueryAvailable[c.chunkIndex]) {
if(EaglerAdapter.glGetQueryResultAvailable(glOcclusionQuery[c.chunkIndex])) {
if(EaglerAdapter.glGetQueryResult(glOcclusionQuery[c.chunkIndex])) {
c.isNowVisible = true;
++c.hasOcclusionData;
if(c.hasOcclusionData > 5) {
c.hasOcclusionData = 5;
}
c.isVisible = cooldownRate;
}else {
if(c.isVisible <= 0) {
c.isNowVisible = false;
--c.hasOcclusionData;
if(c.hasOcclusionData < 0) {
c.hasOcclusionData = 0;
}
}
occlusionQueryAvailable[c.chunkIndex] = false;
occlusionQueryStalled[c.chunkIndex] = 0l;
}else if(occlusionQueryStalled[c.chunkIndex] != 0l && ct - occlusionQueryStalled[c.chunkIndex] > stallRateVisible) {
c.isNowVisible = true;
c.isVisible = cooldownRate;
}
occlusionQueryAvailable[c.chunkIndex] = false;
occlusionQueryStalled[c.chunkIndex] = 0l;
}else if(occlusionQueryStalled[c.chunkIndex] != 0l && ct - occlusionQueryStalled[c.chunkIndex] > stallRateVisible) {
c.isNowVisible = true;
c.isVisible = cooldownRate;
}
}
}
@ -610,6 +623,27 @@ public class RenderGlobal implements IWorldAccess {
ct = System.currentTimeMillis();
if(par2 == 0 && ct - lastOcclusionQuery > queryRate) {
int totalRenderers = this.sortedWorldRenderers.length;
int inFrustumCount = 0;
for (int i = 0; i < totalRenderers; ++i) {
WorldRenderer c = this.sortedWorldRenderers[i];
if(c.isInFrustum) {
++inFrustumCount;
}
}
int occlusionForceCount = (int)(500l / queryRate);
int occlusionForceStep = MathHelper.floor_float(inFrustumCount / (float)occlusionForceCount) + 1;
int forceStartIndex = occlusionForcedIndexShift * occlusionForceStep;
int forceEndIndex = forceStartIndex + occlusionForceStep;
++occlusionForcedIndexShift;
if(forceEndIndex + (occlusionForceStep >> 1) > inFrustumCount) {
forceEndIndex = inFrustumCount;
occlusionForcedIndexShift = 0;
}
inFrustumCount = 0;
lastOcclusionQuery = ct;
this.theWorld.theProfiler.endStartSection("occl");
EaglerAdapter.glEnable(EaglerAdapter.GL_CULL_FACE);
@ -622,7 +656,14 @@ public class RenderGlobal implements IWorldAccess {
int ccx = c.chunkX - fx;
int ccy = c.chunkY - fy;
int ccz = c.chunkZ - fz;
if(!c.skipAllRenderPasses() && c.isInFrustum && !(ccx < 2 && ccx > -2 && ccy < 2 && ccy > -2 && ccz < 2 && ccz > -2)) {
boolean shouldTry = c.isInFrustum;
if(c.isInFrustum) {
++inFrustumCount;
if(!shouldTry && inFrustumCount >= forceStartIndex && inFrustumCount < forceEndIndex) {
shouldTry = true;
}
}
if(shouldTry && !(ccx < 2 && ccx > -2 && ccy < 2 && ccy > -2 && ccz < 2 && ccz > -2)) {
boolean stalled = false;
if(occlusionQueryAvailable[c.chunkIndex]) {
if(occlusionQueryStalled[c.chunkIndex] == 0l) {
@ -642,6 +683,11 @@ public class RenderGlobal implements IWorldAccess {
EaglerAdapter.glDrawOcclusionBB((float)(c.posX - var33), (float)(c.posY - var7), (float)(c.posZ - var9), 16, 16, 16);
EaglerAdapter.glEndQuery();
}
}else {
--c.hasOcclusionData;
if(c.hasOcclusionData < 0) {
c.hasOcclusionData = 0;
}
}
if(c.isVisible > 0) {
--c.isVisible;
@ -1227,54 +1273,31 @@ public class RenderGlobal implements IWorldAccess {
WorldRenderer var10;
int var11;
int var12;
label136:
List laterUpdateList = new ArrayList(var7);
for (var9 = 0; var9 < var7; ++var9) {
var10 = (WorldRenderer) this.worldRenderersToUpdate.get(var9);
if (var10 != null) {
if (!par2) {
if (var10.distanceToEntitySquared(par1EntityLiving) > 256.0F) {
for (var11 = 0; var11 < var3 && (var5[var11] == null || var4.doCompare(var5[var11], var10) <= 0); ++var11) {
;
}
--var11;
if (var11 > 0) {
var12 = var11;
while (true) {
--var12;
if (var12 == 0) {
var5[var11] = var10;
continue label136;
}
var5[var12 - 1] = var5[var12];
}
}
continue;
if (!var10.isInFrustum || !var10.isNowVisible || var10.hasOcclusionData < 3) { // config?
laterUpdateList.add(var10);
}else {
if (var6 == null) {
var6 = new ArrayList();
}
} else if (!var10.isInFrustum) {
continue;
++var8;
var6.add(var10);
}
if (var6 == null) {
var6 = new ArrayList();
}
++var8;
var6.add(var10);
this.worldRenderersToUpdate.set(var9, (Object) null);
}
}
this.worldRenderersToUpdate = laterUpdateList;
this.theWorld.theProfiler.endSection();
this.theWorld.theProfiler.startSection("sort");
this.theWorld.theProfiler.startSection("sortAndUpdate");
int updates = 0;
int dropped = 0;
if (var6 != null) {
if (var6.size() > 1) {
Collections.sort(var6, var4);
@ -1282,71 +1305,24 @@ public class RenderGlobal implements IWorldAccess {
for (var9 = var6.size() - 1; var9 >= 0; --var9) {
var10 = (WorldRenderer) var6.get(var9);
var10.updateRenderer();
var10.needsUpdate = false;
if(updates >= mc.gameSettings.chunkUpdatePerFrame + 1) { // make configurable
this.worldRenderersToUpdate.add(var10);
++dropped;
}else {
++mc.chunkUpdates;
var10.updateRenderer();
var10.needsUpdate = false;
if(!var10.skipAllRenderPasses()) {
++updates;
++mc.chunkGeometryUpdates;
}
}
}
}
this.theWorld.theProfiler.endSection();
var9 = 0;
int var16;
for (var16 = var3 - 1; var16 >= 0; --var16) {
WorldRenderer var17 = var5[var16];
if (var17 != null) {
if (!var17.isInFrustum && var16 != var3 - 1) {
var5[var16] = null;
var5[0] = null;
break;
}
var5[var16].updateRenderer();
var5[var16].needsUpdate = false;
++var9;
}
}
this.mc.chunkUpdates += var9;
this.theWorld.theProfiler.startSection("cleanup");
var16 = 0;
var11 = 0;
for (var12 = this.worldRenderersToUpdate.size(); var16 != var12; ++var16) {
WorldRenderer var13 = (WorldRenderer) this.worldRenderersToUpdate.get(var16);
if (var13 != null) {
boolean var14 = false;
for (int var15 = 0; var15 < var3 && !var14; ++var15) {
if (var13 == var5[var15]) {
var14 = true;
}
}
if (!var14) {
if (var11 != var16) {
this.worldRenderersToUpdate.set(var11, var13);
}
++var11;
}
}
}
this.theWorld.theProfiler.endSection();
this.theWorld.theProfiler.startSection("trim");
while (true) {
--var16;
if (var16 < var11) {
this.theWorld.theProfiler.endSection();
return var7 == var8 + var9;
}
this.worldRenderersToUpdate.remove(var16);
}
return true;
}
private static final TextureLocation tex_terrain = new TextureLocation("/terrain.png");
@ -1561,7 +1537,8 @@ public class RenderGlobal implements IWorldAccess {
*/
public void clipRenderersByFrustum(ICamera par1ICamera, float par2) {
for (int var3 = 0; var3 < this.worldRenderers.length; ++var3) {
if (!this.worldRenderers[var3].skipAllRenderPasses() && (!this.worldRenderers[var3].isInFrustum || (var3 + this.frustumCheckOffset & 15) == 0)) {
WorldRenderer rd = this.worldRenderers[var3];
if (!rd.isInFrustum || (var3 + this.frustumCheckOffset & 31) == 0) {
this.worldRenderers[var3].updateInFrustum(par1ICamera);
}
}

View file

@ -14,6 +14,7 @@ public class WorldRenderer {
private int glRenderList = -1;
private static Tessellator tessellator = Tessellator.instance;
public static int chunksUpdated = 0;
public static int chunksGeometryUpdated = 0;
public int posX;
public int posY;
public int posZ;
@ -72,6 +73,7 @@ public class WorldRenderer {
/** Is the chunk lit */
public boolean isChunkLit;
private boolean isInitialized = false;
public int hasOcclusionData = 0;
/** All the tile entities that have special rendering code for this chunk */
public List tileEntityRenderers = new ArrayList();
@ -96,6 +98,7 @@ public class WorldRenderer {
public void setPosition(int par1, int par2, int par3) {
if (par1 != this.posX || par2 != this.posY || par3 != this.posZ) {
this.setDontDraw();
this.hasOcclusionData = 0;
this.posX = par1;
this.posY = par2;
this.posZ = par3;
@ -224,6 +227,11 @@ public class WorldRenderer {
break;
}
}
if(!(skipRenderPass[0] && skipRenderPass[1])) {
++chunksGeometryUpdated;
}
EaglerAdapter.hintAnisotropicFix(false);
}
@ -283,6 +291,10 @@ public class WorldRenderer {
public void callOcclusionQueryList() {
EaglerAdapter.glCallList(this.glRenderList + 2);
}
public boolean shouldTryOcclusionQuery() {
return !this.isInitialized ? true : !this.skipRenderPass[0] || !this.skipRenderPass[1];
}
/**
* Checks if all render passes are to be skipped. Returns false if the renderer