Skip to content

Commit

Permalink
Merge branch 'gfni' into gfni-timing-recorder
Browse files Browse the repository at this point in the history
  • Loading branch information
douira committed Dec 17, 2023
2 parents 7553494 + 4ae774e commit 26f2299
Show file tree
Hide file tree
Showing 9 changed files with 30 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ class DirectTriggers implements SectionTriggers<TopoSortDynamicData> {
* Degrees of movement from last sort position before the section is sorted
* again.
*/
private static final double TRIGGER_ANGLE = Math.toRadians(20);
private static final double TRIGGER_ANGLE = Math.toRadians(10);
private static final double EARLY_TRIGGER_ANGLE_COS = Math.cos(TRIGGER_ANGLE * EARLY_TRIGGER_FACTOR);
private static final double SECTION_CENTER_DIST_SQUARED = 40 * 3 * Math.pow(16 / 2, 2);
private static final double SECTION_CENTER_DIST_SQUARED = 3 * Math.pow(16 / 2, 2) + 1;
private static final double SECTION_CENTER_DIST = Math.sqrt(SECTION_CENTER_DIST_SQUARED);

/**
Expand Down Expand Up @@ -104,12 +104,11 @@ boolean isAngleTriggering(Vector3dc vector) {
}
}

// TODO: use faster code for this
private static double angleCos(double ax, double ay, double az, double bx, double by, double bz) {
double length1Squared = Math.fma(ax, ax, Math.fma(ay, ay, az * az));
double length2Squared = Math.fma(bx, bx, Math.fma(by, by, bz * bz));
double lengthA = Math.sqrt(Math.fma(ax, ax, Math.fma(ay, ay, az * az)));
double lengthB = Math.sqrt(Math.fma(bx, bx, Math.fma(by, by, bz * bz)));
double dot = Math.fma(ax, bx, Math.fma(ay, by, az * bz));
return dot / Math.sqrt(length1Squared * length2Squared);
return dot / (lengthA * lengthB);
}

private void insertDirectAngleTrigger(DirectTriggerData data, Vector3dc cameraPos, double remainingAngle) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ int getQuadHash() {

public float getAlignedSurfaceArea() {
if (this.facing == ModelQuadFacing.UNASSIGNED) {
return 0;
return 100;
}

var dX = this.extents[3] - this.extents[0];
Expand All @@ -42,7 +42,7 @@ public float getAlignedSurfaceArea() {
return (float) (dX * dY);
} else {
// non-flat aligned quad, weird edge case
return 0;
return 90;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,6 @@ public void appendQuad(ModelQuadView quadView, ChunkVertexEncoder.Vertex[] verti
// POS_X, POS_Y, POS_Z, NEG_X, NEG_Y, NEG_Z
float[] extents = new float[] { posXExtent, posYExtent, posZExtent, negXExtent, negYExtent, negZExtent };

// TODO: does it make a difference if we compute the center as the average of
// the unique vertices or as the center of the extents? (the latter would be
// less work)

// TODO: some of these things should probably only be computed on demand, and an
// allocation of a Quad object should be avoided
AccumulationGroup accGroup;
Expand Down Expand Up @@ -413,7 +409,6 @@ private TranslucentData makeNewTranslucentData(BuiltSectionMeshParts translucent

// from this point on we know the estimated sort type requires direction mixing
// (no backface culling) and all vertices are in the UNASSIGNED direction.
// TODO: don't attempt static topo sorting if BSP sorting works well.
NativeBuffer buffer = PresentTranslucentData.nativeBufferForQuads(this.quads);
if (this.sortType == SortType.STATIC_TOPO_ACYCLIC) {
var result = StaticTopoAcyclicData.fromMesh(translucentMesh, this.quads, sectionPos, buffer);
Expand All @@ -434,6 +429,7 @@ private TranslucentData makeNewTranslucentData(BuiltSectionMeshParts translucent
try {
return BSPDynamicData.fromMesh(translucentMesh, cameraPos, quads, sectionPos, buffer, oldData);
} catch (BSPBuildFailureException e) {
// TODO: investigate existing BSP build failures, then remove this logging
System.out.println("BSP build failure: " + sectionPos);
return TopoSortDynamicData.fromMesh(translucentMesh, cameraPos, quads, sectionPos, this, buffer);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,11 @@
* sections for dynamic sorting to the trigger components.
*
* TODO:
* - many sections can be marked as needing an update but they are only actually
* scheduled for sorting when the RenderSectionManager makes them visible. This
* may result in many sections suddenly needing sorting when the camera moves.
* Maybe it's better to schedule them to be sorted gradually even if not
* visible, if there are idle threads.
* - Movement prediction and preemptive task scheduling to avoid needing to
* perform blocking sorts of close sections. Maybe not an issue? Might reduce
* stutter in high fps situations. However, high complexity with regards to
* processing the results of preemptive sorts.
* - determine the right distance for angle/distance triggering. It seems just
* the diagonal of a section is too small, angle triggering is broken at close
* distances.
* - Bug: adding a slime block onto one of the corners of the monster cube makes
* it invisible. Is this because there's nothing else in this section than just
* that one block? Might have something to do with NONE mode behaving weirdly in
* that situation. Possibly related to index buffer reuse, since it only happens
* after the block has been replaced at least once.
* - Incompatible with rendering anything through Indium because it doesn't run
* the translucent geometry collector properly. It doesn't run Sodium's
* BlockRenderer which is required for lines 166-167 of BlockRenderer to work.
*
* @author douira
* @author douira (the translucent_sorting package)
*/
public class TranslucentSorting {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
* - Doing a convex box test doesn't seem to bring a performance boost, even if
* it does trigger sometimes with man-made structures. The multi partition node
* probably does most of the work already.
* - Checking if the given quads are all coplanar doesn't recoup the cost of
* iterating through all the quads. It also doesn't significantly reduce the
* number of triggering planes (which would have a performance and memory usage
* benefit).
*/
public abstract class BSPNode {

Expand All @@ -27,7 +31,8 @@ public void collectSortedQuads(NativeBuffer nativeBuffer, Vector3fc cameraPos) {
this.collectSortedQuads(new BSPSortState(nativeBuffer), cameraPos);
}

public static BSPResult buildBSP(TQuad[] quads, ChunkSectionPos sectionPos, BSPNode oldRoot, boolean prepareNodeReuse) {
public static BSPResult buildBSP(TQuad[] quads, ChunkSectionPos sectionPos, BSPNode oldRoot,
boolean prepareNodeReuse) {
// throw if there's too many quads
InnerPartitionBSPNode.validateQuadCount(quads.length);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,22 @@ void writeIndex(int index) {
}
}

private static final int INDEX_COMPRESSION_MIN_LENGTH = 50;
private static final int HEADER_LENGTH = 2;
/**
* The minimum size of an index array that will be compressed. This value is
* non-zero to avoid wasting work on compressing arrays that won't benefit from
* it and the overhead in setting up the compression. Empirically, the
* compression ratio is only high for the very largest arrays and largely
* useless for smaller ones.
*/
private static final int INDEX_COMPRESSION_MIN_LENGTH = 32;

private static final int HEADER_LENGTH = 2;
private static final int[] WIDTHS = new int[] { 1, 2, 3, 4, 5, 6, 8, 10, 16, 32 };

private static final int CONSTANT_DELTA_WIDTH_INDEX = 15;

/**
* ceilDiv was introduced to the JDK in Java 18 but is not available in Java 17.
* ceilDiv was introduced to the JDK in Java 18 but is not available in the here
* used Java 17.
*/
private static int ceilDiv(int x, int y) {
return -Math.floorDiv(-x, y);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,6 @@
import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFacing;

/**
* TODO:
* - make partition finding more sophisticated by using distancesByNormal
* and other information.
* - pass partition information to child nodes instead of discarding if
* partition didn't work
* - detect many coplanar quads and avoid partitioning sorting alltogether. Try
* to partition so that large groups of coplanar quads are kept together and
* then not sorted at all.
* - sort the quads inside a node using the same heuristics as in the global
* level: convex hulls (like cuboids where the faces point outwards) don't need
* to be sorted. This could be used to optimize the inside of honey blocks, and
* other blocks.
*
* Implementation note:
* - Presorting the points in block-sized buckets doesn't help. It seems the
* sort algorithm is just fast enough to handle this.
Expand Down Expand Up @@ -78,9 +65,6 @@ record NodeReuseData(float[][] quadExtents, int[] indexes, int indexCount, int m
static NodeReuseData prepareNodeReuse(BSPWorkspace workspace, IntArrayList indexes, int depth) {
// if node reuse is enabled, only enable on the first level of children (not the
// root node and not anything deeper than its children)
// TODO: more sophisticated reuse scheduling (make uset configurable, and only
// do once the section has been modified at least once already to avoid making
// this data on terrain sections that are never touched)
if (workspace.prepareNodeReuse && depth == 1 && indexes.size() > NODE_REUSE_THRESHOLD) {
// collect the extents of the indexed quads and hash them
var quadExtents = new float[indexes.size()][];
Expand Down Expand Up @@ -325,7 +309,6 @@ static BSPNode build(BSPWorkspace workspace, IntArrayList indexes, int depth, BS
// check a different axis if everything is in one quadsBefore,
// which means there are no gaps
if (quadsBefore != null && quadsBefore.size() == indexes.size()) {
// TODO: reuse the sorted point array for child nodes (add to workspace)
continue;
}

Expand Down Expand Up @@ -356,36 +339,27 @@ static BSPNode build(BSPWorkspace workspace, IntArrayList indexes, int depth, BS
partitions, axis, endsWithPlane);
}

// TODO: attempt unaligned partitioning, convex decomposition, etc.

// test if the geometry intersects with itself
// if there is self-intersection, return a multi leaf node to just give up
// sorting this geometry. intersecting geometry is rare but when it does happen,
// it should simply be accepted and rendered as-is. Whatever artifacts this
// causes are considered "ok".
// TODO: also do this test with unaligned quads
int testsRemaining = 10000;
for (int quadAIndex = 0; quadAIndex < indexes.size(); quadAIndex++) {
var quadA = workspace.quads[indexes.getInt(quadAIndex)];
if (quadA.facing() == ModelQuadFacing.UNASSIGNED) {
continue;
}

for (int quadBIndex = quadAIndex + 1; quadBIndex < indexes.size(); quadBIndex++) {
var quadB = workspace.quads[indexes.getInt(quadBIndex)];

if (quadB.facing() == ModelQuadFacing.UNASSIGNED) {
continue;
}

// aligned quads intersect if their bounding boxes intersect
boolean intersects = true;
for (int axis = 0; axis < 3; axis++) {
var opposite = axis + 3;
var extentsA = quadA.extents();
var extentsB = quadB.extents();

if (extentsA[axis] < extentsB[opposite]
|| extentsB[axis] < extentsA[opposite]) {
if (extentsA[axis] <= extentsB[opposite]
|| extentsB[axis] <= extentsA[opposite]) {
intersects = false;
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ public static BSPDynamicData fromMesh(BuiltSectionMeshParts translucentMesh,
TimingRecorder.incrementBy(Counter.BSP_SECTIONS, 1);

// prepare accumulation groups for integration into GFNI triggering
// TODO: combine this and the similar code in TopoSortDynamicData
var aligned = result.getAlignedDistances();
if (aligned != null) {
for (var accGroup : aligned) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap;
import me.jellysquid.mods.sodium.client.gl.util.VertexRange;
import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFacing;
import me.jellysquid.mods.sodium.client.render.chunk.data.BuiltSectionMeshParts;
import me.jellysquid.mods.sodium.client.render.chunk.translucent_sorting.TQuad;
import me.jellysquid.mods.sodium.client.render.chunk.translucent_sorting.TopoGraphSorting;
Expand Down Expand Up @@ -219,16 +218,14 @@ public static TopoSortDynamicData fromMesh(BuiltSectionMeshParts translucentMesh

var distancesByNormal = new Object2ReferenceOpenHashMap<Vector3fc, float[]>(size);
if (collector.getAlignedDistances() != null) {
for (int direction = 0; direction < ModelQuadFacing.DIRECTIONS; direction++) {
var accGroup = collector.getAlignedDistances()[direction];
for (var accGroup : collector.getAlignedDistances()) {
if (accGroup != null) {
accGroup.prepareAndInsert(distancesByNormal);
}
}
}
if (collector.getUnalignedDistanceCount() > 0) {
for (var accGroup : collector.getUnalignedDistances()) {
// TODO: get rid of collector key and just use the normal vector's hash code
accGroup.prepareAndInsert(distancesByNormal);
}
}
Expand Down

0 comments on commit 26f2299

Please sign in to comment.