Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.fastasyncworldedit.core.extent.filter;

import com.fastasyncworldedit.core.extent.filter.block.FilterBlock;
import com.fastasyncworldedit.core.internal.simd.VectorFacade;
import com.fastasyncworldedit.core.internal.simd.VectorizedFilter;
import jdk.incubator.vector.ShortVector;
import jdk.incubator.vector.VectorMask;

public class CountFilter extends ForkedFilter<CountFilter> implements VectorizedFilter {
Expand Down Expand Up @@ -37,9 +37,8 @@ public int getTotal() {
}

@Override
public ShortVector applyVector(final ShortVector get, final ShortVector set, VectorMask<Short> mask) {
public void applyVector(final VectorFacade get, final VectorFacade set, final VectorMask<Short> mask) {
total += mask.trueCount();
return set;
}

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.fastasyncworldedit.core.extent.filter;

import com.fastasyncworldedit.core.extent.filter.block.FilterBlock;
import com.fastasyncworldedit.core.internal.simd.VectorFacade;
import com.fastasyncworldedit.core.internal.simd.VectorizedFilter;
import com.fastasyncworldedit.core.queue.Filter;
import com.fastasyncworldedit.core.queue.IChunk;
import com.sk89q.worldedit.regions.Region;
import jdk.incubator.vector.ShortVector;
import jdk.incubator.vector.VectorMask;
import org.jetbrains.annotations.Nullable;

Expand Down Expand Up @@ -78,9 +78,9 @@ public VectorizedLinkedFilter(final L left, final R right) {
}

@Override
public ShortVector applyVector(final ShortVector get, final ShortVector set, VectorMask<Short> mask) {
ShortVector res = getLeft().applyVector(get, set, mask);
return getRight().applyVector(get, res, mask);
public void applyVector(final VectorFacade get, final VectorFacade set, final VectorMask<Short> mask) {
getLeft().applyVector(get, set, mask);
getRight().applyVector(get, set, mask);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fastasyncworldedit.core.extent.filter.block.DelegateFilter;
import com.fastasyncworldedit.core.extent.filter.block.FilterBlock;
import com.fastasyncworldedit.core.internal.simd.VectorFacade;
import com.fastasyncworldedit.core.internal.simd.SimdSupport;
import com.fastasyncworldedit.core.internal.simd.VectorizedFilter;
import com.fastasyncworldedit.core.internal.simd.VectorizedMask;
Expand All @@ -11,6 +12,7 @@
import jdk.incubator.vector.ShortVector;
import jdk.incubator.vector.VectorMask;
import jdk.incubator.vector.VectorOperators;
import jdk.incubator.vector.VectorSpecies;

import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
Expand Down Expand Up @@ -82,13 +84,15 @@ public VectorizedMaskFilter(final T other, final Mask root, AtomicInteger change
}

@Override
public ShortVector applyVector(final ShortVector get, final ShortVector set, VectorMask<Short> mask) {
public void applyVector(final VectorFacade get, final VectorFacade set, final VectorMask<Short> mask) {
final T parent = getParent();
VectorMask<Short> masked = vectorizedMask.compareVector(set, get);
ShortVector res = parent.applyVector(get, set, mask.and(masked));
VectorMask<Short> changed = res.compare(VectorOperators.NE, set);
changes.getAndAdd(changed.trueCount());
return res;
final VectorSpecies<Short> species = mask.vectorSpecies();
VectorMask<Short> masked = this.vectorizedMask.compareVector(set, get, species);
ShortVector before = set.getOrZero(masked.vectorSpecies());
parent.applyVector(get, set, mask.and(masked));
ShortVector after = set.getOrZero(masked.vectorSpecies());
VectorMask<Short> changed = after.compare(VectorOperators.NE, before);
this.changes.getAndAdd(changed.trueCount());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ public class CharFilterBlock extends ChunkFilterBlock {

private int maxLayer;
private int minLayer;
private CharGetBlocks get;
private IChunkSet set;
protected CharGetBlocks get;
protected IChunkSet set;
protected char[] getArr;
@Nullable
protected char[] setArr;
protected SetDelegate delegate;
// local
private int layer;
protected int layer;
private int index;
private int x;
private int y;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,23 +54,23 @@ public static boolean useVectorApi() {
if (base == null) {
yield null;
}
yield (set, get) -> base.compareVector(set, get).not();
yield (set, get, species) -> base.compareVector(set, get, species).not();
}
default -> null;
};
}

private static VectorizedMask vectorizedTargetMaskNonAir() {
// everything > VOID_AIR is not air
return (set, get) -> get.compare(VectorOperators.UNSIGNED_GT, BlockTypesCache.ReservedIDs.VOID_AIR);
return (set, get, species) -> get.get(species).compare(VectorOperators.UNSIGNED_GT, BlockTypesCache.ReservedIDs.VOID_AIR);
}

private static VectorizedMask vectorizedTargetMask(char ordinal) {
return (set, get) -> get.compare(VectorOperators.EQ, (short) ordinal);
return (set, get, species) -> get.get(species).compare(VectorOperators.EQ, (short) ordinal);
}

private static VectorizedMask vectorizedTargetMaskInverse(char ordinal) {
return (set, get) -> get.compare(VectorOperators.NE, (short) ordinal);
return (set, get, species) -> get.get(species).compare(VectorOperators.NE, (short) ordinal);
}

public static @Nullable VectorizedFilter vectorizedPattern(Pattern pattern) {
Expand Down Expand Up @@ -102,14 +102,16 @@ public VectorizedPattern(final T parent, char ordinal) {
}

@Override
public ShortVector applyVector(final ShortVector get, final ShortVector set, VectorMask<Short> mask) {
// only change the lanes the mask dictates us to change, keep the rest
return set.blend(ShortVector.broadcast(ShortVector.SPECIES_PREFERRED, ordinal), mask);
public Filter newInstance(final Filter other) {
return new VectorizedPattern<>(other, ordinal);
}

@Override
public Filter newInstance(final Filter other) {
return new VectorizedPattern<>(other, ordinal);
public void applyVector(final VectorFacade get, final VectorFacade set, final VectorMask<Short> mask) {
ShortVector s = set.getOrZero(mask.vectorSpecies());
// only change the lanes the mask dictates us to change, keep the rest
s = s.blend(ShortVector.broadcast(ShortVector.SPECIES_PREFERRED, ordinal), mask);
set.setOrIgnore(s);
}

}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.fastasyncworldedit.core.internal.simd;

import com.fastasyncworldedit.core.queue.IBlocks;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import jdk.incubator.vector.ShortVector;
import jdk.incubator.vector.VectorSpecies;
import org.jetbrains.annotations.ApiStatus;

@ApiStatus.Internal
public class VectorFacade {
private final IBlocks blocks;
private int layer;
private int index;
private char[] data;

VectorFacade(final IBlocks blocks) {
this.blocks = blocks;
}

public ShortVector get(VectorSpecies<Short> species) {
if (this.data == null) {
load();
}
return ShortVector.fromCharArray(species, this.data, this.index);
}

public ShortVector getOrZero(VectorSpecies<Short> species) {
if (this.data == null) {
return species.zero().reinterpretAsShorts();
}
return ShortVector.fromCharArray(species, this.data, this.index);
}

public void setOrIgnore(ShortVector vector) {
if (this.data == null) {
if (vector.eq((short) BlockTypesCache.ReservedIDs.__RESERVED__).allTrue()) {
return;
}
load();
}
vector.intoCharArray(this.data, this.index);
}

private void load() {
this.data = this.blocks.load(this.layer);
}

public void setLayer(int layer) {
this.layer = layer;
this.data = null;
}

public void setIndex(int index) {
this.index = index;
}

public void setData(char[] data) {
this.data = data;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,17 @@ public synchronized void filter(final Filter filter) {
throw new IllegalStateException("Unexpected VectorizedCharFilterBlock " + filter);
}
final VectorSpecies<Short> species = ShortVector.SPECIES_PREFERRED;
// TODO can we avoid eager initSet?
initSet(); // set array is null before
char[] setArr = this.setArr;
assert setArr != null;
char[] getArr = this.getArr;
VectorFacade setFassade = new VectorFacade(this.set);
setFassade.setLayer(this.layer);
VectorFacade getFassade = new VectorFacade(this.get);
getFassade.setLayer(this.layer);
getFassade.setData(this.getArr);
// assume setArr.length == getArr.length == 4096
VectorMask<Short> affectAll = species.maskAll(true);
for (int i = 0; i < 4096; i += species.length()) {
ShortVector set = ShortVector.fromCharArray(species, setArr, i);
ShortVector get = ShortVector.fromCharArray(species, getArr, i);
ShortVector res = vecFilter.applyVector(get, set, affectAll);
res.intoCharArray(setArr, i);
setFassade.setIndex(i);
getFassade.setIndex(i);
vecFilter.applyVector(getFassade, setFassade, affectAll);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.fastasyncworldedit.core.internal.simd;

import com.fastasyncworldedit.core.queue.Filter;
import jdk.incubator.vector.ShortVector;
import jdk.incubator.vector.VectorMask;

public interface VectorizedFilter extends Filter {
Expand All @@ -12,8 +11,7 @@ public interface VectorizedFilter extends Filter {
* @param get the get vector
* @param set the set vector
* @param mask the mask with the lanes set to true which should be affected by the filter
* @return the resulting set vector.
*/
ShortVector applyVector(ShortVector get, ShortVector set, VectorMask<Short> mask);
void applyVector(VectorFacade get, VectorFacade set, VectorMask<Short> mask);

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,43 +11,50 @@
public interface VectorizedMask {

default void processChunks(IChunk chunk, IChunkGet get, IChunkSet set) {
VectorFacade setFassade = new VectorFacade(set);
VectorFacade getFassade = new VectorFacade(get);
for (int layer = get.getMinSectionPosition(); layer <= get.getMaxSectionPosition(); layer++) {
setFassade.setLayer(layer);
getFassade.setLayer(layer);
final char[] sectionSet = set.loadIfPresent(layer);
if (sectionSet == null) {
continue;
}
final char[] sectionGet = get.load(layer);
processSection(layer, sectionSet, sectionGet);
setFassade.setData(sectionSet);
processSection(layer, setFassade, getFassade);
}
}

default void processSection(int layer, char[] set, char[] get) {
default void processSection(int layer, VectorFacade set, VectorFacade get) {
final VectorSpecies<Short> species = ShortVector.SPECIES_PREFERRED;
// assume that set.length % species.elementSize() == 0
for (int i = 0; i < set.length; i += species.length()) {
ShortVector vectorSet = ShortVector.fromCharArray(species, set, i);
ShortVector vectorGet = ShortVector.fromCharArray(species, get, i);
vectorSet = processVector(vectorSet, vectorGet);
vectorSet.intoCharArray(set, i);
// assume that chunk sections have length 16 * 16 * 16 == 4096
for (int i = 0; i < 4096; i += species.length()) {
set.setIndex(i);
get.setIndex(i);
processVector(set, get, species);
}
}

/**
* {@return the set vector with all lanes that do not match this mask set to 0}
* Clears all blocks that aren't covered by the mask.
*
* @param set the set vector
* @param get the get vector
* @param set the set vector
* @param get the get vector
* @param species the species to use
*/
default ShortVector processVector(ShortVector set, ShortVector get) {
return set.blend(BlockTypesCache.ReservedIDs.__RESERVED__, compareVector(set, get).not());
default void processVector(VectorFacade set, VectorFacade get, VectorSpecies<Short> species) {
ShortVector s = set.getOrZero(species);
s = s.blend(BlockTypesCache.ReservedIDs.__RESERVED__, compareVector(set, get, species).not());
set.setOrIgnore(s);
}

/**
* {@return a mask with all lanes set that match this mask}
*
* @param set the set vector
* @param get the get vector
* @param set the set vector
* @param get the get vector
* @param species the species to use
*/
VectorMask<Short> compareVector(ShortVector set, ShortVector get);
VectorMask<Short> compareVector(VectorFacade set, VectorFacade get, VectorSpecies<Short> species);

}
Loading