Aa
This commit is contained in:
@@ -568,9 +568,6 @@ public class ModelFactory {
|
||||
}
|
||||
|
||||
private ModelTextureUpload putTextures(int id, ColourDepthTextureData[] textures) {
|
||||
int X = (id&0xFF) * MODEL_TEXTURE_SIZE*3;
|
||||
int Y = ((id>>8)&0xFF) * MODEL_TEXTURE_SIZE*2;
|
||||
|
||||
int texIndex = 0;
|
||||
int[][] texData = new int[6*4][];
|
||||
for (int subTex = 0; subTex < 6; subTex++) {
|
||||
|
||||
@@ -116,7 +116,7 @@ public class ModelTextureBakery {
|
||||
.getBlockModels()
|
||||
.getModel(state);
|
||||
|
||||
var entityModel = state.hasBlockEntity()?BakedBlockEntityModel.bake(state):null;
|
||||
BakedBlockEntityModel entityModel = state.hasBlockEntity()?BakedBlockEntityModel.bake(state):null;
|
||||
|
||||
int oldFB = GlStateManager.getBoundFramebuffer();
|
||||
GL11C.glViewport(0, 0, this.width, this.height);
|
||||
@@ -282,14 +282,17 @@ public class ModelTextureBakery {
|
||||
//System.err.println("REPLACE THE UPLOADING WITH THREAD SAFE VARIENT");
|
||||
BufferRenderer.draw(bb.end());
|
||||
} catch (IllegalStateException e) {
|
||||
System.err.println("Got empty buffer builder! for block " + state);
|
||||
//System.err.println("Got empty buffer builder! for block " + state);
|
||||
}
|
||||
|
||||
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
|
||||
int[] colourData = new int[this.width*this.height];
|
||||
int[] depthData = new int[this.width*this.height];
|
||||
glGetTextureImage(this.colourTex.id, 0, GL_RGBA, GL_UNSIGNED_BYTE, colourData);
|
||||
glGetTextureImage(this.depthTex.id, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, depthData);
|
||||
|
||||
//TODO: USE A PBO to make a download stream of the textures to a buffer to download then do a download stream
|
||||
//glGetTextureImage(this.colourTex.id, 0, GL_RGBA, GL_UNSIGNED_BYTE, colourData);
|
||||
//glGetTextureImage(this.depthTex.id, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, depthData);
|
||||
|
||||
return new ColourDepthTextureData(colourData, depthData, this.width, this.height);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
package me.cortex.voxy.client.core.model;
|
||||
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayFIFOQueue;
|
||||
import it.unimi.dsi.fastutil.ints.IntLinkedOpenHashSet;
|
||||
import me.cortex.voxy.common.world.other.Mapper;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.opengl.GL;
|
||||
import org.lwjgl.opengl.GLCapabilities;
|
||||
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
//Uses an off thread gl context to do the model baking on
|
||||
public class OffThreadModelBakerySystem {
|
||||
//NOTE: Create a static final context offthread and dont close it, just reuse the context, since context creation is expensive
|
||||
private static final long GL_CTX;
|
||||
private static final GLCapabilities GL_CAPS;
|
||||
static {
|
||||
var caps = GL.getCapabilities();
|
||||
GLFW.glfwMakeContextCurrent(0L);
|
||||
GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, 0);
|
||||
GL_CTX = GLFW.glfwCreateWindow(1, 1, "", 0, MinecraftClient.getInstance().getWindow().getHandle());
|
||||
GLFW.glfwMakeContextCurrent(GL_CTX);
|
||||
GL_CAPS = GL.createCapabilities();
|
||||
GLFW.glfwMakeContextCurrent(MinecraftClient.getInstance().getWindow().getHandle());
|
||||
GL.setCapabilities(caps);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private final ModelStore storage = new ModelStore(16);
|
||||
public final ModelFactory factory;
|
||||
private final ConcurrentLinkedDeque<NewModelBufferDelta> bufferDeltas = new ConcurrentLinkedDeque<>();
|
||||
private final IntLinkedOpenHashSet blockIdQueue = new IntLinkedOpenHashSet();
|
||||
private final Semaphore queueCounter = new Semaphore(0);
|
||||
|
||||
|
||||
|
||||
private final Thread bakingThread;
|
||||
private volatile boolean running = true;
|
||||
public OffThreadModelBakerySystem(Mapper mapper) {
|
||||
this.factory = new ModelFactory(mapper);
|
||||
this.bakingThread = new Thread(this::bakeryThread);
|
||||
this.bakingThread.setName("Baking thread");
|
||||
this.bakingThread.setPriority(3);
|
||||
this.bakingThread.start();
|
||||
}
|
||||
|
||||
private void bakeryThread() {
|
||||
GLFW.glfwMakeContextCurrent(GL_CTX);
|
||||
GL.setCapabilities(GL_CAPS);
|
||||
|
||||
//FIXME: tile entities will probably need to be baked on the main render thread
|
||||
while (true) {
|
||||
this.queueCounter.acquireUninterruptibly();
|
||||
if (!this.running) break;
|
||||
int blockId;
|
||||
synchronized (this.blockIdQueue) {
|
||||
blockId = this.blockIdQueue.removeFirstInt();
|
||||
VarHandle.fullFence();//Ensure memory coherancy
|
||||
}
|
||||
|
||||
this.factory.addEntry(blockId);
|
||||
}
|
||||
}
|
||||
|
||||
//Changes to the block table/atlas must be run on the main render thread
|
||||
public void syncChanges() {
|
||||
//TODO: FIXME!! the ordering of the uploads here and the order that _both_ model AND biome are done in the bakery thread MUST be the same!!!
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
this.running = false;
|
||||
this.queueCounter.release(999);
|
||||
try {
|
||||
this.bakingThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
this.factory.free();
|
||||
this.storage.free();
|
||||
}
|
||||
|
||||
public void requestBlockBake(int blockId) {
|
||||
synchronized (this.blockIdQueue) {
|
||||
if (this.blockIdQueue.add(blockId)) {
|
||||
VarHandle.fullFence();//Ensure memory coherancy
|
||||
this.queueCounter.release(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addDebugData(List<String> debug) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ public class OnThreadModelBakerySystem {
|
||||
|
||||
public void tick() {
|
||||
//There should be a method to access the frame time IIRC, if the user framecap is unlimited lock it to like 60 fps for computation
|
||||
int BUDGET = 5;//TODO: make this computed based on the remaining free time in a frame (and like div by 2 to reduce overhead) (with a min of 1)
|
||||
int BUDGET = 20;//TODO: make this computed based on the remaining free time in a frame (and like div by 2 to reduce overhead) (with a min of 1)
|
||||
for (int i = 0; i < BUDGET; i++) {
|
||||
if (!this.blockIdQueue.isEmpty()) {
|
||||
int blockId = -1;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package me.cortex.voxy.client.core.rendering;
|
||||
|
||||
import me.cortex.voxy.client.config.VoxyConfig;
|
||||
import me.cortex.voxy.client.core.model.OffThreadModelBakerySystem;
|
||||
import me.cortex.voxy.client.core.model.OnThreadModelBakerySystem;
|
||||
import me.cortex.voxy.client.core.rendering.building.BuiltSection;
|
||||
import me.cortex.voxy.client.core.rendering.building.RenderGenerationService;
|
||||
@@ -17,8 +16,8 @@ public class RenderService {
|
||||
public RenderService(WorldEngine world) {
|
||||
this.modelService = new OnThreadModelBakerySystem(world.getMapper());
|
||||
this.renderGen = new RenderGenerationService(world, this.modelService, VoxyConfig.CONFIG.renderThreads, this::consumeRenderBuildResult, false);
|
||||
for(int x = -10; x<=10;x++) {
|
||||
for (int z = -10; z <= 10; z++) {
|
||||
for(int x = -200; x<=200;x++) {
|
||||
for (int z = -200; z <= 200; z++) {
|
||||
for (int y = -3; y <= 3; y++) {
|
||||
this.renderGen.enqueueTask(0, x, y, z);
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@ package me.cortex.voxy.client.core.rendering.building;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
||||
import me.cortex.voxy.client.core.model.IdNotYetComputedException;
|
||||
import me.cortex.voxy.client.core.model.ModelFactory;
|
||||
import me.cortex.voxy.client.core.model.OffThreadModelBakerySystem;
|
||||
import me.cortex.voxy.client.core.model.OnThreadModelBakerySystem;
|
||||
import me.cortex.voxy.common.world.WorldEngine;
|
||||
import me.cortex.voxy.common.world.WorldSection;
|
||||
@@ -12,7 +10,6 @@ import me.cortex.voxy.common.world.other.Mapper;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.function.Consumer;
|
||||
@@ -43,6 +40,7 @@ public class RenderGenerationService {
|
||||
this.workers = new Thread[workers];
|
||||
for (int i = 0; i < workers; i++) {
|
||||
this.workers[i] = new Thread(this::renderWorker);
|
||||
this.workers[i].setPriority(3);
|
||||
this.workers[i].setDaemon(true);
|
||||
this.workers[i].setName("Render generation service #" + i);
|
||||
this.workers[i].start();
|
||||
@@ -89,7 +87,7 @@ public class RenderGenerationService {
|
||||
} catch (IdNotYetComputedException e) {
|
||||
if (task.hasDoneModelRequest[0]) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user