mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 12:00:44 +00:00
Split mover budgets for on-screen and off-screen passes
This commit is contained in:
@@ -1308,8 +1308,8 @@ export class PerformanceOverlay extends LitElement implements Layer {
|
||||
<div class="performance-line">
|
||||
tracked: ${Number(unitLayerCounters.moversTrackedTotal ?? 0)}
|
||||
sampled: ${Number(unitLayerCounters.moversSampled ?? 0)}
|
||||
drawn: ${Number(unitLayerCounters.moversDrawn ?? 0)} skipped:
|
||||
${Number(unitLayerCounters.moversSkipped ?? 0)}
|
||||
drawn: ${Number(unitLayerCounters.moversDrawn ?? 0)}
|
||||
skipped: ${Number(unitLayerCounters.moversSkipped ?? 0)}
|
||||
</div>
|
||||
<div class="performance-line">
|
||||
moverCanvasScale:
|
||||
@@ -1323,15 +1323,21 @@ export class PerformanceOverlay extends LitElement implements Layer {
|
||||
</div>
|
||||
<div class="performance-line">
|
||||
draw:
|
||||
${Number(unitLayerCounters.drawTimeMs ?? 0).toFixed(2)}ms /
|
||||
${Number(unitLayerCounters.budgetTargetMs ?? 0).toFixed(1)}ms
|
||||
(+${Number(
|
||||
unitLayerCounters.budgetSoftOverrunMs ?? 0,
|
||||
).toFixed(1)}ms
|
||||
on-screen) avgOnDebt:
|
||||
${Number(unitLayerCounters.avgOnScreenDebt ?? 0).toFixed(2)}
|
||||
maxOnDebt:
|
||||
${Number(unitLayerCounters.maxOnScreenDebt ?? 0).toFixed(0)}
|
||||
${Number(unitLayerCounters.drawTimeMs ?? 0).toFixed(2)}ms
|
||||
</div>
|
||||
<div class="performance-line">
|
||||
on:
|
||||
${Number(unitLayerCounters.onScreenDrawTimeMs ?? 0).toFixed(2)}ms
|
||||
/
|
||||
${Number(unitLayerCounters.onScreenBudgetTargetMs ?? 0).toFixed(1)}ms
|
||||
off:
|
||||
${Number(unitLayerCounters.offScreenVerifyTimeMs ?? 0).toFixed(2)}ms
|
||||
/
|
||||
${Number(unitLayerCounters.offScreenVerifyBudgetMs ?? 0).toFixed(2)}ms
|
||||
</div>
|
||||
<div class="performance-line">
|
||||
avgOnDebt: ${Number(unitLayerCounters.avgOnScreenDebt ?? 0).toFixed(2)}
|
||||
maxOnDebt: ${Number(unitLayerCounters.maxOnScreenDebt ?? 0).toFixed(0)}
|
||||
</div>
|
||||
</div>`
|
||||
: html``}
|
||||
|
||||
@@ -40,11 +40,10 @@ enum Relationship {
|
||||
Enemy,
|
||||
}
|
||||
|
||||
const UNIT_DRAW_BUDGET_MS = 2;
|
||||
const UNIT_DRAW_SOFT_OVERRUN_MS = 1;
|
||||
const OFFSCREEN_REFRESH_EVERY_N_FRAMES = 60;
|
||||
const ONSCREEN_DRAW_BUDGET_MS = 2;
|
||||
const OFFSCREEN_VERIFY_BUDGET_MS = 0.1;
|
||||
const OFFSCREEN_REFRESH_EVERY_N_FRAMES = 30;
|
||||
const ONSCREEN_HYSTERESIS_FRAMES = 2;
|
||||
const OFFSCREEN_VERIFY_MAX_PER_FRAME = 12;
|
||||
const VIEW_PADDING_PX = 12;
|
||||
const MOVER_SPATIAL_HASH_CELL_PX = 24;
|
||||
const DYNAMIC_MOVER_SCALE_STEPS = [1, 2, 3, 4];
|
||||
@@ -157,8 +156,10 @@ export class UnitLayer implements Layer {
|
||||
moversDrawn: 0,
|
||||
moversSkipped: 0,
|
||||
drawTimeMs: 0,
|
||||
budgetTargetMs: UNIT_DRAW_BUDGET_MS,
|
||||
budgetSoftOverrunMs: UNIT_DRAW_SOFT_OVERRUN_MS,
|
||||
onScreenDrawTimeMs: 0,
|
||||
offScreenVerifyTimeMs: 0,
|
||||
onScreenBudgetTargetMs: ONSCREEN_DRAW_BUDGET_MS,
|
||||
offScreenVerifyBudgetMs: OFFSCREEN_VERIFY_BUDGET_MS,
|
||||
avgOnScreenDebt: 0,
|
||||
maxOnScreenDebt: 0,
|
||||
moverCanvasScale: 1,
|
||||
@@ -580,8 +581,10 @@ export class UnitLayer implements Layer {
|
||||
moversDrawn: moverPerf.drawn,
|
||||
moversSkipped: moverPerf.skipped,
|
||||
drawTimeMs: moverPerf.budgetUsedMs,
|
||||
budgetTargetMs: UNIT_DRAW_BUDGET_MS,
|
||||
budgetSoftOverrunMs: UNIT_DRAW_SOFT_OVERRUN_MS,
|
||||
onScreenDrawTimeMs: moverPerf.onScreenBudgetUsedMs,
|
||||
offScreenVerifyTimeMs: moverPerf.offScreenBudgetUsedMs,
|
||||
onScreenBudgetTargetMs: ONSCREEN_DRAW_BUDGET_MS,
|
||||
offScreenVerifyBudgetMs: OFFSCREEN_VERIFY_BUDGET_MS,
|
||||
avgOnScreenDebt:
|
||||
onScreenDebtCount > 0 ? totalOnScreenDebt / onScreenDebtCount : 0,
|
||||
maxOnScreenDebt,
|
||||
@@ -605,6 +608,8 @@ export class UnitLayer implements Layer {
|
||||
drawn: number;
|
||||
skipped: number;
|
||||
budgetUsedMs: number;
|
||||
onScreenBudgetUsedMs: number;
|
||||
offScreenBudgetUsedMs: number;
|
||||
} {
|
||||
const frameStartMs = performance.now();
|
||||
const drawnIds = new Set<number>();
|
||||
@@ -620,9 +625,9 @@ export class UnitLayer implements Layer {
|
||||
tickFloat,
|
||||
activeMoverIds,
|
||||
drawnIds,
|
||||
frameStartMs,
|
||||
performance.now(),
|
||||
ONSCREEN_DRAW_BUDGET_MS,
|
||||
viewBounds,
|
||||
Number.MAX_SAFE_INTEGER,
|
||||
sampledCache,
|
||||
spatial,
|
||||
);
|
||||
@@ -630,27 +635,28 @@ export class UnitLayer implements Layer {
|
||||
drawn += onScreenPass.drawn;
|
||||
skipped += onScreenPass.skipped;
|
||||
|
||||
const budgetExceeded = !onScreenPass.budgetRemaining;
|
||||
const shouldVerifyOffscreen =
|
||||
!budgetExceeded &&
|
||||
this.offScreenMoverIds.length > 0 &&
|
||||
this.renderFrame % OFFSCREEN_REFRESH_EVERY_N_FRAMES === 0;
|
||||
|
||||
let offScreenBudgetUsedMs = 0;
|
||||
|
||||
if (shouldVerifyOffscreen) {
|
||||
const offscreenPass = this.drawBucketPass(
|
||||
"off",
|
||||
tickFloat,
|
||||
activeMoverIds,
|
||||
drawnIds,
|
||||
frameStartMs,
|
||||
performance.now(),
|
||||
OFFSCREEN_VERIFY_BUDGET_MS,
|
||||
viewBounds,
|
||||
OFFSCREEN_VERIFY_MAX_PER_FRAME,
|
||||
sampledCache,
|
||||
spatial,
|
||||
);
|
||||
sampled += offscreenPass.sampled;
|
||||
drawn += offscreenPass.drawn;
|
||||
skipped += offscreenPass.skipped;
|
||||
offScreenBudgetUsedMs = offscreenPass.budgetUsedMs;
|
||||
}
|
||||
|
||||
for (const unitId of activeMoverIds) {
|
||||
@@ -668,6 +674,8 @@ export class UnitLayer implements Layer {
|
||||
drawn,
|
||||
skipped,
|
||||
budgetUsedMs: performance.now() - frameStartMs,
|
||||
onScreenBudgetUsedMs: onScreenPass.budgetUsedMs,
|
||||
offScreenBudgetUsedMs,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -676,9 +684,9 @@ export class UnitLayer implements Layer {
|
||||
tickFloat: number,
|
||||
activeMoverIds: Set<number>,
|
||||
drawnIds: Set<number>,
|
||||
frameStartMs: number,
|
||||
passStartMs: number,
|
||||
budgetMs: number,
|
||||
viewBounds: { left: number; top: number; right: number; bottom: number },
|
||||
maxItems: number,
|
||||
sampledCache: Map<number, MoverRenderSample | null>,
|
||||
spatial: MoverSpatialIndex,
|
||||
): {
|
||||
@@ -686,16 +694,22 @@ export class UnitLayer implements Layer {
|
||||
drawn: number;
|
||||
skipped: number;
|
||||
budgetRemaining: boolean;
|
||||
budgetUsedMs: number;
|
||||
} {
|
||||
const bucketIds =
|
||||
bucket === "on" ? this.onScreenMoverIds : this.offScreenMoverIds;
|
||||
if (bucketIds.length === 0 || maxItems <= 0) {
|
||||
return { sampled: 0, drawn: 0, skipped: 0, budgetRemaining: true };
|
||||
if (bucketIds.length === 0 || budgetMs <= 0) {
|
||||
return {
|
||||
sampled: 0,
|
||||
drawn: 0,
|
||||
skipped: 0,
|
||||
budgetRemaining: true,
|
||||
budgetUsedMs: 0,
|
||||
};
|
||||
}
|
||||
|
||||
const startCursor =
|
||||
bucket === "on" ? this.onScreenCursor : this.offScreenCursor;
|
||||
const cap = Math.min(bucketIds.length, maxItems);
|
||||
|
||||
let sampled = 0;
|
||||
let drawn = 0;
|
||||
@@ -704,7 +718,7 @@ export class UnitLayer implements Layer {
|
||||
const processed = new Set<number>();
|
||||
let scanned = 0;
|
||||
|
||||
for (let offset = 0; offset < cap; offset++) {
|
||||
for (let offset = 0; offset < bucketIds.length; offset++) {
|
||||
if (bucketIds.length === 0) {
|
||||
break;
|
||||
}
|
||||
@@ -715,12 +729,8 @@ export class UnitLayer implements Layer {
|
||||
continue;
|
||||
}
|
||||
|
||||
const elapsedMs = performance.now() - frameStartMs;
|
||||
const canDrawWithinTarget = elapsedMs < UNIT_DRAW_BUDGET_MS;
|
||||
const canDrawOnScreenOverrun =
|
||||
bucket === "on" &&
|
||||
elapsedMs < UNIT_DRAW_BUDGET_MS + UNIT_DRAW_SOFT_OVERRUN_MS;
|
||||
if (!canDrawWithinTarget && !canDrawOnScreenOverrun) {
|
||||
const elapsedMs = performance.now() - passStartMs;
|
||||
if (elapsedMs >= budgetMs) {
|
||||
budgetRemaining = false;
|
||||
skipped++;
|
||||
break;
|
||||
@@ -834,7 +844,13 @@ export class UnitLayer implements Layer {
|
||||
: 0;
|
||||
}
|
||||
|
||||
return { sampled, drawn, skipped, budgetRemaining };
|
||||
return {
|
||||
sampled,
|
||||
drawn,
|
||||
skipped,
|
||||
budgetRemaining,
|
||||
budgetUsedMs: performance.now() - passStartMs,
|
||||
};
|
||||
}
|
||||
|
||||
private buildMoverSpatialHash(): MoverSpatialIndex {
|
||||
|
||||
Reference in New Issue
Block a user