mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-07 12:56:31 +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();
|
return instances.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean moreThanTwoThirdsChanged() {
|
|
||||||
return (changed.cardinality() * 3) > (instances.size() * 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void notifyDirty(int index) {
|
public void notifyDirty(int index) {
|
||||||
if (index < 0 || index >= getInstanceCount()) {
|
if (index < 0 || index >= getInstanceCount()) {
|
||||||
return;
|
return;
|
||||||
|
@ -68,21 +63,34 @@ public abstract class AbstractInstancer<I extends Instance> implements Instancer
|
||||||
final int oldSize = this.instances.size();
|
final int oldSize = this.instances.size();
|
||||||
int removeCount = deleted.cardinality();
|
int removeCount = deleted.cardinality();
|
||||||
|
|
||||||
|
if (oldSize == removeCount) {
|
||||||
|
clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final int newSize = oldSize - removeCount;
|
final int newSize = oldSize - removeCount;
|
||||||
|
|
||||||
// shift surviving elements left over the spaces left by removed elements
|
// Punch out the deleted instances, shifting over surviving instances to fill their place.
|
||||||
for (int i = 0, j = 0; (i < oldSize) && (j < newSize); i++, j++) {
|
for (int scanPos = 0, writePos = 0; (scanPos < oldSize) && (writePos < newSize); scanPos++, writePos++) {
|
||||||
i = deleted.nextClearBit(i);
|
// Find next non-deleted element.
|
||||||
|
scanPos = deleted.nextClearBit(scanPos);
|
||||||
|
|
||||||
if (i != j) {
|
if (scanPos != writePos) {
|
||||||
var handle = handles.get(i);
|
// Grab the old instance/handle from scanPos...
|
||||||
I instance = instances.get(i);
|
var handle = handles.get(scanPos);
|
||||||
|
I instance = instances.get(scanPos);
|
||||||
|
|
||||||
handles.set(j, handle);
|
// ... and move it to writePos.
|
||||||
instances.set(j, instance);
|
handles.set(writePos, handle);
|
||||||
|
instances.set(writePos, instance);
|
||||||
|
|
||||||
handle.index = j;
|
// Make sure the handle knows it's been moved...
|
||||||
changed.set(j);
|
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
|
@Override
|
||||||
public void setDeleted() {
|
public void setDeleted() {
|
||||||
instancer.notifyRemoval(index);
|
instancer.notifyRemoval(index);
|
||||||
|
// invalidate ourselves
|
||||||
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
|
|
|
@ -76,26 +76,9 @@ public class IndirectEngine extends AbstractEngine {
|
||||||
executor.syncUntil(flushFlag::isRaised);
|
executor.syncUntil(flushFlag::isRaised);
|
||||||
|
|
||||||
try (var restoreState = GlStateTracker.getRestoreState()) {
|
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);
|
drawManager.renderCrumbling(crumblingBlocks);
|
||||||
|
|
||||||
MaterialRenderState.reset();
|
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) {
|
if (++longPosition > segmentMask) {
|
||||||
segmentPosition++;
|
segmentPosition++;
|
||||||
if (segmentPosition >= segments.numSegments()) {
|
if (segmentPosition >= segments.numSegments()) {
|
||||||
return segments.numSegments() << log2SegmentSize;
|
return segments.numSegments() << log2SegmentSize + (longPosition << 6);
|
||||||
}
|
}
|
||||||
segment = segments.getSegment(segmentPosition);
|
segment = segments.getSegment(segmentPosition);
|
||||||
longPosition = 0;
|
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