Wait a minute

- Add debug flag to disable frame/tick plan execution
- Should help debugging cases where a visual constructor produces a
  visual in an invalid state like the weeping shulker bug
This commit is contained in:
Jozufozu 2024-11-15 18:18:44 -08:00
parent f3845a15fb
commit 3811da166c
7 changed files with 101 additions and 13 deletions

View file

@ -0,0 +1,5 @@
package dev.engine_room.flywheel.backend;
public class BackendDebugFlags {
public static boolean LIGHT_STORAGE_VIEW = false;
}

View file

@ -10,6 +10,7 @@ import dev.engine_room.flywheel.api.visual.Effect;
import dev.engine_room.flywheel.api.visual.EffectVisual;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
import dev.engine_room.flywheel.api.visualization.VisualizationManager;
import dev.engine_room.flywheel.backend.BackendDebugFlags;
import dev.engine_room.flywheel.backend.SkyLightSectionStorageExtension;
import dev.engine_room.flywheel.backend.engine.indirect.StagingBuffer;
import dev.engine_room.flywheel.backend.gl.buffer.GlBuffer;
@ -49,8 +50,6 @@ import net.minecraft.world.level.chunk.DataLayer;
* <p>Thus, each section occupies 5832 bytes.
*/
public class LightStorage implements Effect {
public static boolean DEBUG = false;
public static final int BLOCKS_PER_SECTION = 18 * 18 * 18;
public static final int LIGHT_SIZE_BYTES = BLOCKS_PER_SECTION;
public static final int SOLID_SIZE_BYTES = MoreMath.ceilingDiv(BLOCKS_PER_SECTION, Integer.SIZE) * Integer.BYTES;
@ -108,12 +107,12 @@ public class LightStorage implements Effect {
public <C> Plan<C> createFramePlan() {
return SimplePlan.of(() -> {
if (DEBUG != isDebugOn) {
if (BackendDebugFlags.LIGHT_STORAGE_VIEW != isDebugOn) {
var visualizationManager = VisualizationManager.get(level);
// Really should be non-null, but just in case.
if (visualizationManager != null) {
if (DEBUG) {
if (BackendDebugFlags.LIGHT_STORAGE_VIEW) {
visualizationManager.effects()
.queueAdd(this);
} else {
@ -121,7 +120,7 @@ public class LightStorage implements Effect {
.queueRemove(this);
}
}
isDebugOn = DEBUG;
isDebugOn = BackendDebugFlags.LIGHT_STORAGE_VIEW;
}
if (updatedSections.isEmpty() && requestedSections == null) {

View file

@ -0,0 +1,44 @@
package dev.engine_room.flywheel.lib.task;
import dev.engine_room.flywheel.api.task.Plan;
import dev.engine_room.flywheel.api.task.TaskExecutor;
import dev.engine_room.flywheel.lib.task.functional.BooleanSupplierWithContext;
/**
* Executes one plan or another, depending on a dynamically evaluated condition.
*
* @param condition The condition to branch on.
* @param onTrue The plan to execute if the condition is true.
* @param <C> The type of the context object.
*/
public record ConditionalPlan<C>(BooleanSupplierWithContext<C> condition,
Plan<C> onTrue) implements SimplyComposedPlan<C> {
public static <C> Builder<C> on(BooleanSupplierWithContext<C> condition) {
return new Builder<>(condition);
}
public static <C> Builder<C> on(BooleanSupplierWithContext.Ignored<C> condition) {
return new Builder<>(condition);
}
@Override
public void execute(TaskExecutor taskExecutor, C context, Runnable onCompletion) {
if (condition.getAsBoolean(context)) {
onTrue.execute(taskExecutor, context, onCompletion);
} else {
onCompletion.run();
}
}
public static final class Builder<C> {
private final BooleanSupplierWithContext<C> condition;
public Builder(BooleanSupplierWithContext<C> condition) {
this.condition = condition;
}
public ConditionalPlan<C> then(Plan<C> onTrue) {
return new ConditionalPlan<>(condition, onTrue);
}
}
}

View file

@ -0,0 +1,8 @@
package dev.engine_room.flywheel.impl;
public class ImplDebugFlags {
/**
* Debug flag to globally turn beginFrame/tick off.
*/
public static boolean PAUSE_UPDATES = false;
}

View file

@ -15,6 +15,8 @@ import dev.engine_room.flywheel.api.visual.ShaderLightVisual;
import dev.engine_room.flywheel.api.visual.TickableVisual;
import dev.engine_room.flywheel.api.visual.Visual;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
import dev.engine_room.flywheel.impl.ImplDebugFlags;
import dev.engine_room.flywheel.lib.task.ConditionalPlan;
import dev.engine_room.flywheel.lib.task.ForEachPlan;
import dev.engine_room.flywheel.lib.task.NestedPlan;
import dev.engine_room.flywheel.lib.task.PlanMap;
@ -42,11 +44,16 @@ public abstract class Storage<T> {
}
public Plan<DynamicVisual.Context> framePlan() {
return NestedPlan.of(dynamicVisuals, lightUpdatedVisuals.plan(), ForEachPlan.of(() -> simpleDynamicVisuals, SimpleDynamicVisual::beginFrame));
var update = ConditionalPlan.<DynamicVisual.Context>on(() -> !ImplDebugFlags.PAUSE_UPDATES)
.then(NestedPlan.of(dynamicVisuals, ForEachPlan.of(() -> simpleDynamicVisuals, SimpleDynamicVisual::beginFrame)));
// Do light updates regardless.
return NestedPlan.of(lightUpdatedVisuals.plan(), update);
}
public Plan<TickableVisual.Context> tickPlan() {
return NestedPlan.of(tickableVisuals, ForEachPlan.of(() -> simpleTickableVisuals, SimpleTickableVisual::tick));
return ConditionalPlan.<TickableVisual.Context>on(() -> !ImplDebugFlags.PAUSE_UPDATES)
.then(NestedPlan.of(tickableVisuals, ForEachPlan.of(() -> simpleTickableVisuals, SimpleTickableVisual::tick)));
}
public LightUpdatedVisualStorage lightUpdatedVisuals() {

View file

@ -8,9 +8,9 @@ import com.mojang.brigadier.context.CommandContext;
import dev.engine_room.flywheel.api.backend.Backend;
import dev.engine_room.flywheel.api.backend.BackendManager;
import dev.engine_room.flywheel.backend.BackendDebugFlags;
import dev.engine_room.flywheel.backend.compile.LightSmoothness;
import dev.engine_room.flywheel.backend.compile.PipelineCompiler;
import dev.engine_room.flywheel.backend.engine.LightStorage;
import dev.engine_room.flywheel.backend.engine.uniform.DebugMode;
import dev.engine_room.flywheel.backend.engine.uniform.FrameUniforms;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
@ -179,12 +179,24 @@ public final class FlwCommands {
debug.then(ClientCommandManager.literal("lightSections")
.then(ClientCommandManager.literal("on")
.executes(context -> {
LightStorage.DEBUG = true;
BackendDebugFlags.LIGHT_STORAGE_VIEW = true;
return Command.SINGLE_SUCCESS;
}))
.then(ClientCommandManager.literal("off")
.executes(context -> {
LightStorage.DEBUG = false;
BackendDebugFlags.LIGHT_STORAGE_VIEW = false;
return Command.SINGLE_SUCCESS;
})));
debug.then(ClientCommandManager.literal("pauseUpdates")
.then(ClientCommandManager.literal("on")
.executes(context -> {
ImplDebugFlags.PAUSE_UPDATES = true;
return Command.SINGLE_SUCCESS;
}))
.then(ClientCommandManager.literal("off")
.executes(context -> {
ImplDebugFlags.PAUSE_UPDATES = false;
return Command.SINGLE_SUCCESS;
})));

View file

@ -6,9 +6,9 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import dev.engine_room.flywheel.api.backend.Backend;
import dev.engine_room.flywheel.api.backend.BackendManager;
import dev.engine_room.flywheel.backend.BackendDebugFlags;
import dev.engine_room.flywheel.backend.compile.LightSmoothness;
import dev.engine_room.flywheel.backend.compile.PipelineCompiler;
import dev.engine_room.flywheel.backend.engine.LightStorage;
import dev.engine_room.flywheel.backend.engine.uniform.DebugMode;
import dev.engine_room.flywheel.backend.engine.uniform.FrameUniforms;
import net.minecraft.client.Minecraft;
@ -172,14 +172,27 @@ public final class FlwCommands {
debug.then(Commands.literal("lightSections")
.then(Commands.literal("on")
.executes(context -> {
LightStorage.DEBUG = true;
BackendDebugFlags.LIGHT_STORAGE_VIEW = true;
return Command.SINGLE_SUCCESS;
}))
.then(Commands.literal("off")
.executes(context -> {
LightStorage.DEBUG = false;
BackendDebugFlags.LIGHT_STORAGE_VIEW = false;
return Command.SINGLE_SUCCESS;
})));
debug.then(Commands.literal("pauseUpdates")
.then(Commands.literal("on")
.executes(context -> {
ImplDebugFlags.PAUSE_UPDATES = true;
return Command.SINGLE_SUCCESS;
}))
.then(Commands.literal("off")
.executes(context -> {
ImplDebugFlags.PAUSE_UPDATES = false;
return Command.SINGLE_SUCCESS;
})));
return debug;
}