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:
parent
38def07edb
commit
132395e6f7
11 changed files with 250 additions and 8 deletions
55
src/AcDream.App/Rendering/Packs/RenderPackResidentBudget.cs
Normal file
55
src/AcDream.App/Rendering/Packs/RenderPackResidentBudget.cs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
namespace AcDream.App.Rendering.Packs;
|
||||
|
||||
/// <summary>
|
||||
/// The one rule for a pack preset's effective resident-GPU ceiling.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// A preset's <c>MaxResidentGpuBytes</c> is the <b>1080p</b> figure of the
|
||||
/// Campaign AR budget table (Low 64 / Medium 128 / High 256 MiB). The pack's
|
||||
/// resident set is dominated by screen-sized images — the HDR world colour +
|
||||
/// depth targets alone are 12 bytes per pixel, plus the ray/bloom
|
||||
/// intermediates — so a ceiling that does not scale with pixel count refuses
|
||||
/// the pack the moment the user picks a larger mode: at 2560×1440 the Low
|
||||
/// preset's screen targets are 44 MB of a 64 MiB budget, and live Holtburg's
|
||||
/// scene-dependent shadow command buffers pushed the total to 64.25 MiB.
|
||||
/// That refusal is what the owner hit at the Campaign VM VM7 gate
|
||||
/// (2026-08-23, #425): Apply → "needs 67368164 resident GPU bytes; the
|
||||
/// active pack budget is 67108864" → persisted back to the default path.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The effective ceiling is therefore the declared 1080p figure scaled by
|
||||
/// the pixel-count ratio (never below 1, so smaller modes keep the declared
|
||||
/// ceiling), and still capped by the hardware's <c>MaxPackResidentBytes</c>.
|
||||
/// The parts of the resident set that do NOT scale with the screen (shadow
|
||||
/// depth maps, shadow command/transform buffers) are over-allowed by the same
|
||||
/// factor; that errs on the side of honouring the user's explicit resolution
|
||||
/// choice while keeping the bound proportional to what they asked the GPU to
|
||||
/// draw. <c>tools/run-atmospheric-performance-matrix.ps1</c> judges its
|
||||
/// resident column with this same rule so the tool and the runtime cannot
|
||||
/// disagree.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
internal static class RenderPackResidentBudget
|
||||
{
|
||||
internal const long ReferencePixels = 1920L * 1080L;
|
||||
|
||||
internal static long Effective(
|
||||
long declaredBytesAt1080p,
|
||||
int viewportWidth,
|
||||
int viewportHeight,
|
||||
long hardwareCapBytes)
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(declaredBytesAt1080p);
|
||||
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(viewportWidth);
|
||||
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(viewportHeight);
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(hardwareCapBytes);
|
||||
|
||||
long pixels = checked((long)viewportWidth * viewportHeight);
|
||||
long scaled = pixels <= ReferencePixels
|
||||
? declaredBytesAt1080p
|
||||
: checked((long)Math.Ceiling(
|
||||
(double)declaredBytesAt1080p * pixels / ReferencePixels));
|
||||
return Math.Min(scaled, hardwareCapBytes);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue