mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-03-03 14:14:39 +01:00
Merge branch '1.20.1/dev' into 1.21.1/dev
This commit is contained in:
commit
f4123add3a
8 changed files with 112 additions and 111 deletions
|
@ -15,7 +15,6 @@ import dev.engine_room.flywheel.api.task.Plan;
|
|||
import dev.engine_room.flywheel.api.visualization.VisualEmbedding;
|
||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||
import dev.engine_room.flywheel.backend.FlwBackend;
|
||||
import dev.engine_room.flywheel.backend.compile.core.ShaderException;
|
||||
import dev.engine_room.flywheel.backend.engine.embed.EmbeddedEnvironment;
|
||||
import dev.engine_room.flywheel.backend.engine.embed.Environment;
|
||||
import dev.engine_room.flywheel.backend.engine.embed.EnvironmentStorage;
|
||||
|
@ -96,7 +95,7 @@ public class EngineImpl implements Engine {
|
|||
Uniforms.update(context);
|
||||
environmentStorage.flush();
|
||||
drawManager.render(lightStorage, environmentStorage);
|
||||
} catch (ShaderException e) {
|
||||
} catch (Exception e) {
|
||||
FlwBackend.LOGGER.error("Falling back", e);
|
||||
triggerFallback();
|
||||
}
|
||||
|
@ -106,7 +105,7 @@ public class EngineImpl implements Engine {
|
|||
public void renderCrumbling(RenderContext context, List<CrumblingBlock> crumblingBlocks) {
|
||||
try (var state = GlStateTracker.getRestoreState()) {
|
||||
drawManager.renderCrumbling(crumblingBlocks);
|
||||
} catch (ShaderException e) {
|
||||
} catch (Exception e) {
|
||||
FlwBackend.LOGGER.error("Falling back", e);
|
||||
triggerFallback();
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import dev.engine_room.flywheel.api.task.Plan;
|
|||
import dev.engine_room.flywheel.api.visual.DynamicVisual;
|
||||
import dev.engine_room.flywheel.api.visual.TickableVisual;
|
||||
import dev.engine_room.flywheel.api.visualization.VisualManager;
|
||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||
import dev.engine_room.flywheel.impl.visualization.storage.Storage;
|
||||
import dev.engine_room.flywheel.impl.visualization.storage.Transaction;
|
||||
import dev.engine_room.flywheel.lib.task.SimplePlan;
|
||||
|
@ -54,21 +55,25 @@ public class VisualManagerImpl<T, S extends Storage<T>> implements VisualManager
|
|||
queue.add(Transaction.update(obj));
|
||||
}
|
||||
|
||||
public void processQueue(float partialTick) {
|
||||
public void processQueue(VisualizationContext visualizationContext, float partialTick) {
|
||||
var storage = getStorage();
|
||||
Transaction<T> transaction;
|
||||
while ((transaction = queue.poll()) != null) {
|
||||
transaction.apply(storage, partialTick);
|
||||
switch (transaction.action()) {
|
||||
case ADD -> storage.add(visualizationContext, transaction.obj(), partialTick);
|
||||
case REMOVE -> storage.remove(transaction.obj());
|
||||
case UPDATE -> storage.update(transaction.obj(), partialTick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Plan<DynamicVisual.Context> framePlan() {
|
||||
return SimplePlan.<DynamicVisual.Context>of(context -> processQueue(context.partialTick()))
|
||||
public Plan<DynamicVisual.Context> framePlan(VisualizationContext visualizationContext) {
|
||||
return SimplePlan.<DynamicVisual.Context>of(context -> processQueue(visualizationContext, context.partialTick()))
|
||||
.then(storage.framePlan());
|
||||
}
|
||||
|
||||
public Plan<TickableVisual.Context> tickPlan() {
|
||||
return SimplePlan.<TickableVisual.Context>of(context -> processQueue(1))
|
||||
public Plan<TickableVisual.Context> tickPlan(VisualizationContext visualizationContext) {
|
||||
return SimplePlan.<TickableVisual.Context>of(context -> processQueue(visualizationContext, 1))
|
||||
.then(storage.tickPlan());
|
||||
}
|
||||
|
||||
|
|
|
@ -59,9 +59,15 @@ public class VisualizationManagerImpl implements VisualizationManager {
|
|||
private static final LevelAttached<VisualizationManagerImpl> MANAGERS = new LevelAttached<>(VisualizationManagerImpl::new, VisualizationManagerImpl::delete);
|
||||
|
||||
private final TaskExecutorImpl taskExecutor;
|
||||
private final Engine engine;
|
||||
private final DistanceUpdateLimiterImpl frameLimiter;
|
||||
private final RenderDispatcherImpl renderDispatcher = new RenderDispatcherImpl();
|
||||
private final LevelAccessor level;
|
||||
|
||||
// VisualizationManagerImpl can (and should!) be constructed off of the main thread, but it may be
|
||||
// difficult for engines to avoid OpenGL calls which would not be safe. Shove all the init logic
|
||||
// that depends on engine construction into here, and defer until we get invoked on the main thread.
|
||||
@Nullable
|
||||
private LateInit lateInit;
|
||||
|
||||
private final VisualManagerImpl<BlockEntity, BlockEntityStorage> blockEntities;
|
||||
private final VisualManagerImpl<Entity, EntityStorage> entities;
|
||||
|
@ -70,49 +76,14 @@ public class VisualizationManagerImpl implements VisualizationManager {
|
|||
private final Flag frameFlag = new Flag("frame");
|
||||
private final Flag tickFlag = new Flag("tick");
|
||||
|
||||
private final Plan<RenderContext> framePlan;
|
||||
private final Plan<TickableVisual.Context> tickPlan;
|
||||
|
||||
private VisualizationManagerImpl(LevelAccessor level) {
|
||||
this.level = level;
|
||||
taskExecutor = FlwTaskExecutor.get();
|
||||
engine = BackendManager.currentBackend()
|
||||
.createEngine(level);
|
||||
frameLimiter = createUpdateLimiter();
|
||||
|
||||
var visualizationContext = engine.createVisualizationContext();
|
||||
var blockEntitiesStorage = new BlockEntityStorage(visualizationContext);
|
||||
var entitiesStorage = new EntityStorage(visualizationContext);
|
||||
var effectsStorage = new EffectStorage(visualizationContext);
|
||||
|
||||
blockEntities = new VisualManagerImpl<>(blockEntitiesStorage);
|
||||
entities = new VisualManagerImpl<>(entitiesStorage);
|
||||
effects = new VisualManagerImpl<>(effectsStorage);
|
||||
|
||||
var recreate = SimplePlan.<RenderContext>of(context -> blockEntitiesStorage.recreateAll(context.partialTick()),
|
||||
context -> entitiesStorage.recreateAll(context.partialTick()),
|
||||
context -> effectsStorage.recreateAll(context.partialTick()));
|
||||
|
||||
var update = MapContextPlan.map(this::createVisualFrameContext)
|
||||
.to(NestedPlan.of(blockEntities.framePlan(), entities.framePlan(), effects.framePlan()));
|
||||
|
||||
framePlan = IfElsePlan.on((RenderContext ctx) -> engine.updateRenderOrigin(ctx.camera()))
|
||||
.ifTrue(recreate)
|
||||
.ifFalse(update)
|
||||
.plan()
|
||||
.then(SimplePlan.of(() -> {
|
||||
if (blockEntities.areGpuLightSectionsDirty() || entities.areGpuLightSectionsDirty() || effects.areGpuLightSectionsDirty()) {
|
||||
var out = new LongOpenHashSet();
|
||||
out.addAll(blockEntities.gpuLightSections());
|
||||
out.addAll(entities.gpuLightSections());
|
||||
out.addAll(effects.gpuLightSections());
|
||||
engine.lightSections(out);
|
||||
}
|
||||
}))
|
||||
.then(engine.createFramePlan())
|
||||
.then(RaisePlan.raise(frameFlag));
|
||||
|
||||
tickPlan = NestedPlan.of(blockEntities.tickPlan(), entities.tickPlan(), effects.tickPlan())
|
||||
.then(RaisePlan.raise(tickFlag));
|
||||
blockEntities = new VisualManagerImpl<>(new BlockEntityStorage());
|
||||
entities = new VisualManagerImpl<>(new EntityStorage());
|
||||
effects = new VisualManagerImpl<>(new EffectStorage());
|
||||
|
||||
if (level instanceof Level l) {
|
||||
LevelExtension.getAllLoadedEntities(l)
|
||||
|
@ -120,16 +91,65 @@ public class VisualizationManagerImpl implements VisualizationManager {
|
|||
}
|
||||
}
|
||||
|
||||
private DynamicVisual.Context createVisualFrameContext(RenderContext ctx) {
|
||||
Vec3i renderOrigin = engine.renderOrigin();
|
||||
var cameraPos = ctx.camera()
|
||||
.getPosition();
|
||||
private class LateInit {
|
||||
private final Engine engine;
|
||||
|
||||
Matrix4f viewProjection = new Matrix4f(ctx.viewProjection());
|
||||
viewProjection.translate((float) (renderOrigin.getX() - cameraPos.x), (float) (renderOrigin.getY() - cameraPos.y), (float) (renderOrigin.getZ() - cameraPos.z));
|
||||
FrustumIntersection frustum = new FrustumIntersection(viewProjection);
|
||||
private final Plan<RenderContext> framePlan;
|
||||
private final Plan<TickableVisual.Context> tickPlan;
|
||||
|
||||
return new DynamicVisualContextImpl(ctx.camera(), frustum, ctx.partialTick(), frameLimiter);
|
||||
private LateInit(LevelAccessor level) {
|
||||
engine = BackendManager.currentBackend()
|
||||
.createEngine(level);
|
||||
|
||||
var visualizationContext = engine.createVisualizationContext();
|
||||
|
||||
var recreate = SimplePlan.<RenderContext>of(context -> blockEntities.getStorage()
|
||||
.recreateAll(visualizationContext, context.partialTick()), context -> entities.getStorage()
|
||||
.recreateAll(visualizationContext, context.partialTick()), context -> effects.getStorage()
|
||||
.recreateAll(visualizationContext, context.partialTick()));
|
||||
|
||||
var update = MapContextPlan.map(this::createVisualFrameContext)
|
||||
.to(NestedPlan.of(blockEntities.framePlan(visualizationContext), entities.framePlan(visualizationContext), effects.framePlan(visualizationContext)));
|
||||
|
||||
framePlan = IfElsePlan.on((RenderContext ctx) -> engine.updateRenderOrigin(ctx.camera()))
|
||||
.ifTrue(recreate)
|
||||
.ifFalse(update)
|
||||
.plan()
|
||||
.then(SimplePlan.of(() -> {
|
||||
if (blockEntities.areGpuLightSectionsDirty() || entities.areGpuLightSectionsDirty() || effects.areGpuLightSectionsDirty()) {
|
||||
var out = new LongOpenHashSet();
|
||||
out.addAll(blockEntities.gpuLightSections());
|
||||
out.addAll(entities.gpuLightSections());
|
||||
out.addAll(effects.gpuLightSections());
|
||||
engine.lightSections(out);
|
||||
}
|
||||
}))
|
||||
.then(engine.createFramePlan())
|
||||
.then(RaisePlan.raise(frameFlag));
|
||||
|
||||
tickPlan = NestedPlan.of(blockEntities.tickPlan(visualizationContext), entities.tickPlan(visualizationContext), effects.tickPlan(visualizationContext))
|
||||
.then(RaisePlan.raise(tickFlag));
|
||||
}
|
||||
|
||||
private DynamicVisual.Context createVisualFrameContext(RenderContext ctx) {
|
||||
Vec3i renderOrigin = engine.renderOrigin();
|
||||
var cameraPos = ctx.camera()
|
||||
.getPosition();
|
||||
|
||||
Matrix4f viewProjection = new Matrix4f(ctx.viewProjection());
|
||||
viewProjection.translate((float) (renderOrigin.getX() - cameraPos.x), (float) (renderOrigin.getY() - cameraPos.y), (float) (renderOrigin.getZ() - cameraPos.z));
|
||||
FrustumIntersection frustum = new FrustumIntersection(viewProjection);
|
||||
|
||||
return new DynamicVisualContextImpl(ctx.camera(), frustum, ctx.partialTick(), frameLimiter);
|
||||
}
|
||||
}
|
||||
|
||||
private LateInit lateInit() {
|
||||
if (lateInit == null) {
|
||||
lateInit = new LateInit(level);
|
||||
}
|
||||
|
||||
return lateInit;
|
||||
}
|
||||
|
||||
private DistanceUpdateLimiterImpl createUpdateLimiter() {
|
||||
|
@ -191,7 +211,11 @@ public class VisualizationManagerImpl implements VisualizationManager {
|
|||
|
||||
@Override
|
||||
public Vec3i renderOrigin() {
|
||||
return engine.renderOrigin();
|
||||
if (lateInit == null) {
|
||||
return Vec3i.ZERO;
|
||||
} else {
|
||||
return lateInit.engine.renderOrigin();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -225,7 +249,7 @@ public class VisualizationManagerImpl implements VisualizationManager {
|
|||
taskExecutor.syncUntil(tickFlag::isRaised);
|
||||
tickFlag.lower();
|
||||
|
||||
tickPlan.execute(taskExecutor, TickableVisualContextImpl.INSTANCE);
|
||||
lateInit().tickPlan.execute(taskExecutor, TickableVisualContextImpl.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -240,7 +264,7 @@ public class VisualizationManagerImpl implements VisualizationManager {
|
|||
|
||||
frameLimiter.tick();
|
||||
|
||||
framePlan.execute(taskExecutor, context);
|
||||
lateInit().framePlan.execute(taskExecutor, context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -248,7 +272,7 @@ public class VisualizationManagerImpl implements VisualizationManager {
|
|||
*/
|
||||
private void render(RenderContext context) {
|
||||
taskExecutor.syncUntil(frameFlag::isRaised);
|
||||
engine.render(context);
|
||||
lateInit().engine.render(context);
|
||||
}
|
||||
|
||||
private void renderCrumbling(RenderContext context, Long2ObjectMap<SortedSet<BlockDestructionProgress>> destructionProgress) {
|
||||
|
@ -292,12 +316,12 @@ public class VisualizationManagerImpl implements VisualizationManager {
|
|||
}
|
||||
|
||||
if (!crumblingBlocks.isEmpty()) {
|
||||
engine.renderCrumbling(context, crumblingBlocks);
|
||||
lateInit().engine.renderCrumbling(context, crumblingBlocks);
|
||||
}
|
||||
}
|
||||
|
||||
public void onLightUpdate(SectionPos sectionPos, LightLayer layer) {
|
||||
engine.onLightUpdate(sectionPos, layer);
|
||||
lateInit().engine.onLightUpdate(sectionPos, layer);
|
||||
long longPos = sectionPos.asLong();
|
||||
blockEntities.onLightUpdate(longPos);
|
||||
entities.onLightUpdate(longPos);
|
||||
|
@ -315,7 +339,9 @@ public class VisualizationManagerImpl implements VisualizationManager {
|
|||
blockEntities.invalidate();
|
||||
entities.invalidate();
|
||||
effects.invalidate();
|
||||
engine.delete();
|
||||
if (lateInit != null) {
|
||||
lateInit.engine.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private class RenderDispatcherImpl implements RenderDispatcher {
|
||||
|
@ -335,6 +361,7 @@ public class VisualizationManagerImpl implements VisualizationManager {
|
|||
}
|
||||
}
|
||||
|
||||
private record CrumblingBlockImpl(BlockPos pos, int progress, List<Instance> instances) implements Engine.CrumblingBlock {
|
||||
private record CrumblingBlockImpl(BlockPos pos, int progress,
|
||||
List<Instance> instances) implements dev.engine_room.flywheel.api.backend.Engine.CrumblingBlock {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,10 +15,6 @@ import net.minecraft.world.level.block.entity.BlockEntity;
|
|||
public class BlockEntityStorage extends Storage<BlockEntity> {
|
||||
private final Long2ObjectMap<BlockEntityVisual<?>> posLookup = new Long2ObjectOpenHashMap<>();
|
||||
|
||||
public BlockEntityStorage(VisualizationContext visualizationContext) {
|
||||
super(visualizationContext);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BlockEntityVisual<?> visualAtPos(long pos) {
|
||||
return posLookup.get(pos);
|
||||
|
@ -50,7 +46,7 @@ public class BlockEntityStorage extends Storage<BlockEntity> {
|
|||
|
||||
@Override
|
||||
@Nullable
|
||||
protected BlockEntityVisual<?> createRaw(BlockEntity obj, float partialTick) {
|
||||
protected BlockEntityVisual<?> createRaw(VisualizationContext visualizationContext, BlockEntity obj, float partialTick) {
|
||||
var visualizer = VisualizationHelper.getVisualizer(obj);
|
||||
if (visualizer == null) {
|
||||
return null;
|
||||
|
@ -72,9 +68,9 @@ public class BlockEntityStorage extends Storage<BlockEntity> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void recreateAll(float partialTick) {
|
||||
public void recreateAll(VisualizationContext visualizationContext, float partialTick) {
|
||||
posLookup.clear();
|
||||
super.recreateAll(partialTick);
|
||||
super.recreateAll(visualizationContext, partialTick);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -5,12 +5,8 @@ import dev.engine_room.flywheel.api.visual.EffectVisual;
|
|||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||
|
||||
public class EffectStorage extends Storage<Effect> {
|
||||
public EffectStorage(VisualizationContext visualizationContext) {
|
||||
super(visualizationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EffectVisual<?> createRaw(Effect obj, float partialTick) {
|
||||
protected EffectVisual<?> createRaw(VisualizationContext visualizationContext, Effect obj, float partialTick) {
|
||||
return obj.visualize(visualizationContext, partialTick);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,18 +7,14 @@ import net.minecraft.world.entity.Entity;
|
|||
import net.minecraft.world.level.Level;
|
||||
|
||||
public class EntityStorage extends Storage<Entity> {
|
||||
public EntityStorage(VisualizationContext visualizationContext) {
|
||||
super(visualizationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EntityVisual<?> createRaw(Entity obj, float partialTick) {
|
||||
protected EntityVisual<?> createRaw(VisualizationContext context, Entity obj, float partialTick) {
|
||||
var visualizer = VisualizationHelper.getVisualizer(obj);
|
||||
if (visualizer == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return visualizer.createVisual(visualizationContext, obj, partialTick);
|
||||
return visualizer.createVisual(context, obj, partialTick);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -25,8 +25,6 @@ import dev.engine_room.flywheel.lib.visual.SimpleTickableVisual;
|
|||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
|
||||
|
||||
public abstract class Storage<T> {
|
||||
protected final VisualizationContext visualizationContext;
|
||||
|
||||
private final Map<T, Visual> visuals = new Reference2ObjectOpenHashMap<>();
|
||||
protected final PlanMap<DynamicVisual, DynamicVisual.Context> dynamicVisuals = new PlanMap<>();
|
||||
protected final PlanMap<TickableVisual, TickableVisual.Context> tickableVisuals = new PlanMap<>();
|
||||
|
@ -35,10 +33,6 @@ public abstract class Storage<T> {
|
|||
protected final LightUpdatedVisualStorage lightUpdatedVisuals = new LightUpdatedVisualStorage();
|
||||
protected final ShaderLightVisualStorage shaderLightVisuals = new ShaderLightVisualStorage();
|
||||
|
||||
public Storage(VisualizationContext visualizationContext) {
|
||||
this.visualizationContext = visualizationContext;
|
||||
}
|
||||
|
||||
public Collection<Visual> getAllVisuals() {
|
||||
return visuals.values();
|
||||
}
|
||||
|
@ -71,11 +65,16 @@ public abstract class Storage<T> {
|
|||
*/
|
||||
public abstract boolean willAccept(T obj);
|
||||
|
||||
public void add(T obj, float partialTick) {
|
||||
public void add(VisualizationContext visualizationContext, T obj, float partialTick) {
|
||||
Visual visual = visuals.get(obj);
|
||||
|
||||
if (visual == null) {
|
||||
create(obj, partialTick);
|
||||
visual = createRaw(visualizationContext, obj, partialTick);
|
||||
|
||||
if (visual != null) {
|
||||
setup(visual, partialTick);
|
||||
visuals.put(obj, visual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,7 +119,7 @@ public abstract class Storage<T> {
|
|||
visual.update(partialTick);
|
||||
}
|
||||
|
||||
public void recreateAll(float partialTick) {
|
||||
public void recreateAll(VisualizationContext visualizationContext, float partialTick) {
|
||||
dynamicVisuals.clear();
|
||||
tickableVisuals.clear();
|
||||
simpleDynamicVisuals.clear();
|
||||
|
@ -131,7 +130,7 @@ public abstract class Storage<T> {
|
|||
visuals.replaceAll((obj, visual) -> {
|
||||
visual.delete();
|
||||
|
||||
var out = createRaw(obj, partialTick);
|
||||
var out = createRaw(visualizationContext, obj, partialTick);
|
||||
|
||||
if (out != null) {
|
||||
setup(out, partialTick);
|
||||
|
@ -141,17 +140,8 @@ public abstract class Storage<T> {
|
|||
});
|
||||
}
|
||||
|
||||
private void create(T obj, float partialTick) {
|
||||
var visual = createRaw(obj, partialTick);
|
||||
|
||||
if (visual != null) {
|
||||
setup(visual, partialTick);
|
||||
visuals.put(obj, visual);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract Visual createRaw(T obj, float partialTick);
|
||||
protected abstract Visual createRaw(VisualizationContext visualizationContext, T obj, float partialTick);
|
||||
|
||||
private void setup(Visual visual, float partialTick) {
|
||||
if (visual instanceof DynamicVisual dynamic) {
|
||||
|
|
|
@ -12,12 +12,4 @@ public record Transaction<T>(T obj, Action action) {
|
|||
public static <T> Transaction<T> update(T obj) {
|
||||
return new Transaction<>(obj, Action.UPDATE);
|
||||
}
|
||||
|
||||
public void apply(Storage<T> storage, float partialTick) {
|
||||
switch (action) {
|
||||
case ADD -> storage.add(obj, partialTick);
|
||||
case REMOVE -> storage.remove(obj);
|
||||
case UPDATE -> storage.update(obj, partialTick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue