Profile and optimize retained rendering

This commit is contained in:
gamer147
2026-07-22 14:19:20 -04:00
parent 4c9719c5dc
commit 4ea352e45d
17 changed files with 1619 additions and 144 deletions

View File

@@ -0,0 +1,97 @@
using Age.Engine.Model;
public class PerformanceFrameLogTests
{
[Fact]
public void WritesStableCsvSchemaAndFrameWorkload()
{
string path = System.IO.Path.Combine(System.IO.Path.GetTempPath(),
$"age-perf-{Guid.NewGuid():N}.csv");
try
{
using (var log = new PerformanceFrameLog(path))
{
log.BeginFrame(17, 1234, 1.0 / 60.0, "SC0000.BIN", 0x2a91, 0x20c);
log.BeginRecomposite(false);
log.RecordPresentationReasons(1 | 4 | 16);
log.RecordRecomposeAllocation(4096);
log.RecordSnapshotAllocation(512);
log.RecordCompositeAllocation(2048);
log.RecordSourcePrepAllocation(128);
log.RecordSetDataAllocation(1024);
log.RecordUiAllocation(64);
log.RecordPresentationCoordinate("SC0000.BIN", 0x2aaa, 0x21c);
log.RecordObject(timeVarying: true);
log.RecordRaster(800, 600, new Affine2D(1, 0, 0, 1, 0, 0),
800, 600, dynamic: false, BlendKind.Alpha, ticks: 10);
log.RecordFillLayer();
log.RecordSkippedLayer();
log.EndRecomposite();
log.EndFrame();
Assert.Equal(1, log.FrameCount);
Assert.Equal(1, log.RecompositeCount);
}
string[] lines = File.ReadAllLines(path);
Assert.Equal(2, lines.Length);
string[] header = lines[0].Split(',');
string[] row = lines[1].Split(',');
Assert.Equal(header.Length, row.Length);
Assert.Equal("frame", header[0]);
Assert.Equal("17", row[0]);
Assert.Equal("1", row[Array.IndexOf(header, "recomposited")]);
Assert.Equal("1", row[Array.IndexOf(header, "present_host_request")]);
Assert.Equal("1", row[Array.IndexOf(header, "present_retained_mutation")]);
Assert.Equal("1", row[Array.IndexOf(header, "present_discrete_cell")]);
Assert.Equal("0", row[Array.IndexOf(header, "present_continuous_channel")]);
Assert.Equal("4096", row[Array.IndexOf(header, "recompose_allocated_bytes")]);
Assert.Equal("512", row[Array.IndexOf(header, "snapshot_allocated_bytes")]);
Assert.Equal("2048", row[Array.IndexOf(header, "composite_allocated_bytes")]);
Assert.Equal("128", row[Array.IndexOf(header, "source_prep_allocated_bytes")]);
Assert.Equal("1024", row[Array.IndexOf(header, "set_data_allocated_bytes")]);
Assert.Equal("64", row[Array.IndexOf(header, "ui_allocated_bytes")]);
Assert.Equal("1", row[Array.IndexOf(header, "time_varying_objects")]);
Assert.Equal("480000", row[Array.IndexOf(header, "candidate_pixels")]);
Assert.Equal("SC0000.BIN", row[Array.IndexOf(header, "script")].Trim('"'));
Assert.Equal("10897", row[Array.IndexOf(header, "offset")]);
Assert.Equal("524", row[Array.IndexOf(header, "opcode")]);
Assert.Equal("10922", row[Array.IndexOf(header, "present_offset")]);
Assert.Equal("540", row[Array.IndexOf(header, "present_opcode")]);
}
finally
{
if (File.Exists(path)) File.Delete(path);
}
}
[Theory]
[InlineData(0, 0, 10, 10, 100)]
[InlineData(-5, -5, 10, 10, 25)]
[InlineData(95, 95, 10, 10, 25)]
[InlineData(200, 200, 10, 10, 0)]
public void CandidatePixelsClipsIntegerTranslations(int x, int y, int width, int height, long expected)
{
var transform = new Affine2D(1, 0, 0, 1, x, y);
Assert.True(PerformanceFrameLog.IsIntegerTranslation(transform));
Assert.Equal(expected,
PerformanceFrameLog.EstimateCandidatePixels(transform, width, height, 100, 100));
}
[Fact]
public void CandidatePixelsUsesAffineBoundingBoxAndDetectsNonIntegerPath()
{
var scaled = new Affine2D(2, 0, 0, 3, 1.5, 2.5);
Assert.False(PerformanceFrameLog.IsIntegerTranslation(scaled));
Assert.Equal(651,
PerformanceFrameLog.EstimateCandidatePixels(scaled, 10, 10, 100, 100));
}
[Fact]
public void RasterClassificationSeparatesTranslationScaleAndGeneralAffine()
{
Assert.True(PerformanceFrameLog.IsTranslation(new Affine2D(1, 0, 0, 1, 0.25, -0.5)));
Assert.False(PerformanceFrameLog.IsIntegerTranslation(new Affine2D(1, 0, 0, 1, 0.25, -0.5)));
Assert.True(PerformanceFrameLog.IsAxisAligned(new Affine2D(2, 0, 0, 3, 0, 0)));
Assert.False(PerformanceFrameLog.IsAxisAligned(new Affine2D(1, 0.25, 0, 1, 0, 0)));
}
}