mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-06 04:16:36 +01:00
To delete or not to delete
- Fix AtomicBitset#nextClearBit - Add test for AtomicBitset - Remove unnecessary gl state stuff from IndirectEngine#renderCrumbling. - Fix instance removal on IndirectEngine. - Deleting an instance not at the end of the instancers list would cause an exception to be thrown during upload caused by out-of-bounds indexing. - Fixed by unsetting changed for the tail of the instancers list.
This commit is contained in:
parent
7c0959be9a
commit
948750f296
5 changed files with 67 additions and 34 deletions
|
@ -40,11 +40,6 @@ public abstract class AbstractInstancer<I extends Instance> implements Instancer
|
|||
return instances.size();
|
||||
}
|
||||
|
||||
protected boolean moreThanTwoThirdsChanged() {
|
||||
return (changed.cardinality() * 3) > (instances.size() * 2);
|
||||
}
|
||||
|
||||
|
||||
public void notifyDirty(int index) {
|
||||
if (index < 0 || index >= getInstanceCount()) {
|
||||
return;
|
||||
|
@ -68,21 +63,34 @@ public abstract class AbstractInstancer<I extends Instance> implements Instancer
|
|||
final int oldSize = this.instances.size();
|
||||
int removeCount = deleted.cardinality();
|
||||
|
||||
if (oldSize == removeCount) {
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
|
||||
final int newSize = oldSize - removeCount;
|
||||
|
||||
// shift surviving elements left over the spaces left by removed elements
|
||||
for (int i = 0, j = 0; (i < oldSize) && (j < newSize); i++, j++) {
|
||||
i = deleted.nextClearBit(i);
|
||||
// Punch out the deleted instances, shifting over surviving instances to fill their place.
|
||||
for (int scanPos = 0, writePos = 0; (scanPos < oldSize) && (writePos < newSize); scanPos++, writePos++) {
|
||||
// Find next non-deleted element.
|
||||
scanPos = deleted.nextClearBit(scanPos);
|
||||
|
||||
if (i != j) {
|
||||
var handle = handles.get(i);
|
||||
I instance = instances.get(i);
|
||||
if (scanPos != writePos) {
|
||||
// Grab the old instance/handle from scanPos...
|
||||
var handle = handles.get(scanPos);
|
||||
I instance = instances.get(scanPos);
|
||||
|
||||
handles.set(j, handle);
|
||||
instances.set(j, instance);
|
||||
// ... and move it to writePos.
|
||||
handles.set(writePos, handle);
|
||||
instances.set(writePos, instance);
|
||||
|
||||
handle.index = j;
|
||||
changed.set(j);
|
||||
// Make sure the handle knows it's been moved...
|
||||
handle.index = writePos;
|
||||
// ...and set it changed to force an upload.
|
||||
changed.set(writePos);
|
||||
|
||||
// Clear the old slot. There's nothing meaningful there that can be considered "changed".
|
||||
changed.clear(scanPos);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ public class InstanceHandleImpl implements InstanceHandle {
|
|||
@Override
|
||||
public void setDeleted() {
|
||||
instancer.notifyRemoval(index);
|
||||
// invalidate ourselves
|
||||
clear();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
|
|
|
@ -76,26 +76,9 @@ public class IndirectEngine extends AbstractEngine {
|
|||
executor.syncUntil(flushFlag::isRaised);
|
||||
|
||||
try (var restoreState = GlStateTracker.getRestoreState()) {
|
||||
int prevActiveTexture = GlStateManager._getActiveTexture();
|
||||
Minecraft.getInstance().gameRenderer.overlayTexture()
|
||||
.setupOverlayColor();
|
||||
Minecraft.getInstance().gameRenderer.lightTexture()
|
||||
.turnOnLightLayer();
|
||||
|
||||
GlTextureUnit.T1.makeActive();
|
||||
RenderSystem.bindTexture(RenderSystem.getShaderTexture(1));
|
||||
GlTextureUnit.T2.makeActive();
|
||||
RenderSystem.bindTexture(RenderSystem.getShaderTexture(2));
|
||||
|
||||
drawManager.renderCrumbling(crumblingBlocks);
|
||||
|
||||
MaterialRenderState.reset();
|
||||
|
||||
Minecraft.getInstance().gameRenderer.overlayTexture()
|
||||
.teardownOverlayColor();
|
||||
Minecraft.getInstance().gameRenderer.lightTexture()
|
||||
.turnOffLightLayer();
|
||||
GlStateManager._activeTexture(prevActiveTexture);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -168,13 +168,13 @@ public class AtomicBitset {
|
|||
if (++longPosition > segmentMask) {
|
||||
segmentPosition++;
|
||||
if (segmentPosition >= segments.numSegments()) {
|
||||
return segments.numSegments() << log2SegmentSize;
|
||||
return segments.numSegments() << log2SegmentSize + (longPosition << 6);
|
||||
}
|
||||
segment = segments.getSegment(segmentPosition);
|
||||
longPosition = 0;
|
||||
}
|
||||
|
||||
word = segment.get(longPosition);
|
||||
word = ~segment.get(longPosition);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package com.jozufozu.flywheel.lib.util;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class TestAtomicBitset {
|
||||
|
||||
@Test
|
||||
void testNextClearBit() {
|
||||
var segmentLength = 1 << AtomicBitset.DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS;
|
||||
var bitLength = 2 << AtomicBitset.DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS;
|
||||
var bs = new AtomicBitset(AtomicBitset.DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS, bitLength);
|
||||
|
||||
Assertions.assertEquals(0, bs.nextClearBit(0));
|
||||
Assertions.assertEquals(1, bs.nextClearBit(1));
|
||||
|
||||
Assertions.assertEquals(5000, bs.nextClearBit(5000));
|
||||
|
||||
bs.set(16);
|
||||
|
||||
Assertions.assertEquals(0, bs.nextClearBit(0));
|
||||
Assertions.assertEquals(17, bs.nextClearBit(16));
|
||||
|
||||
bs.set(segmentLength + 1);
|
||||
|
||||
Assertions.assertEquals(0, bs.nextClearBit(0));
|
||||
Assertions.assertEquals(segmentLength + 2, bs.nextClearBit(segmentLength + 1));
|
||||
|
||||
bs.set(bitLength);
|
||||
|
||||
Assertions.assertEquals(0, bs.nextClearBit(0));
|
||||
Assertions.assertEquals(bitLength + 1, bs.nextClearBit(bitLength));
|
||||
|
||||
for (int i = 0; i < bitLength; i++) {
|
||||
bs.set(i);
|
||||
}
|
||||
|
||||
Assertions.assertEquals(bitLength + 1, bs.nextClearBit(0));
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue