Skip to content

Commit

Permalink
More API improvements
Browse files Browse the repository at this point in the history
- Add Engine#onLightUpdate; remove LightUpdateHolder and backend/ClientChunkCacheMixin
- Add Effect#level
- Add VisualizationHelper#queueAdd and #queueRemove for Effects
- Fix PartialModel not assigning bakedModel field when populating on init
- Fix PartialModel.ALL using weak keys instead of weak values
- Make Simple*Visualizer and corresponding inner Builder classes final
- Restore FlatLit#light overload that accepts block and sky light values separately
- Add AbstractBlockEntityVisual#relight overloads that accept Iterator and Iterable
- Reorganize classes in impl.vizualization
  • Loading branch information
PepperCode1 committed Jul 22, 2024
1 parent 74b2fc0 commit 3cc2c82
Show file tree
Hide file tree
Showing 30 changed files with 169 additions and 177 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.client.Camera;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.core.Vec3i;
import net.minecraft.world.level.LightLayer;

@BackendImplemented
public interface Engine {
Expand All @@ -32,23 +34,9 @@ public interface Engine {
Plan<RenderContext> createFramePlan();

/**
* Render all instances necessary for the given visual type.
* @param executor The task executor running the frame plan.
* @param context The render context for this frame.
* @param visualType The type of visual.
*/
void render(TaskExecutor executor, RenderContext context, VisualType visualType);

/**
* Render the given instances as a crumbling overlay.
* <br>
* This is guaranteed to be called between the first and last calls to {@link #render} for the current frame.
*
* @param executor The task executor running the frame plan.
* @param context The render context for this frame.
* @param crumblingBlocks The instances to render. This list is never empty.
* @return The current render origin.
*/
void renderCrumbling(TaskExecutor executor, RenderContext context, List<CrumblingBlock> crumblingBlocks);
Vec3i renderOrigin();

/**
* Maintain the render origin to be within a certain distance from the camera in all directions,
Expand All @@ -58,11 +46,6 @@ public interface Engine {
*/
boolean updateRenderOrigin(Camera camera);

/**
* @return The current render origin.
*/
Vec3i renderOrigin();

/**
* Assign the set of sections that visuals have requested GPU light for.
*
Expand All @@ -72,6 +55,27 @@ public interface Engine {
*/
void lightSections(LongSet sections);

void onLightUpdate(SectionPos sectionPos, LightLayer layer);

/**
* Render all instances necessary for the given visual type.
* @param executor The task executor running the frame plan.
* @param context The render context for this frame.
* @param visualType The type of visual.
*/
void render(TaskExecutor executor, RenderContext context, VisualType visualType);

/**
* Render the given instances as a crumbling overlay.
* <br>
* This is guaranteed to be called between the first and last calls to {@link #render} for the current frame.
*
* @param executor The task executor running the frame plan.
* @param context The render context for this frame.
* @param crumblingBlocks The instances to render. This list is never empty.
*/
void renderCrumbling(TaskExecutor executor, RenderContext context, List<CrumblingBlock> crumblingBlocks);

/**
* Free all resources associated with this engine.
* <br>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package dev.engine_room.flywheel.api.visual;

import dev.engine_room.flywheel.api.visualization.VisualizationContext;
import net.minecraft.world.level.LevelAccessor;

/**
* An effect is not attached to any formal game object, but allows you to hook into
* flywheel's systems to render things. They're closely analogous to particles but
* without any built in support for networking.
*/
public interface Effect {
LevelAccessor level();

/**
* Create a visual that will be keyed by this effect object.
*
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.client.Camera;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.core.Vec3i;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.phys.Vec3;

public class EngineImpl implements Engine {
Expand Down Expand Up @@ -56,21 +58,8 @@ public Plan<RenderContext> createFramePlan() {
}

@Override
public void render(TaskExecutor executor, RenderContext context, VisualType visualType) {
executor.syncUntil(flushFlag::isRaised);
if (visualType == VisualType.EFFECT) {
flushFlag.lower();
}

drawManager.render(visualType);
}

@Override
public void renderCrumbling(TaskExecutor executor, RenderContext context, List<CrumblingBlock> crumblingBlocks) {
// Need to wait for flush before we can inspect instancer state.
executor.syncUntil(flushFlag::isRaised);

drawManager.renderCrumbling(crumblingBlocks);
public Vec3i renderOrigin() {
return renderOrigin;
}

@Override
Expand All @@ -91,13 +80,31 @@ public boolean updateRenderOrigin(Camera camera) {
}

@Override
public Vec3i renderOrigin() {
return renderOrigin;
public void lightSections(LongSet sections) {
lightStorage.sections(sections);
}

@Override
public void lightSections(LongSet sections) {
lightStorage.sections(sections);
public void onLightUpdate(SectionPos sectionPos, LightLayer layer) {
lightStorage.onLightUpdate(sectionPos.asLong());
}

@Override
public void render(TaskExecutor executor, RenderContext context, VisualType visualType) {
executor.syncUntil(flushFlag::isRaised);
if (visualType == VisualType.EFFECT) {
flushFlag.lower();
}

drawManager.render(visualType);
}

@Override
public void renderCrumbling(TaskExecutor executor, RenderContext context, List<CrumblingBlock> crumblingBlocks) {
// Need to wait for flush before we can inspect instancer state.
executor.syncUntil(flushFlag::isRaised);

drawManager.renderCrumbling(crumblingBlocks);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@

import dev.engine_room.flywheel.api.RenderContext;
import dev.engine_room.flywheel.api.task.Plan;
import dev.engine_room.flywheel.backend.LightUpdateHolder;
import dev.engine_room.flywheel.backend.engine.indirect.StagingBuffer;
import dev.engine_room.flywheel.backend.gl.buffer.GlBuffer;
import dev.engine_room.flywheel.lib.task.SimplePlan;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.longs.Long2IntMap;
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongArraySet;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
Expand Down Expand Up @@ -53,6 +52,7 @@ public class LightStorage {
private final BitSet changed = new BitSet();
private boolean needsLutRebuild = false;

private final LongSet updatedSections = new LongOpenHashSet();
@Nullable
private LongSet requestedSections;

Expand All @@ -72,11 +72,12 @@ public void sections(LongSet sections) {
requestedSections = sections;
}

public void onLightUpdate(long section) {
updatedSections.add(section);
}

public Plan<RenderContext> createFramePlan() {
return SimplePlan.of(() -> {
var updatedSections = LightUpdateHolder.get(level)
.getAndClearUpdatedSections();

if (updatedSections.isEmpty() && requestedSections == null) {
return;
}
Expand All @@ -87,15 +88,15 @@ public Plan<RenderContext> createFramePlan() {
LongSet sectionsToCollect;
if (requestedSections == null) {
// If none were requested, then we need to collect all sections that received updates.
sectionsToCollect = new LongArraySet();
sectionsToCollect = new LongOpenHashSet();
} else {
// If we did receive a new set of requested sections, we only
// need to collect the sections that weren't yet tracked.
sectionsToCollect = requestedSections;
sectionsToCollect = new LongOpenHashSet(requestedSections);
sectionsToCollect.removeAll(section2ArenaIndex.keySet());
}

// updatedSections contains all sections than received light updates,
// updatedSections contains all sections that received light updates,
// but we only care about its intersection with our tracked sections.
for (long updatedSection : updatedSections) {
// Since sections contain the border light of their neighbors, we need to collect the neighbors as well.
Expand All @@ -115,6 +116,7 @@ public Plan<RenderContext> createFramePlan() {
// TODO: Should this be done in parallel?
sectionsToCollect.forEach(this::collectSection);

updatedSections.clear();
requestedSections = null;
});
}
Expand All @@ -130,7 +132,7 @@ private void removeUnusedSections() {
var entry = it.next();
var section = entry.getLongKey();

if (!this.requestedSections.contains(section)) {
if (!requestedSections.contains(section)) {
arena.free(entry.getIntValue());
needsLutRebuild = true;
it.remove();
Expand Down

This file was deleted.

1 change: 0 additions & 1 deletion common/src/backend/resources/flywheel.backend.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"refmap": "backend-flywheel.refmap.json",
"client": [
"AbstractClientPlayerAccessor",
"ClientChunkCacheMixin",
"GlStateManagerMixin",
"LevelRendererAccessor",
"OptionsMixin",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,21 @@
public interface FlatLit extends Instance {
/**
* Set the packed light value for this instance.
* @param packedLight Packed block and sky light per {@link LightTexture#pack(int, int)}
* @param packedLight the packed light per {@link LightTexture#pack(int, int)}
* @return {@code this} for chaining
*/
FlatLit light(int packedLight);

/**
* Set the block and sky light values for this instance.
* @param blockLight the block light value
* @param skyLight the sky light value
* @return {@code this} for chaining
*/
default FlatLit light(int blockLight, int skyLight) {
return light(LightTexture.pack(blockLight, skyLight));
}

static void relight(int packedLight, @Nullable FlatLit... instances) {
for (FlatLit instance : instances) {
if (instance != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ public abstract class BlockModelBuilder {
BlockAndTintGetter level;
@Nullable
PoseStack poseStack;
boolean renderFluids = false;
@Nullable
BiFunction<RenderType, Boolean, Material> materialFunc;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package dev.engine_room.flywheel.lib.model.baked;

import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentMap;

import org.jetbrains.annotations.UnknownNullability;

import com.google.common.collect.MapMaker;

import dev.engine_room.flywheel.lib.internal.FlwLibXplat;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.model.BakedModel;
Expand All @@ -17,7 +19,7 @@
* Once Minecraft has finished baking all models, all PartialModels will have their bakedModel fields populated.
*/
public final class PartialModel {
static final WeakHashMap<ResourceLocation, PartialModel> ALL = new WeakHashMap<>();
static final ConcurrentMap<ResourceLocation, PartialModel> ALL = new MapMaker().weakValues().makeMap();
static boolean populateOnInit = false;

private final ResourceLocation modelLocation;
Expand All @@ -28,14 +30,12 @@ private PartialModel(ResourceLocation modelLocation) {
this.modelLocation = modelLocation;

if (populateOnInit) {
FlwLibXplat.INSTANCE.getBakedModel(Minecraft.getInstance().getModelManager(), modelLocation);
bakedModel = FlwLibXplat.INSTANCE.getBakedModel(Minecraft.getInstance().getModelManager(), modelLocation);
}
}

public static PartialModel of(ResourceLocation modelLocation) {
synchronized (ALL) {
return ALL.computeIfAbsent(modelLocation, PartialModel::new);
}
return ALL.computeIfAbsent(modelLocation, PartialModel::new);
}

@UnknownNullability
Expand Down
Loading

0 comments on commit 3cc2c82

Please sign in to comment.