Skip to content

Commit

Permalink
Entities optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
xCollateral committed Sep 14, 2023
1 parent 8d5d790 commit 2ed323b
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 74 deletions.
1 change: 1 addition & 0 deletions src/main/java/net/vulkanmod/config/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class Config {
public int advCulling = 2;
public boolean indirectDraw = false;
public boolean uniqueOpaqueLayer = true;
public boolean entityCulling = true;

private static Path path;

Expand Down
7 changes: 6 additions & 1 deletion src/main/java/net/vulkanmod/config/Options.java
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,17 @@ Enable Gui optimizations (Stats bar, Chat, Debug Hud)
Use a culling algorithm that might improve performance by
reducing the number of non visible chunk sections rendered.
""")),
new SwitchOption("Entity Culling",
value -> config.entityCulling = value,
() -> config.entityCulling)
.setTooltip(Component.nullToEmpty("""
Enables culling for entities on non visible sections.""")),
new SwitchOption("Indirect Draw",
value -> config.indirectDraw = value,
() -> config.indirectDraw)
.setTooltip(Component.nullToEmpty("""
Reduces CPU overhead but increases GPU overhead.
Enabling it might help in CPU limited systems.""")),
Enabling it might help in CPU limited systems."""))
};

}
Expand Down
79 changes: 9 additions & 70 deletions src/main/java/net/vulkanmod/mixin/chunk/LevelRendererMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.phys.Vec3;
import net.vulkanmod.Initializer;
import net.vulkanmod.render.chunk.WorldRenderer;
import net.vulkanmod.render.profiling.Profiler2;
import net.vulkanmod.vulkan.util.Pair;
Expand Down Expand Up @@ -46,20 +47,13 @@ public abstract class LevelRendererMixin {
@Shadow private boolean generateClouds;
@Shadow @Final private EntityRenderDispatcher entityRenderDispatcher;

@Shadow protected abstract boolean shouldShowEntityOutlines();

@Shadow public abstract void needsUpdate();

@Shadow public abstract void renderLevel(PoseStack poseStack, float f, long l, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f);

private WorldRenderer worldRenderer;

@Unique
private static boolean ENTITIES_OPT = true;

@Unique
private Object2ReferenceOpenHashMap<Class<? extends Entity>, ObjectArrayList<Pair<Entity, MultiBufferSource>>> entitiesMap = new Object2ReferenceOpenHashMap<>();

//TODO clear VBOs

@Inject(method = "<init>", at = @At("RETURN"))
private void init(Minecraft minecraft, EntityRenderDispatcher entityRenderDispatcher, BlockEntityRenderDispatcher blockEntityRenderDispatcher, RenderBuffers renderBuffers, CallbackInfo ci) {
this.worldRenderer = WorldRenderer.init(this.renderBuffers);
Expand Down Expand Up @@ -89,8 +83,6 @@ private void renderBlockEntities(PoseStack poseStack, float f, long l, boolean b
private void setupRender(Camera camera, Frustum frustum, boolean isCapturedFrustum, boolean spectator) {
this.worldRenderer.setupRenderer(camera, frustum, isCapturedFrustum, spectator);

ENTITIES_OPT = true;
// ENTITIES_OPT = false;
entitiesMap.clear();
}

Expand Down Expand Up @@ -200,10 +192,11 @@ private void popProfiler3(PoseStack poseStack, float f, long l, boolean bl, Came
*/
@Overwrite
private void renderEntity(Entity entity, double d, double e, double f, float g, PoseStack poseStack, MultiBufferSource multiBufferSource) {
if(!ENTITIES_OPT) {
double h = Mth.lerp((double)g, entity.xOld, entity.getX());
double i = Mth.lerp((double)g, entity.yOld, entity.getY());
double j = Mth.lerp((double)g, entity.zOld, entity.getZ());
//Entity lists optimization
if(!Initializer.CONFIG.entityCulling) {
double h = Mth.lerp(g, entity.xOld, entity.getX());
double i = Mth.lerp(g, entity.yOld, entity.getY());
double j = Mth.lerp(g, entity.zOld, entity.getZ());
float k = Mth.lerp(g, entity.yRotO, entity.getYRot());
this.entityRenderDispatcher.render(entity, h - d, i - e, j - f, k, g, poseStack, multiBufferSource, this.entityRenderDispatcher.getPackedLightCoords(entity, g));
return;
Expand All @@ -226,7 +219,7 @@ private void renderEntity(Entity entity, double d, double e, double f, float g,
shift = At.Shift.AFTER, ordinal = 0)
)
private void renderEntities(PoseStack poseStack, float partialTicks, long l, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, CallbackInfo ci) {
if(!ENTITIES_OPT)
if(!Initializer.CONFIG.entityCulling)
return;

Vec3 cameraPos = WorldRenderer.getCameraPos();
Expand All @@ -245,58 +238,4 @@ private void renderEntities(PoseStack poseStack, float partialTicks, long l, boo
}
}

// @Redirect(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientLevel;entitiesForRendering()Ljava/lang/Iterable;"))
// private Iterable<Entity> replaceIterator(ClientLevel instance) {
//
// return () -> new Iterator<Entity>() {
// @Override
// public boolean hasNext() {
// return false;
// }
//
// @Override
// public Entity next() {
// return null;
// }
// };
// }
//
// @Inject(method = "renderLevel", at = @At(value = "INVOKE",
// target = "Lnet/minecraft/client/multiplayer/ClientLevel;entitiesForRendering()Ljava/lang/Iterable;",
// shift = At.Shift.AFTER),
// locals = LocalCapture.CAPTURE_FAILHARD
// )
// private void renderEntities(PoseStack poseStack, float f, long l, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, CallbackInfo ci) {
// for(Entity entity : this.level.entitiesForRendering()) {
// if (this.entityRenderDispatcher.shouldRender(entity, frustum, d0, d1, d2) || entity.hasIndirectPassenger(this.minecraft.player)) {
// BlockPos blockpos = entity.blockPosition();
// if ((this.level.isOutsideBuildHeight(blockpos.getY()) || this.isChunkCompiled(blockpos)) && (entity != p_109604_.getEntity() || p_109604_.isDetached() || p_109604_.getEntity() instanceof LivingEntity && ((LivingEntity)p_109604_.getEntity()).isSleeping()) && (!(entity instanceof LocalPlayer) || p_109604_.getEntity() == entity)) {
// ++this.renderedEntities;
// if (entity.tickCount == 0) {
// entity.xOld = entity.getX();
// entity.yOld = entity.getY();
// entity.zOld = entity.getZ();
// }
//
// MultiBufferSource multibuffersource;
// if (this.shouldShowEntityOutlines() && this.minecraft.shouldEntityAppearGlowing(entity)) {
// flag3 = true;
// OutlineBufferSource outlinebuffersource = this.renderBuffers.outlineBufferSource();
// multibuffersource = outlinebuffersource;
// int i = entity.getTeamColor();
// int j = 255;
// int k = i >> 16 & 255;
// int l = i >> 8 & 255;
// int i1 = i & 255;
// outlinebuffersource.setColor(k, l, i1, 255);
// } else {
// multibuffersource = bu;
// }
//
// this.renderEntity(entity, d0, d1, d2, p_109601_, p_109600_, multibuffersource);
// }
// }
// }
// }

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package net.vulkanmod.mixin.render.entity;

import net.minecraft.client.renderer.culling.Frustum;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import net.vulkanmod.Initializer;
import net.vulkanmod.render.chunk.WorldRenderer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

@Mixin(EntityRenderer.class)
public class EntityRendererM<T extends Entity> {

// /**
// * @author
// * @reason
// */
// @Overwrite
// public boolean shouldRender(T entity, Frustum frustum, double d, double e, double f) {
// if (!entity.shouldRender(d, e, f)) {
// return false;
// } else if (entity.noCulling) {
// return true;
// } else {
// AABB aABB = entity.getBoundingBoxForCulling().inflate(0.5);
// if (aABB.hasNaN() || aABB.getSize() == 0.0) {
// aABB = new AABB(entity.getX() - 2.0, entity.getY() - 2.0, entity.getZ() - 2.0, entity.getX() + 2.0, entity.getY() + 2.0, entity.getZ() + 2.0);
// }
//
//// WorldRenderer.getInstance().getSectionGrid().getSectionAtBlockPos((int) entity.getX(), (int) entity.getY(), (int) entity.getZ());
// WorldRenderer worldRenderer = WorldRenderer.getInstance();
//// return (worldRenderer.getLastFrame() == worldRenderer.getSectionGrid().getSectionAtBlockPos(entity.getBlockX(), entity.getBlockY(), entity.getBlockZ()).getLastFrame());
//
// return frustum.isVisible(aABB);
// }
// }

@Redirect(method = "shouldRender", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/culling/Frustum;isVisible(Lnet/minecraft/world/phys/AABB;)Z"))
private boolean isVisible(Frustum frustum, AABB aABB) {
if(Initializer.CONFIG.entityCulling) {
WorldRenderer worldRenderer = WorldRenderer.getInstance();

Vec3 pos = aABB.getCenter();

return (worldRenderer.getLastFrame() == worldRenderer.getSectionGrid().getSectionAtBlockPos((int) pos.x(), (int) pos.y(), (int) pos.z()).getLastFrame());
} else {
return frustum.isVisible(aABB);
}

}
}
24 changes: 21 additions & 3 deletions src/main/java/net/vulkanmod/render/chunk/WorldRenderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
import net.vulkanmod.vulkan.memory.IndirectBuffer;
import net.vulkanmod.vulkan.memory.MemoryTypes;
import net.vulkanmod.vulkan.shader.Pipeline;
import net.vulkanmod.vulkan.shader.ShaderManager;
import org.joml.FrustumIntersection;
import org.joml.Matrix4f;

Expand Down Expand Up @@ -91,6 +90,8 @@ public class WorldRenderer {
public RenderRegionCache renderRegionCache;
int nonEmptyChunks;

private final List<Runnable> onAllChangedCallbacks = new ObjectArrayList<>();

private WorldRenderer(RenderBuffers renderBuffers) {
this.minecraft = Minecraft.getInstance();
this.renderBuffers = renderBuffers;
Expand Down Expand Up @@ -258,6 +259,7 @@ private void initializeQueueForFullUpdate(Camera camera) {
RenderSection renderSection1 = this.sectionGrid.getSectionAtBlockPos(new BlockPos(k + SectionPos.sectionToBlockCoord(i1, 8), j, l + SectionPos.sectionToBlockCoord(j1, 8)));
if (renderSection1 != null) {
renderSection1.setGraphInfo(null, (byte) 0);
renderSection1.setLastFrame(this.lastFrame);
list.add(renderSection1);

}
Expand All @@ -275,6 +277,7 @@ private void initializeQueueForFullUpdate(Camera camera) {

} else {
renderSection.setGraphInfo(null, (byte) 0);
renderSection.setLastFrame(this.lastFrame);
this.chunkQueue.add(renderSection);
}

Expand Down Expand Up @@ -492,6 +495,8 @@ public void allChanged() {
this.sectionGrid = new SectionGrid(this.level, this.minecraft.options.getEffectiveRenderDistance());
this.chunkAreaQueue = new AreaSetQueue(this.sectionGrid.chunkAreaManager.size);

this.onAllChangedCallbacks.forEach(Runnable::run);

Entity entity = this.minecraft.getCameraEntity();
if (entity != null) {
this.sectionGrid.repositionCamera(entity.getX(), entity.getZ());
Expand All @@ -511,7 +516,7 @@ public void setLevel(@Nullable ClientLevel level) {
this.level = level;
if (level != null) {
this.allChanged();
} else {
} else {
if (this.sectionGrid != null) {
this.sectionGrid.releaseAllBuffers();
this.sectionGrid = null;
Expand All @@ -524,6 +529,14 @@ public void setLevel(@Nullable ClientLevel level) {

}

public void addOnAllChangedCallback(Runnable runnable) {
this.onAllChangedCallbacks.add(runnable);
}

public void clearOnAllChangedCallbacks() {
this.onAllChangedCallbacks.clear();
}

public void renderChunkLayer(RenderType renderType, PoseStack poseStack, double camX, double camY, double camZ, Matrix4f projection) {
//debug
// Profiler p = Profiler.getProfiler("chunks");
Expand Down Expand Up @@ -572,7 +585,7 @@ else if(layerName.equals("translucent"))
VRenderSystem.applyMVP(poseStack.last().pose(), projection);

Renderer renderer = Renderer.getInstance();
Pipeline pipeline = ShaderManager.getInstance().getTerrainShader(renderType);
Pipeline pipeline = TerrainShaderManager.getInstance().getTerrainShader(renderType);
renderer.bindPipeline(pipeline);
Renderer.getDrawer().bindAutoIndexBuffer(Renderer.getCommandBuffer(), 7);

Expand Down Expand Up @@ -730,4 +743,9 @@ public String getChunkStatistics() {
return String.format("Chunks: %d(%d)/%d D: %d, %s", this.nonEmptyChunks, j, i, this.lastViewDistance, tasksInfo);
}

public void cleanUp() {
if(indirectBuffers != null)
Arrays.stream(indirectBuffers).forEach(Buffer::freeBuffer);
}

}
1 change: 1 addition & 0 deletions src/main/resources/vulkanmod.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"profiling.GuiMixin",
"profiling.KeyboardHandlerM",

"render.entity.EntityRendererM",
"render.model.ModelPartCubeM",
"render.model.ModelPartM",
"render.vertex.FaceBakeryM",
Expand Down

0 comments on commit 2ed323b

Please sign in to comment.