fix #425: pack resident budget is a 1080p ceiling that scales with pixel count; an explicit Apply retries a failed selection

Live Holtburg at 2560x1440: the Low preset needed 67,368,164 resident bytes
(screen-sized HDR/depth/ray targets are 44 MB of that) against an absolute
64 MiB ceiling that had only been validated at 1080p, so Options -> Apply
fell back to the default path; every later Apply was then refused by the
controller's failure memo, which treated the user's deliberate choice like
automatic re-activation.

RenderPackResidentBudget.Effective scales the declared 1080p figure by the
viewport's pixel-count ratio (never below 1), still capped by the hardware
MaxPackResidentBytes; both pack graphs use it and the performance-matrix
tool judges its resident column by the same rule (contract test updated).
RenderPackController.Request gains explicitUserChoice, which clears the
memo for that selection; RenderPackSelectionBinding passes it on every
display edge (Apply, including resolution changes) and keeps the memo for
the startup request.

Tests: RenderPackResidentBudgetTests (1080p/720p keep the declared
ceiling, 1440p = 16/9x, 4K = 4x, hardware cap wins, zero extent rejected);
controller explicit-retry; the binding test now proves the user's next
Apply activates once the cause is gone. App hermetic lane 6,068/0 (Release).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-23 10:00:11 +02:00
parent 38def07edb
commit 132395e6f7
11 changed files with 250 additions and 8 deletions

View file

@ -162,10 +162,20 @@ public sealed class AtmosphericPerformanceMatrixContractTests
"$cpuP99 -gt $budget.IncrementalCpuMillisecondsP99",
source,
StringComparison.Ordinal);
// #425: the declared resident ceiling is the 1080p figure and scales
// with the row's pixel count — the same rule as
// RenderPackResidentBudget.Effective, so the tool and the runtime
// cannot disagree about a 1440p/4K row.
Assert.Contains(
"$residentGpuBytes -gt $budget.ResidentGpuBytes",
"$residentGpuBytes -gt $residentCeiling",
source,
StringComparison.Ordinal);
Assert.Contains("$referencePixels = 1920L * 1080L", source, StringComparison.Ordinal);
Assert.Contains(
"[Math]::Ceiling([double]$budget.ResidentGpuBytes * $rowPixels / $referencePixels)",
source,
StringComparison.Ordinal);
Assert.Contains("$rowPixels -le $referencePixels", source, StringComparison.Ordinal);
Assert.Contains(
"$gpuP50 -gt $budget.InclusiveGpuMillisecondsP50At1080p",
source,