Stable radix sprite sort and render hot-path optimizations
SpriteBatcher now sorts with a stable LSD radix sort: equal-key sprites keep submission order across frames (no flicker) and passes over digits identical in all keys are skipped, making the common single-layer case nearly free. Hot paths avoid per-sprite trig and square roots: SinCos is skipped for unrotated sprites and the culling radius comes from the region's precomputed diagonal. Stress scene (100k entities, ~61k on screen, Release): 103 -> 124 FPS. Sample now runs with VSync off to show real frame rates. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
2b7d4c4fef
commit
a3e6d3bb0a
@@ -37,6 +37,33 @@ public class CullingTests
|
||||
Assert.Equal(0.5f * MathF.Sqrt(800f), radius, 3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BoundingCircle_RegionOverload_MatchesSizeOverload_ForUniformScale()
|
||||
{
|
||||
var region = new Texture2DRegion(null!, new Rectangle(0, 0, 48, 24));
|
||||
var transform = new Transform2D(new Vector2(10f, 20f), rotation: 0.6f, scale: new Vector2(1.5f, 1.5f));
|
||||
var origin = new Vector2(5f, 7f);
|
||||
|
||||
var (centerA, radiusA) = CullingMath.SpriteBoundingCircle(transform, 48f, 24f, origin);
|
||||
var (centerB, radiusB) = CullingMath.SpriteBoundingCircle(in transform, region, origin);
|
||||
|
||||
Assert.Equal(centerA.X, centerB.X, 3);
|
||||
Assert.Equal(centerA.Y, centerB.Y, 3);
|
||||
Assert.Equal(radiusA, radiusB, 3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BoundingCircle_RegionOverload_IsConservative_ForNonUniformScale()
|
||||
{
|
||||
var region = new Texture2DRegion(null!, new Rectangle(0, 0, 100, 10));
|
||||
var transform = new Transform2D(Vector2.Zero, scale: new Vector2(1f, 3f));
|
||||
|
||||
var (_, exact) = CullingMath.SpriteBoundingCircle(transform, 100f, 10f, Vector2.Zero);
|
||||
var (_, conservative) = CullingMath.SpriteBoundingCircle(in transform, region, Vector2.Zero);
|
||||
|
||||
Assert.True(conservative >= exact);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(50f, 50f, true)] // inside
|
||||
[InlineData(-4f, 50f, true)] // touching from the left (radius 5)
|
||||
|
||||
Reference in New Issue
Block a user