Merge branch 'distant-horizons-core-optimizations'
This commit is contained in:
+51
-51
@@ -59,9 +59,19 @@ public final class BufferQuad
|
||||
|
||||
public boolean hasError = false;
|
||||
|
||||
// Pre-computed sort keys to avoid recomputing on every comparison
|
||||
// Slight increase in memory for reduction in cpu usage
|
||||
public final long sortKeyEastWest;
|
||||
public final long sortKeyNorthSouth;
|
||||
|
||||
|
||||
BufferQuad(
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
public BufferQuad(
|
||||
short x, short y, short z, short widthEastWest, short widthNorthSouthOrHeight,
|
||||
int color, byte irisBlockMaterialId, byte skylight, byte blockLight,
|
||||
EDhDirection direction)
|
||||
@@ -85,64 +95,46 @@ public final class BufferQuad
|
||||
this.skyLight = skylight;
|
||||
this.blockLight = blockLight;
|
||||
this.direction = direction;
|
||||
this.sortKeyEastWest = computeSortKey(direction, true);
|
||||
this.sortKeyNorthSouth = computeSortKey(direction, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** a rough but fast calculation */
|
||||
double calculateDistance(double relativeX, double relativeY, double relativeZ)
|
||||
private long computeSortKey(EDhDirection dir, boolean eastWest)
|
||||
{
|
||||
return Math.pow(relativeX - this.x, 2) + Math.pow(relativeY - this.y, 2) + Math.pow(relativeZ - this.z, 2);
|
||||
if (eastWest)
|
||||
{
|
||||
switch (dir.axis)
|
||||
{
|
||||
case X: return (long) x << 48 | (long) y << 32 | (long) z << 16;
|
||||
case Y: return (long) y << 48 | (long) z << 32 | (long) x << 16;
|
||||
case Z: return (long) z << 48 | (long) y << 32 | (long) x << 16;
|
||||
default: throw new IllegalArgumentException("Invalid Axis enum: [" + dir.axis + "].");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (dir.axis)
|
||||
{
|
||||
case X: return (long) x << 48 | (long) z << 32 | (long) y << 16;
|
||||
case Y: return (long) y << 48 | (long) x << 32 | (long) z << 16;
|
||||
case Z: return (long) z << 48 | (long) x << 32 | (long) y << 16;
|
||||
default: throw new IllegalArgumentException("Invalid Axis enum: [" + dir.axis + "].");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** compares this quad's position to the given quad */
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
/** compares this quad's position to the given quad using pre-computed sort keys */
|
||||
public int compare(BufferQuad quad, BufferMergeDirectionEnum compareDirection)
|
||||
{
|
||||
if (this.direction != quad.direction)
|
||||
throw new IllegalArgumentException("The other quad is not in the same direction: " + quad.direction + " vs " + this.direction);
|
||||
|
||||
if (compareDirection == BufferMergeDirectionEnum.EastWest)
|
||||
{
|
||||
switch (this.direction.axis)
|
||||
{
|
||||
case X:
|
||||
return threeDimensionalCompare(this.x, this.y, this.z, quad.x, quad.y, quad.z);
|
||||
case Y:
|
||||
return threeDimensionalCompare(this.y, this.z, this.x, quad.y, quad.z, quad.x);
|
||||
case Z:
|
||||
return threeDimensionalCompare(this.z, this.y, this.x, quad.z, quad.y, quad.x);
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid Axis enum: [" + this.direction.axis + "].");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (this.direction.axis)
|
||||
{
|
||||
case X:
|
||||
return threeDimensionalCompare(this.x, this.z, this.y, quad.x, quad.z, quad.y);
|
||||
case Y:
|
||||
return threeDimensionalCompare(this.y, this.x, this.z, quad.y, quad.x, quad.z);
|
||||
case Z:
|
||||
return threeDimensionalCompare(this.z, this.x, this.y, quad.z, quad.x, quad.y);
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid Axis enum: [" + this.direction.axis + "].");
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Compares two 3D points A and B. <br>
|
||||
* The X, Y, and Z coordinates can be passed into parameters 0, 1, and 2 in any order
|
||||
* provided they are in the same order for both A and B. <br>
|
||||
* With the 0th parameter being the most significant when comparing.
|
||||
*/
|
||||
private static int threeDimensionalCompare(short a0, short a1, short a2, short b0, short b1, short b2)
|
||||
{
|
||||
long a = (long) a0 << 48 | (long) a1 << 32 | (long) a2 << 16;
|
||||
long b = (long) b0 << 48 | (long) b1 << 32 | (long) b2 << 16;
|
||||
return Long.compare(a, b);
|
||||
return compareDirection == BufferMergeDirectionEnum.EastWest
|
||||
? Long.compare(this.sortKeyEastWest, quad.sortKeyEastWest)
|
||||
: Long.compare(this.sortKeyNorthSouth, quad.sortKeyNorthSouth);
|
||||
}
|
||||
|
||||
|
||||
@@ -154,11 +146,15 @@ public final class BufferQuad
|
||||
public boolean tryMerge(BufferQuad quad, BufferMergeDirectionEnum mergeDirection)
|
||||
{
|
||||
if (quad.hasError || this.hasError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// only merge quads that are in the same direction
|
||||
if (this.direction != quad.direction)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure these quads share the same perpendicular axis
|
||||
if ((mergeDirection == BufferMergeDirectionEnum.EastWest && this.y != quad.y)
|
||||
@@ -175,7 +171,6 @@ public final class BufferQuad
|
||||
short otherParallelCompareStartPos;
|
||||
switch (this.direction.axis)
|
||||
{
|
||||
default: // shouldn't normally happen, just here to make the compiler happy
|
||||
case X:
|
||||
if (mergeDirection == BufferMergeDirectionEnum.EastWest)
|
||||
{
|
||||
@@ -232,6 +227,9 @@ public final class BufferQuad
|
||||
otherParallelCompareStartPos = quad.z;
|
||||
}
|
||||
break;
|
||||
|
||||
default: // shouldn't normally happen, just here to make the compiler happy
|
||||
throw new IllegalArgumentException("Unsupported axis: ["+this.direction.axis+"]");
|
||||
}
|
||||
|
||||
// get the width of this quad in the relevant axis
|
||||
@@ -333,4 +331,6 @@ public final class BufferQuad
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+15
-6
@@ -341,13 +341,24 @@ public class ColumnBox
|
||||
|
||||
|
||||
// Apply light to the range [adjMinY, adjMaxY)
|
||||
applyLightToRange(segments, newSegments, adjMinY, adjMaxY, lightToApply);
|
||||
applyLightToRangeAndPopulateNewSgements(segments, newSegments, adjMinY, adjMaxY, lightToApply);
|
||||
{
|
||||
// swap references so we can use the newly populated segments
|
||||
LongArrayList temp = segments;
|
||||
segments = newSegments;
|
||||
newSegments = temp;
|
||||
}
|
||||
|
||||
// Fill overhang area [adjMaxY, adjAboveMinY) with adjSkyLight
|
||||
short adjAboveMinY = RenderDataPointUtil.getYMin(adjAbovePoint);
|
||||
if (adjMaxY < adjAboveMinY)
|
||||
{
|
||||
applyLightToRange(segments, newSegments, adjMaxY, adjAboveMinY, adjSkyLight);
|
||||
applyLightToRangeAndPopulateNewSgements(segments, newSegments, adjMaxY, adjAboveMinY, adjSkyLight);
|
||||
{
|
||||
LongArrayList temp = segments;
|
||||
segments = newSegments;
|
||||
newSegments = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,10 +384,11 @@ public class ColumnBox
|
||||
/**
|
||||
* Apply the new light value over the given y range,
|
||||
* splitting segments as needed
|
||||
* and putting the new segments into "newSegments"
|
||||
* <p>
|
||||
* source: claude.ai
|
||||
*/
|
||||
private static void applyLightToRange(
|
||||
private static void applyLightToRangeAndPopulateNewSgements(
|
||||
LongArrayList segments, LongArrayList newSegments,
|
||||
short rangeStart, short rangeEnd,
|
||||
byte newLight)
|
||||
@@ -419,9 +431,6 @@ public class ColumnBox
|
||||
newSegments.add(YSegmentUtil.encode(rangeEnd, endY, skyLight));
|
||||
}
|
||||
}
|
||||
|
||||
segments.clear();
|
||||
segments.addAll(newSegments);
|
||||
}
|
||||
|
||||
private static void tryAddVerticalFaceWithSkyLightToBuilder(
|
||||
|
||||
+8
-6
@@ -129,6 +129,7 @@ public class FullDataToRenderDataTransformer
|
||||
ColumnRenderView tempExpandingColumnView = ColumnRenderView.getPooled();
|
||||
RenderDataPointReducingList reducingList = new RenderDataPointReducingList())
|
||||
{
|
||||
DhBlockPosMutable mutableBlockPos = new DhBlockPosMutable();
|
||||
for (int x = 0; x < FullDataSourceV2.WIDTH; x++)
|
||||
{
|
||||
for (int z = 0; z < FullDataSourceV2.WIDTH; z++)
|
||||
@@ -142,7 +143,7 @@ public class FullDataToRenderDataTransformer
|
||||
baseX + BitShiftUtil.pow(x, dataDetail), baseZ + BitShiftUtil.pow(z, dataDetail),
|
||||
columnArrayView, dataColumn,
|
||||
// pooled references so we don't need to re-allocate/get them 4000 times per render source
|
||||
phantomCheckout, tempExpandingColumnView, reducingList);
|
||||
phantomCheckout, tempExpandingColumnView, reducingList, mutableBlockPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -157,7 +158,7 @@ public class FullDataToRenderDataTransformer
|
||||
ColumnRenderView columnArrayView,
|
||||
LongArrayList fullDataColumn,
|
||||
// pooled references
|
||||
PhantomArrayListCheckout phantomCheckout, ColumnRenderView tempExpandingColumnView, RenderDataPointReducingList reducingList)
|
||||
PhantomArrayListCheckout phantomCheckout, ColumnRenderView tempExpandingColumnView, RenderDataPointReducingList reducingList, DhBlockPosMutable mutableBlockPos)
|
||||
{
|
||||
// we can't do anything if the full data is missing or empty
|
||||
if (fullDataColumn == null
|
||||
@@ -170,7 +171,7 @@ public class FullDataToRenderDataTransformer
|
||||
if (fullDataLength <= columnArrayView.maxVerticalSliceCount)
|
||||
{
|
||||
// Directly use the arrayView since it fits.
|
||||
setRenderColumnView(levelWrapper, fullDataSource, blockX, blockZ, columnArrayView, fullDataColumn);
|
||||
setRenderColumnView(levelWrapper, fullDataSource, blockX, blockZ, columnArrayView, fullDataColumn, mutableBlockPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -178,7 +179,7 @@ public class FullDataToRenderDataTransformer
|
||||
|
||||
// expand the ColumnArrayView to fit the new larger max vertical size
|
||||
tempExpandingColumnView.populate(dataArrayList, fullDataLength, 0, fullDataLength);
|
||||
setRenderColumnView(levelWrapper, fullDataSource, blockX, blockZ, tempExpandingColumnView, fullDataColumn);
|
||||
setRenderColumnView(levelWrapper, fullDataSource, blockX, blockZ, tempExpandingColumnView, fullDataColumn, mutableBlockPos);
|
||||
|
||||
columnArrayView.changeVerticalSizeFrom(tempExpandingColumnView, reducingList);
|
||||
}
|
||||
@@ -186,7 +187,7 @@ public class FullDataToRenderDataTransformer
|
||||
private static void setRenderColumnView(
|
||||
IClientLevelWrapper levelWrapper, FullDataSourceV2 fullDataSource,
|
||||
int blockX, int blockZ,
|
||||
ColumnRenderView renderColumnData, LongArrayList fullColumnData)
|
||||
ColumnRenderView renderColumnData, LongArrayList fullColumnData, DhBlockPosMutable mutableBlockPos)
|
||||
{
|
||||
//===============//
|
||||
// config values //
|
||||
@@ -242,7 +243,8 @@ public class FullDataToRenderDataTransformer
|
||||
|
||||
FullDataPointIdMap fullDataMapping = fullDataSource.mapping;
|
||||
|
||||
DhBlockPosMutable mutableBlockPos = new DhBlockPosMutable(blockX, 0, blockZ);
|
||||
mutableBlockPos.setX(blockX);
|
||||
mutableBlockPos.setZ(blockZ);
|
||||
|
||||
// goes from the top down
|
||||
for (int fullDataIndex = 0; fullDataIndex < fullColumnData.size(); fullDataIndex++)
|
||||
|
||||
+8
-1
@@ -73,10 +73,17 @@ public class RateLimitedThreadPoolExecutor extends ThreadPoolExecutor
|
||||
{
|
||||
super.afterExecute(runnable, throwable);
|
||||
|
||||
double ratio = this.runTimeRatioConfig.get();
|
||||
if (ratio >= 1.0)
|
||||
{
|
||||
// Avoid sleeping for 0 time
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
long runTime = System.nanoTime() - this.runStartTime.get();
|
||||
Thread.sleep(TimeUnit.NANOSECONDS.toMillis((long) (runTime / this.runTimeRatioConfig.get() - runTime)));
|
||||
Thread.sleep(TimeUnit.NANOSECONDS.toMillis((long) (runTime / ratio - runTime)));
|
||||
}
|
||||
catch (InterruptedException ignore)
|
||||
{
|
||||
|
||||
@@ -188,11 +188,11 @@
|
||||
"If true non terrain objects will be rendered in DH's terrain. \nThis includes beacon beams and clouds.",
|
||||
"distanthorizons.config.client.advanced.graphics.genericRendering.enableBeaconRendering":
|
||||
"Enable Beacon Rendering",
|
||||
"distanthorizons.config.client.advanced.graphics.genericRendering.beaconRenderHeight":
|
||||
"distanthorizons.config.client.advanced.graphics.genericRendering.beaconRenderHeight":
|
||||
"Beacon render height",
|
||||
"distanthorizons.config.client.advanced.graphics.genericRendering.beaconRenderHeight.@tooltip":
|
||||
"Sets the maximum height at which beacons will render. \nThis will only affect new beacons coming into LOD render distance. \nBeacons currently visible in LOD chunks will not be affected.",
|
||||
"distanthorizons.config.client.advanced.graphics.genericRendering.expandDistantBeacons":
|
||||
"distanthorizons.config.client.advanced.graphics.genericRendering.expandDistantBeacons":
|
||||
"Expand Distant Beacons",
|
||||
"distanthorizons.config.client.advanced.graphics.genericRendering.expandDistantBeacons.@tooltip":
|
||||
"If true LOD beacon beams will be rendered wider at extreme distances, \nmaking them easier to see. \nIf false all LOD beacon beams will only ever be 1 block wide.",
|
||||
|
||||
Reference in New Issue
Block a user