Always the first thing to fall apart

- Fix crumbling on indirect
This commit is contained in:
Jozufozu 2024-11-08 16:10:44 -08:00
parent eae1d0ef94
commit 68453d8349
4 changed files with 30 additions and 10 deletions

View File

@ -8,6 +8,8 @@ import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import org.jetbrains.annotations.Nullable;
import com.mojang.datafixers.util.Pair; import com.mojang.datafixers.util.Pair;
import dev.engine_room.flywheel.api.RenderContext; import dev.engine_room.flywheel.api.RenderContext;
@ -106,7 +108,13 @@ public abstract class DrawManager<N extends AbstractInstancer<?>> {
return false; return false;
} }
protected static <I extends AbstractInstancer<?>> Map<GroupKey<?>, Int2ObjectMap<List<Pair<I, InstanceHandleImpl<?>>>>> doCrumblingSort(Class<I> clazz, List<Engine.CrumblingBlock> crumblingBlocks) { @FunctionalInterface
protected interface State2Instancer<I extends AbstractInstancer<?>> {
// I tried using a plain Function<State<?>, I> here, but it exploded with type errors.
@Nullable I apply(InstanceHandleImpl.State<?> state);
}
protected static <I extends AbstractInstancer<?>> Map<GroupKey<?>, Int2ObjectMap<List<Pair<I, InstanceHandleImpl<?>>>>> doCrumblingSort(List<Engine.CrumblingBlock> crumblingBlocks, State2Instancer<I> cast) {
Map<GroupKey<?>, Int2ObjectMap<List<Pair<I, InstanceHandleImpl<?>>>>> byType = new HashMap<>(); Map<GroupKey<?>, Int2ObjectMap<List<Pair<I, InstanceHandleImpl<?>>>>> byType = new HashMap<>();
for (Engine.CrumblingBlock block : crumblingBlocks) { for (Engine.CrumblingBlock block : crumblingBlocks) {
int progress = block.progress(); int progress = block.progress();
@ -123,16 +131,12 @@ public abstract class DrawManager<N extends AbstractInstancer<?>> {
continue; continue;
} }
InstanceHandleImpl.State<?> abstractInstancer = impl.state; var instancer = cast.apply(impl.state);
// AbstractInstancer directly implement HandleState, so this check is valid.
if (!clazz.isInstance(abstractInstancer)) { if (instancer == null) {
// This rejects instances that were created by a different engine,
// and also instances that are hidden or deleted.
continue; continue;
} }
var instancer = clazz.cast(abstractInstancer);
byType.computeIfAbsent(new GroupKey<>(instancer.type, instancer.environment), $ -> new Int2ObjectArrayMap<>()) byType.computeIfAbsent(new GroupKey<>(instancer.type, instancer.environment), $ -> new Int2ObjectArrayMap<>())
.computeIfAbsent(progress, $ -> new ArrayList<>()) .computeIfAbsent(progress, $ -> new ArrayList<>())
.add(Pair.of(instancer, impl)); .add(Pair.of(instancer, impl));

View File

@ -189,7 +189,7 @@ public class IndirectDrawManager extends DrawManager<IndirectInstancer<?>> {
} }
public void renderCrumbling(List<Engine.CrumblingBlock> crumblingBlocks) { public void renderCrumbling(List<Engine.CrumblingBlock> crumblingBlocks) {
var byType = doCrumblingSort(IndirectInstancer.class, crumblingBlocks); var byType = doCrumblingSort(crumblingBlocks, IndirectInstancer::fromState);
if (byType.isEmpty()) { if (byType.isEmpty()) {
return; return;

View File

@ -74,6 +74,14 @@ public class IndirectInstancer<I extends Instance> extends AbstractInstancer<I>
return new InstanceHandleImpl[ObjectStorage.PAGE_SIZE]; return new InstanceHandleImpl[ObjectStorage.PAGE_SIZE];
} }
@Nullable
public static IndirectInstancer<?> fromState(InstanceHandleImpl.State<?> handle) {
if (handle instanceof InstancePage<?> instancer) {
return instancer.parent;
}
return null;
}
private static final class InstancePage<I extends Instance> implements InstanceHandleImpl.State<I> { private static final class InstancePage<I extends Instance> implements InstanceHandleImpl.State<I> {
private final IndirectInstancer<I> parent; private final IndirectInstancer<I> parent;
private final int pageNo; private final int pageNo;

View File

@ -147,7 +147,15 @@ public class InstancedDrawManager extends DrawManager<InstancedInstancer<?>> {
@Override @Override
public void renderCrumbling(List<Engine.CrumblingBlock> crumblingBlocks) { public void renderCrumbling(List<Engine.CrumblingBlock> crumblingBlocks) {
// Sort draw calls into buckets, so we don't have to do as many shader binds. // Sort draw calls into buckets, so we don't have to do as many shader binds.
var byType = doCrumblingSort(InstancedInstancer.class, crumblingBlocks); var byType = doCrumblingSort(crumblingBlocks, handle -> {
// AbstractInstancer directly implement HandleState, so this check is valid.
if (handle instanceof InstancedInstancer<?> instancer) {
return instancer;
}
// This rejects instances that were created by a different engine,
// and also instances that are hidden or deleted.
return null;
});
if (byType.isEmpty()) { if (byType.isEmpty()) {
return; return;