Skip to content

Commit

Permalink
optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
quentin452 committed May 5, 2023
1 parent d5c9397 commit 34d5e51
Show file tree
Hide file tree
Showing 10 changed files with 246 additions and 167 deletions.
2 changes: 2 additions & 0 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,7 @@ dependencies {
implementation("org.joml:joml:1.10.5")

implementation 'org.apache.logging.log4j:log4j-core:2.16.0'

compile group: 'org.apache.commons', name: 'commons-math3', version: '3.6.1'
}

1 change: 0 additions & 1 deletion src/main/java/fr/iamacat/multithreading/asm/Mixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ public enum Mixin implements IMixin {

client_core_MixinLiquidRendering(Side.CLIENT,
m -> MultithreadingandtweaksMultithreadingConfig.enableMixinLiquidRendering, "core.MixinLiquidRendering"),

// MOD-FILTERED MIXINS

// The modFilter argument is a predicate, so you can also use the .and(), .or(), and .negate() methods to mix and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public class MultithreadingandtweaksMultithreadingConfig {
@Config.RequiresMcRestart
public static boolean enableMixinTileEntities;

@Config.Comment("Enable multithreaded Worldgen")
@Config.Comment("Enable multithreaded Worldgen)")
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean enableMixinWorldgen;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.entity.Entity;
Expand Down Expand Up @@ -70,47 +69,39 @@ public void onDoRender(Entity entity, double x, double y, double z, float yaw, f

public void renderEntities(World world, Collection<Entity> entities, RenderManager renderManager, float tickDelta) {
if (MultithreadingandtweaksMultithreadingConfig.enableMixinEntitiesRendering) {
int batchSize = BATCH_SIZE; // The maximum number of entities to render per batch
List<List<Entity>> entityBatches = splitEntitiesIntoBatches(entities);

// Submit rendering tasks to the thread pool using parallel stream
List<CompletableFuture<Void>> renderingFutures = entityBatches.parallelStream()
.map(entityBatch -> CompletableFuture.runAsync(() -> {
for (Entity entity : entityBatch) {
renderManager.renderEntityWithPosYaw(
entity,
entity.posX - RenderManager.renderPosX,
entity.posY - RenderManager.renderPosY,
entity.posZ - RenderManager.renderPosZ,
entity.rotationYaw,
tickDelta);
}
}, executorService))
.collect(Collectors.toList());

// Wait for all rendering tasks to complete
CompletableFuture.allOf(renderingFutures.toArray(new CompletableFuture[0]))
.join();
}
}
List<Entity> entityList = new ArrayList<>(entities);
int entityCount = entityList.size();
if (entityCount == 0) {
return;
}

private List<List<Entity>> splitEntitiesIntoBatches(Collection<Entity> entities) {
if (MultithreadingandtweaksMultithreadingConfig.enableMixinFireTick) {
int batchSize = BATCH_SIZE; // The maximum number of entities to render per batch
// Compute the number of tasks to use based on the number of available processors
int taskCount = Math.min(entityCount, ForkJoinPool.getCommonPoolParallelism());
int batchSize = (int) Math.ceil((double) entityCount / taskCount);

// Split entities into batches
List<List<Entity>> entityBatches = new ArrayList<>();
List<Entity> entityBatch = new ArrayList<>();
for (Entity entity : entities) {
entityBatch.add(entity);
if (entityBatch.size() == batchSize) {
entityBatches.add(entityBatch);
entityBatch = new ArrayList<>();
}
for (int i = 0; i < entityCount; i += batchSize) {
int end = Math.min(i + batchSize, entityCount);
entityBatches.add(entityList.subList(i, end));
}
if (!entityBatch.isEmpty()) {
entityBatches.add(entityBatch);
}
return entityBatches;

// Submit rendering tasks to the ForkJoinPool
ForkJoinPool.commonPool()
.execute(() -> {
entityBatches.parallelStream()
.forEach(entityBatch -> {
for (Entity entity : entityBatch) {
renderManager.renderEntityWithPosYaw(
entity,
entity.posX - RenderManager.renderPosX,
entity.posY - RenderManager.renderPosY,
entity.posZ - RenderManager.renderPosZ,
entity.rotationYaw,
tickDelta);
}
});
});
}
return new ArrayList<>();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import cpw.mods.fml.client.FMLClientHandler;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLiquid;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.util.EnumFacing;
Expand All @@ -24,6 +22,7 @@

import com.falsepattern.lib.compat.BlockPos;

import cpw.mods.fml.client.FMLClientHandler;
import fr.iamacat.multithreading.config.MultithreadingandtweaksMultithreadingConfig;

@Mixin(BlockLiquid.class)
Expand Down Expand Up @@ -58,16 +57,24 @@ private void tesselateFluid(IBlockAccess world, BlockPos pos, Tessellator tessel
}

private void tesselateBatch(World world, List<BlockPos> positions, Tessellator tessellator,
Set<BlockPos> visitedBlocks, int state) {
Block block = world.getBlock(positions.get(0).getX(), positions.get(0).getY(), positions.get(0).getZ());
Set<BlockPos> visitedBlocks, int state) {
Block block = world.getBlock(
positions.get(0)
.getX(),
positions.get(0)
.getY(),
positions.get(0)
.getZ());
List<BlockPos> fluidBlocks = new ArrayList<>();

Minecraft minecraft = FMLClientHandler.instance().getClient();
Minecraft minecraft = FMLClientHandler.instance()
.getClient();
TextureMap textureMapBlocks = minecraft.getTextureMapBlocks();

for (BlockPos blockPos : positions) {
Block currentBlock = world.getBlock(blockPos.getX(), blockPos.getY(), blockPos.getZ());
if (currentBlock.getMaterial().isLiquid() && currentBlock == block) {
if (currentBlock.getMaterial()
.isLiquid() && currentBlock == block) {
for (EnumFacing direction : EnumFacing.values()) {
BlockPos offset = blockPos.offset(direction);
if (!visitedBlocks.add(offset)) {
Expand All @@ -76,13 +83,24 @@ private void tesselateBatch(World world, List<BlockPos> positions, Tessellator t

Block offsetBlock = world.getBlock(offset.getX(), offset.getY(), offset.getZ());
int offsetMetadata = world.getBlockMetadata(offset.getX(), offset.getY(), offset.getZ());
if (offsetBlock.getMaterial().isReplaceable() ||
(offsetBlock.getMaterial().isLiquid() && offsetBlock == block && offsetMetadata == state)) {
putFluidVertex(tessellator, blockPos.getX(), blockPos.getY(), blockPos.getZ(),
textureMapBlocks.getTextureExtry(offsetBlock.getIcon(0, offsetMetadata).getIconName()), direction);
} else if (offsetBlock.getMaterial().isLiquid() && offsetBlock == block) {
fluidBlocks.add(offset);
}
if (offsetBlock.getMaterial()
.isReplaceable()
|| (offsetBlock.getMaterial()
.isLiquid() && offsetBlock == block
&& offsetMetadata == state)) {
putFluidVertex(
tessellator,
blockPos.getX(),
blockPos.getY(),
blockPos.getZ(),
textureMapBlocks.getTextureExtry(
offsetBlock.getIcon(0, offsetMetadata)
.getIconName()),
direction);
} else if (offsetBlock.getMaterial()
.isLiquid() && offsetBlock == block) {
fluidBlocks.add(offset);
}
}
}
}
Expand All @@ -92,8 +110,8 @@ private void tesselateBatch(World world, List<BlockPos> positions, Tessellator t
}
}


private void putFluidVertex(Tessellator tessellator, double x, double y, double z, TextureAtlasSprite sprite, EnumFacing facing) {
private void putFluidVertex(Tessellator tessellator, double x, double y, double z, TextureAtlasSprite sprite,
EnumFacing facing) {
float minU, maxU, minV, maxV;
if (facing == EnumFacing.UP || facing == EnumFacing.DOWN) {
minU = sprite.getInterpolatedU(x * 8);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package fr.iamacat.multithreading.mixins.client.core;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.nbt.NBTTagCompound;
Expand All @@ -25,48 +25,53 @@
public abstract class MixinTileEntities {

private static final int BATCH_SIZE = MultithreadingandtweaksMultithreadingConfig.batchsize;
private static final ExecutorService THREAD_POOL = Executors
.newFixedThreadPool(MultithreadingandtweaksMultithreadingConfig.numberofcpus);

private World world;
private List<TileEntity> tileEntities;
private final Object lock = new Object();

@Inject(method = "init", at = @At("RETURN"))
public void init(CallbackInfo ci) {
this.world = world;
this.tileEntities = new ArrayList<>();
}

@Inject(method = "func_147455_a", at = @At("RETURN"))
public void addTileEntity(TileEntity tileEntity) {
synchronized (lock) {
this.tileEntities.add(tileEntity);
}
this.tileEntities.add(tileEntity);
}

@Inject(method = "process", at = @At("RETURN"))
public void process(CallbackInfo ci) {
public void processTileEntities() {
// Split the tile entities into batches
List<List<TileEntity>> batches = splitIntoBatches(this.tileEntities);

// Process each batch using a for loop
// Process each batch using a thread pool
List<Future<?>> futures = new ArrayList<>();
for (List<TileEntity> batch : batches) {
processBatch(batch);
futures.add(THREAD_POOL.submit(() -> processBatch(batch)));
}

// Wait for all tasks to complete
for (Future<?> future : futures) {
try {
future.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}

private void processBatch(List<TileEntity> batch) {
if (MultithreadingandtweaksMultithreadingConfig.enableMixinTileEntities) {
for (TileEntity tileEntity : batch) {
// Process each tile entity
tileEntity.updateEntity();
NBTTagCompound tag = new NBTTagCompound();
tileEntity.writeToNBT(tag);
this.world.setTileEntity(
tileEntity.xCoord,
tileEntity.yCoord,
tileEntity.zCoord,
TileEntity.createAndLoadEntity(tag));
}
for (TileEntity tileEntity : batch) {
// Process each tile entity
tileEntity.updateEntity();
NBTTagCompound tag = new NBTTagCompound();
tileEntity.writeToNBT(tag);
this.world.setTileEntity(
tileEntity.xCoord,
tileEntity.yCoord,
tileEntity.zCoord,
TileEntity.createAndLoadEntity(tag));
}
}

Expand All @@ -79,42 +84,34 @@ private static <T> List<List<T>> splitIntoBatches(List<T> list) {

@Inject(method = "renderTileEntities", at = @At("HEAD"))
public void renderTileEntities(World world, List<TileEntity> tileEntities, CallbackInfo ci) {
// Use a ForkJoinPool with the number of threads equal to the number of available processors
ForkJoinPool pool = new ForkJoinPool(MultithreadingandtweaksMultithreadingConfig.numberofcpus);

// Process each tile entity in parallel
pool.submit(
() -> tileEntities.parallelStream()
.forEach(tileEntity -> {
if (tileEntity != null) {
world.addTileEntity(tileEntity);
}
}))
.join();

pool.shutdown();
// Process each tile entity in parallel using a thread pool
List<Future<?>> futures = new ArrayList<>();
for (TileEntity tileEntity : tileEntities) {
if (tileEntity != null) {
futures.add(THREAD_POOL.submit(() -> renderTileEntity(tileEntity)));
}
}

// Wait for all tasks to complete
for (Future<?> future : futures) {
try {
future.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}

public void render(TileEntity tileentity, float partialTicks, int destroyStage, double x, double y, double z) {
double dx = tileentity.xCoord - x;
double dy = tileentity.yCoord - y;
double dz = tileentity.zCoord - z;
double distanceSq = dx * dx + dy * dy + dz * dz;
if (distanceSq < 4096.0D) {
// Use multithreaded rendering
List<TileEntity> tileEntities = Collections.singletonList(tileentity);
tileEntities.parallelStream()
.forEach(te -> {
GL11.glPushMatrix();
GL11.glTranslated(te.xCoord + 0.5 - x, te.yCoord + 0.5 - y, te.zCoord + 0.5 - z);
TileEntitySpecialRenderer renderer = TileEntityRendererDispatcher.instance.getSpecialRenderer(te);
if (renderer != null) {
if (te.shouldRenderInPass(destroyStage)) {
renderer.renderTileEntityAt(te, x, y, z, partialTicks);
}
}
GL11.glPopMatrix();
});
private void renderTileEntity(TileEntity tileentity) {
GL11.glPushMatrix();
GL11.glTranslated(
tileentity.xCoord + 0.5 - RenderManager.renderPosX,
tileentity.yCoord + 0.5 - RenderManager.renderPosY,
tileentity.zCoord + 0.5 - RenderManager.renderPosZ);
TileEntitySpecialRenderer renderer = TileEntityRendererDispatcher.instance.getSpecialRenderer(tileentity);
if (renderer != null) {
renderer.renderTileEntityAt(tileentity, 0, 0, 0, 0);
}
GL11.glPopMatrix();
}
}
Loading

0 comments on commit 34d5e51

Please sign in to comment.