docs #477: bound first-failure reporting and extended reproduction

This commit is contained in:
Erik 2026-09-05 18:49:22 +02:00
parent cd888a4932
commit c8ec04e97d
2 changed files with 525 additions and 0 deletions

View file

@ -0,0 +1,87 @@
# #477 — preserve the first swapchain failure
2026-09-05. Base `cd888a493`. Bounded diagnostic/error-propagation repair,
not a repair claim for the AMD reset. FPS remains deferred; G4 remains FAIL.
## Evidence and boundary
`477-cathedral-recurrence.md` records the owner's approximately 16-minute
cathedral session ending in device loss at an abandoned-frame timeline submit.
At this base, `VulkanSwapchain.TryAcquire` discards the original VkResult after
`OnAcquire` classifies it. `SwapchainBackbuffer.TryAcquire` maps Fail to false;
`VulkanGpuDevice.TryBeginFrame` consequently attempts an empty timeline submit.
`VulkanSwapchain.Present` likewise discards fatal results into a Fail action
that its adapter maps to false (recreation). This hides the first failing API.
The already-existing `VulkanCallException` retains operation and exact Result.
The already-existing policy distinguishes normal unavailable/recreation cases
from Fail. Preserve that distinction at the actual native-call boundaries.
Primary API references inspected by the lead on 2026-09-05:
[Khronos acquire](https://docs.vulkan.org/refpages/latest/refpages/source/vkAcquireNextImageKHR.html)
and [Khronos present](https://docs.vulkan.org/refpages/latest/refpages/source/vkQueuePresentKHR.html).
Acquire can return Success, Suboptimal, Timeout, NotReady, OutOfDate, and fatal
results including DeviceLost. Present likewise distinguishes usable/recreation
results from fatal ones. The existing policy is retained, not redesigned.
There is no retail Vulkan counterpart: this changes backend error reporting,
not any AC-specific decision, membership, drawing, or accepted-frame behavior.
## Implementation contract
Allowed production file: `src/AcDream.App/Rendering/Gpu/Vk/VulkanSwapchain.cs`.
Allowed tests: new `tests/AcDream.App.Tests/Rendering/Gpu/Vk/VulkanSwapchainFailureTests.cs`
and, only if needed, existing `VulkanSwapchainConfigurationTests.cs` beside it.
Lead owns this contract, verification, register decision, and ledgers.
After each native acquire/present call, classify using the existing policy.
If the action is Fail, throw the existing VulkanCallException with the original
Result and operation `vkAcquireNextImageKHR` or `vkQueuePresentKHR`. Otherwise
return the unchanged action. Do not apply the success-only Check indiscriminately
to Suboptimal/Timeout/NotReady/OutOfDate. The uncreated-swapchain path remains
RecreateNow without invoking native acquire. Update the obsolete untested class
comment only to the actual coverage now provided.
No changes to frame serial retirement, teardown, exception suppression,
recovery/retry policy, synchronization, shaders, pacing, native settings,
graphics quality, package, or scene behavior. No new logging toggle/framework,
new exception type, diagnostic owner, interface, or production test hook.
## Verification required
Use the existing test-side INativeContext/UnmanagedCallersOnly pattern to call
the real VulkanSwapchain methods with controlled native results. Tests must
prove the actual production boundaries (not just a copied classification):
1. Acquire DeviceLost and another fatal result throw with exact operation and
Result; present does the same. Include an unknown negative error as a guard
against silently weakening the policy's default fatal path.
2. Acquire Success/Suboptimal/Timeout/NotReady/OutOfDate return the unchanged
actions; present Success/Suboptimal/OutOfDate likewise. Successful acquire
preserves its native image index. No invented assertion on failed-call index.
3. An uncreated swapchain returns RecreateNow without calling native acquire.
4. Restore old acquire/present result handling separately using apply_patch;
the respective fatal tests must fail. Restore the fix and rerun green.
Keep TRXs/logs under artifacts/477-first-failure; no retry laundering.
5. Release build 0 errors, focused tests including existing configuration,
frame-flight, acquisition, synchronization and capture-validity classes.
No build or test while either graphical client is running.
The lead independently checks call flow through the unchanged adapters and
frame loop, runs the integrated Release lane, and checks the bounded diff.
One independent production/API review; retail port review is inapplicable to
this backend-only change. No intentional retail deviation is introduced; if
implementation exceeds that statement, stop for a contract/register decision.
## Follow-on test and stop rules
After review and green build, run a longer non-validation cathedral/Neftet
reproduction, retaining exact binary/configuration/process/evidence identities.
Automation is not the identical owner session; state that limitation. A clean
run does not prove the driver's initiating fault fixed. Record PNG PASS/FAIL
provisionally and close only our test client gracefully. No simultaneous client,
build/test, unbounded stress, force kill, or main merge.
Implementer returns without committing or launching clients. Build red twice,
contract ambiguity, any need for an additional production file, or third fix
round stops the chunk and is reported. Independent tests and raw failures are
required before a diagnostic PASS; #477 stability remains separately open.

View file

@ -0,0 +1,438 @@
# #477 extended non-validation reproduction, not a performance or exact owner-session gate.
# Approximately 21 minutes of dwell plus movement/loading; explicit terminal graceful close.
# Owner crash trajectory is unknown. Scripted workload does not prove its exact reproduction.
# High/MSAA4, 1280x720, recipe10. Every held input is balanced.
wait world-ready 180000
wait world-visible 300000
resize 1280 720
wait framebuffer 1280 720 30000
renderpack select high
wait render-pack high 90000
sleep 5000
checkpoint 477_long_00_login
screenshot 477-long-00-login 15000
# Phase 1: cathedral_hall
command /teleloc F4180104 36.9 48.7 169.805 1 0 0 0
wait materialized 1 180000
wait world-visible 300000
sleep 5000
checkpoint 477_long_1_arrival
screenshot 477-long-1-arrival 15000
# Minute 1
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
input press CombatToggleCombat
sleep 1000
sleep 30000
sleep 30000
checkpoint 477_long_1_minute_1
# Minute 2
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
sleep 30000
sleep 30000
checkpoint 477_long_1_minute_2
# Minute 3
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
sleep 30000
sleep 30000
checkpoint 477_long_1_minute_3
# Minute 4
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
sleep 30000
sleep 30000
checkpoint 477_long_1_minute_4
# Minute 5
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
sleep 30000
sleep 30000
checkpoint 477_long_1_minute_5
# Minute 6
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
input press CombatToggleCombat
sleep 1000
sleep 30000
sleep 30000
checkpoint 477_long_1_minute_6
screenshot 477-long-1-settled 15000
# Phase 2: cathedral_stairwell
command /teleloc F4180113 39.502899 19.832422 180.976700 1 0 0 0
wait materialized 2 180000
wait world-visible 300000
sleep 5000
checkpoint 477_long_2_arrival
screenshot 477-long-2-arrival 15000
# Minute 1
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
input press CombatToggleCombat
sleep 1000
sleep 30000
sleep 30000
checkpoint 477_long_2_minute_1
# Minute 2
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
sleep 30000
sleep 30000
checkpoint 477_long_2_minute_2
# Minute 3
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
sleep 30000
sleep 30000
checkpoint 477_long_2_minute_3
# Minute 4
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
sleep 30000
sleep 30000
checkpoint 477_long_2_minute_4
# Minute 5
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
sleep 30000
sleep 30000
checkpoint 477_long_2_minute_5
# Minute 6
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
input press CombatToggleCombat
sleep 1000
sleep 30000
sleep 30000
checkpoint 477_long_2_minute_6
screenshot 477-long-2-settled 15000
# Phase 3: cathedral_return
command /teleloc F4180104 36.9 48.7 169.805 1 0 0 0
wait materialized 3 180000
wait world-visible 300000
sleep 5000
checkpoint 477_long_3_arrival
screenshot 477-long-3-arrival 15000
# Minute 1
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
input press CombatToggleCombat
sleep 1000
sleep 30000
sleep 30000
checkpoint 477_long_3_minute_1
# Minute 2
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
sleep 30000
sleep 30000
checkpoint 477_long_3_minute_2
# Minute 3
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
sleep 30000
sleep 30000
checkpoint 477_long_3_minute_3
# Minute 4
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
sleep 30000
sleep 30000
checkpoint 477_long_3_minute_4
# Minute 5
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
sleep 30000
sleep 30000
checkpoint 477_long_3_minute_5
# Minute 6
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
input press CombatToggleCombat
sleep 1000
sleep 30000
sleep 30000
checkpoint 477_long_3_minute_6
screenshot 477-long-3-settled 15000
# Phase 4: neftet
command /teleloc 8763000E 40.4574 129.281 8.004999 1 0 0 0
wait materialized 4 180000
wait world-visible 300000
sleep 5000
checkpoint 477_long_4_arrival
screenshot 477-long-4-arrival 15000
# Minute 1
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
input down MovementJump
sleep 350
input up MovementJump
sleep 2500
input press CombatToggleCombat
sleep 1000
sleep 30000
sleep 30000
checkpoint 477_long_4_minute_1
# Minute 2
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
input down MovementJump
sleep 350
input up MovementJump
sleep 2500
sleep 30000
sleep 30000
checkpoint 477_long_4_minute_2
# Minute 3
input down MovementTurnRight
sleep 500
input up MovementTurnRight
input down MovementForward
sleep 200
input up MovementForward
sleep 1000
input down MovementBackup
sleep 200
input up MovementBackup
input down CameraRotateRight
sleep 300
input up CameraRotateRight
input down MovementJump
sleep 350
input up MovementJump
sleep 2500
input press CombatToggleCombat
sleep 1000
sleep 30000
sleep 30000
checkpoint 477_long_4_minute_3
screenshot 477-long-4-settled 15000
checkpoint 477_long_complete
close-client